Bypass all resource restrictions, passwords, and keys? Read here!
Decryption key:
ACPT - Custom post Types Plugin for Wordpress v2.1.3 Nulled
## [2.1.3] - 2026-10-06
### Added
- **Collapsible sidebar in the field builders** - the sidebar of every canvas builder (meta fields, forms, custom table columns, dynamic blocks, option pages, WooCommerce product data) can be hidden to a thin strip, from a toolbar button or by dragging its edge, giving the fields the full width on small screens. The choice is remembered per item, and clicking a field reopens the sidebar with its settings.
### Fixed
#### Admin
- **Forms stopped sending email with plugins that replace `wp_mail()`** - since 2.1.0 ACPT loaded WordPress' pluggable functions while plugins were still loading, so plugins that override `wp_mail()` (e.g. ActiveCampaign Postmark) could no longer do it and form emails were lost (Ticket #1377).
- **Updating installed the previous version** - after a release WordPress showed the new version but installed the previous zip, served from a cache. The update package URL now includes the version, so every release gets its own download (Tickets #1354, #1370).
#### Custom tables
- **The admin crashed when two tables had foreign keys pointing at each other** - loading the tables recursed until PHP ran out of memory on every admin page, locking users out of wp-admin. Tables referencing each other, in a pair or a longer chain, now load normally (Ticket #1372).
#### Meta fields
- **JSON in a Textarea field still lost characters with "Allow HTML" off** - spaces and line breaks at the start and end of every JSON string were removed, so values made only of line breaks (common in Etch and Gutenberg exports) were saved empty. The JSON is now saved exactly as typed (Ticket #1370).
- **A Relationship value read with `get_acpt_field()` couldn't be saved back** - it returns the related posts, users or terms as objects, and passing them to `save_acpt_meta_field_value()` failed with a PHP error, so nothing was saved. Objects are now saved as their IDs, and removing an item with `unset()` works too (Ticket #1371).
#### Dynamic blocks
- **HTML and line breaks were stripped from a block's Callback and CSS on save** - the Twig template lost every tag and was compressed to one line, and the CSS was flattened. Both are now saved as typed; users without the `unfiltered_html` capability (e.g. multisite site admins) get post-safe HTML in the Callback and tag-free CSS (Ticket #1378).
#### Field builders on small screens
- **Narrow field cards overflowed their border** - a field at 50% width, or inside a repeater, pushed its switches and type badge outside the card. Cards now adapt to their real width, hiding the inline switches and then the type badge when there's no room; both stay available in the sidebar (Ticket #1376).
- **The sidebar width followed the screen as a percentage** - a sidebar made wider on a large monitor took more than half of the builder on a laptop. Its width is now kept in pixels and capped to half of the builder when the page loads (found while auditing Ticket #1376).
- **Box and block header icons could fall outside the box**, the toolbar's "Sidebar on the right" button was cut off at 1024px, and field names were truncated after 10 characters even when there was room. Headers keep their icons inside, the toolbar switches to compact icons on narrow builders, and names use the available width with the full name on hover (found while auditing Ticket #1376).
#### Bricks
- **Toggle fields never matched in element conditions on non-English sites** - a Toggle was rendered as the translated "True"/"False" (e.g. "Wahr"/"Falsch"), which Bricks conditions don't treat as yes/no, so `{acpt_...} == 1` never matched. Toggles now return `1`/`0` inside element conditions and with the `:value` argument (Ticket #1375).
Decryption key:
ACPT - Custom post Types Plugin for Wordpress v2.1.2 Nulled
### Fixed
#### Meta fields
- **Editor fields inside Repeaters lost all formatting on save** - since 2.1.0 every sub-field of a Repeater or Flexible Content field was sanitized as plain text, so saving the post stripped the HTML tags and line breaks from Editor sub-fields (and line breaks from Textarea sub-fields). Each sub-field is now sanitized according to its own type; Editor sub-fields keep post-safe HTML (Ticket #1361).
- **Select dropdowns were clipped below 1200px window width** - the responsive meta-field layout set `overflow: hidden`, which cut off the Selectize popup and made arrow-key navigation look unresponsive. Only horizontal overflow is clipped now (Ticket #1360).
- **A saved `0` showed as empty in the admin** - since 2.1.1 a required Number field accepts and saves `0`, but on reload the edit screen showed the input empty (Currency, Weight and Length too), because the escaping helper treated `"0"` as empty. A stored `0` is now shown, and a `0` min/max on the admin Number field is respected (Ticket #1354).
- **Blank Number, Currency, Weight and Length fields were saved as `0`** - leaving the amount empty stored `0`, so the front end showed `0` / `0.00 EUR` instead of nothing. A blank amount now stays blank; an explicit `0` is still saved as `0` (found while investigating Ticket #1355).
- **Time field values came back empty** when saved in a format other than the site's time format (e.g. `10:00` on a site using `g:i a`), which is what the admin time picker saves when the field's display format differs. `get_acpt_field()`, shortcodes and page builder tags returned nothing, including for Time fields inside repeaters. Any supported time format is now accepted (Ticket #1352).
- **Bulk Edit wiped ACPT fields** - WordPress' Bulk Edit panel submitted every ACPT quick-edit input, including the ones left blank, so any bulk edit (even just enabling comments) emptied those fields on every selected post. Blank Bulk Edit inputs now mean "no change", as they do for WordPress' own fields; this also applies to Custom table columns (Ticket #1369).
- **JSON saved in a Textarea field was altered** - `%20`-style sequences and tags inside JSON strings were stripped, and with "Allow HTML" enabled the JSON was saved with backslash-escaped quotes and `&`, `<`, `>` encoded, so it was no longer valid JSON. JSON is now kept as typed; tags inside it follow the field's "Allow HTML" setting (Ticket #1370).
- **The unit of a blank Currency, Weight or Length field was replaced** - when the amount was empty, the edit screen preselected the field's default unit instead of the saved one, so saving the post again overwrote it (Ticket #1355).
#### Admin
- **List pagination crashed with "Unexpected Application Error! 404 Not Found"** - page 2 and later of the Meta Keys Manager, Datasets and WooCommerce product data lists had no matching route, and the Custom Tables list linked its pages to a non-existent `/tables` path. All four now paginate (Ticket #1363).
- **Fatal error with plugins that run the main query early in wp-admin** - a custom login URL plugin rendering its 404 page during an admin request triggered `Call to undefined function get_current_screen()` in the admin columns code, white-screening the site (Ticket #1368).
#### Custom tables
- **Advanced column settings were lost on save** - on a column saved without any advanced settings, later changes to them (width, before/after text, CSS class, min/max, pattern, ...) were silently dropped on every save, because the empty settings were returned as a JSON array instead of an object (found while investigating Ticket #1363).
- **Tables with UNSIGNED or ZEROFILL columns could not be created or synced** - the generated SQL put `UNSIGNED`/`ZEROFILL` after `NOT NULL` (and, when syncing an existing table, after `DEFAULT`/`COMMENT` too), e.g. `BIGINT NOT NULL UNSIGNED`, which MySQL and MariaDB reject as a syntax error. Syncing a column with a text default also produced an unterminated `DEFAULT 'value`. Both are fixed (Ticket #1367).
- **A column default of `0` was dropped, and decimal defaults were truncated** - `0` was treated as "no default" when creating or syncing a table (so `DEFAULT 0` never reached the database), a default like `1.5` was synced as `1`, and a DECIMAL default such as `1` kept showing the table as not synced because the server reports it as `1.00` (found while fixing Ticket #1367).
- **No way to set a Currency column's default currency** - the record form always preselected USD. Currency columns now have a "Default currency" setting (Ticket #1362). Saved advanced settings are also shown again when a column is reopened.
- **Duplicating a column only kept its type** - the copy got the column type but none of the settings changed in the sidebar (length, nullable, default value, advanced settings, ...). The duplicate now copies them, with a new name and id; the primary key flag, index/foreign key links and the inverse side of a bidirectional relation are not copied (Ticket #1363).
#### Bricks
- **Text field tags rendered empty in link settings** - an ACPT Text field used as the only content of a Bricks link setting (e.g. an Icon element's custom URL) returned nothing, because Text fields weren't registered for Bricks' `link` context. They now resolve to the bare URL, without the field's before/after text (Ticket #1356).
- **Date and Time tags printed the "before" text twice and never the "after" text** (found while fixing Ticket #1352).
#### Forms
- **Front-end form Number fields still rejected `0`** - with no limits configured they were rendered with `min="1" max="100"`, so the browser refused `0` (and anything above 100) even after the 2.1.1 fix, and a minimum set to `0` was ignored. Number fields now have no limits unless configured, and a `0` limit is respected (Ticket #1354, follow-up of #1338).
- **Currency, Weight and Length fields rejected `0`** - in both front-end forms and the admin, their amount input defaulted to a minimum of `0.01` (Currency) or `1` (admin Weight/Length), and a minimum set to `0` was ignored. They now have no minimum or maximum unless configured, and a `0` limit is respected (Ticket #1354).
#### Gutenberg
- **Block Bindings: ACPT fields missing from the Site Editor's Attributes panel** - the list of bindable fields was computed once and then cached, so switching templates in the Site Editor without a page reload kept the fields of whatever screen it was first computed on (often none, which hides the panel). The list now follows the template being edited. The list could also be computed before ACPT's fields had finished loading and then stay empty for that template even after a reload (more likely on sites with many field groups); it is now only built once the fields are loaded (Ticket #1357).
#### Divi 5
- **WYSIWYG (Editor) fields lost their formatting in ACPT Dynamic Data** - lists, bold text and other markup were stripped unless "Enable Raw HTML" was turned on. Editor fields now render their HTML (filtered to post-safe markup) by default, like the `[acpt]` shortcode and the legacy ACPT Meta Fields module (Ticket #1358).
Decryption key:
ACPT - Custom post Types Plugin for Wordpress v2.1.1 Nulled
# Changelog
## [2.1.1] - 2026-09-25
Bug-fix release for issues reported after 2.1.0.
### Fixed
#### Meta fields
- **Saving a field group failed with "`Value` key is mandatory"** - a field option row without a value (e.g. a stale row reaching an Image field) aborted the whole group save. Such rows are now skipped, and a row with a label but no value falls back to its label (Ticket #1349).
- **Saving an "All users" / "All comments" location rule fataled** - the empty `find` the UI submits for these rule types is now normalised instead of throwing (Ticket #1339).
- **Currency / Weight / Length fields fataled the post editor** when a default unit was set without a default amount (`explode(): Argument #2 must be of type string, array given`) (Ticket #1346).
- **Required fields rejected `0`** - a required Number field set to `0` failed with "Expected a non-empty value" in the admin and "The field is required" on front-end forms (Ticket #1338).
- **Field groups did not show on taxonomies registered by other plugins** (e.g. WooCommerce Product categories) - they could be selected as a location but never rendered or saved (Ticket #1337).
- **Link fields without link text returned a plain URL string** instead of the `{url, label}` array 2.0.x returned, so they rendered empty in Elementor Pro, Bricks, Divi, Oxygen, Yoast, WP Grid Builder and Zion, and an Elementor Pro display condition on them fataled (Ticket #1341).
#### Option pages
- **Repeater "Add element" did nothing on option pages** - the AJAX row generation fataled with a `Strings::toDBFormat()` TypeError, affecting every repeater on an option page (Ticket #1333).
#### Forms
- **Form submissions bypassed ACPT permissions** - field- and column-level permissions are now enforced on submission, and forms writing CCT records require the table's create/update permission (Ticket #1345).
#### Gutenberg
- **ACPT blocks rendered empty on the front end** - the Basic, Repeater and Relational field blocks and all Dynamic Blocks were registered only in editor contexts, so on the front end WordPress never called their render callback (Ticket #1348).
- **Basic Fields block showed "Error loading block: [object Object]"** in the Site Editor for fields with large settings - the preview request exceeded the server URL limit; it is now sent via POST (Ticket #1322).
#### Integrations
- **SEOPress: pages crashed when an ACPT field rendered empty or `0`** - the SEOPress integration returned `null` from a string-typed method whenever a field value rendered to an empty string or `0`, a fatal error on every page where SEOPress builds its dynamic variables (single posts, archives, and the Breakdance builder preview). It now returns an empty string (Ticket #1335).
- **Breakdance/Oxygen 6 native Repeater Field element could white-screen** - `ACPTRepeaterField::hasSubFields()` left an internal value undefined when a repeater's meta group belonged to something other than a post type, taxonomy, or option page, instead of resolving cleanly to "no rows"; `ACPTField::getValue()` and `RawValueConverter::convert()` also only guarded against `\Exception`, not every PHP error type, and Breakdance's own dynamic-data render chain has no error handling of its own, so any uncaught error here white-screened the whole page.
#### REST API
- **`PUT /acpt/v1/meta/{id}` rejected the unchanged output of `GET`** - read-only keys returned by GET are now accepted, missing settings (group display/context/priority, box settings) were added to the schema, and updating a field keeps its position (Ticket #1347).
#### Miscellaneous
- **Address map never loaded when another ACPT script was on the page** - seven static scripts overwrote each other's `window.onload`; they now use `addEventListener('load', ...)` (Ticket #1344).
- **Caught errors re-crashed the page when ACPT logging was enabled** - the `acpt/error` logger only accepted `\Exception`, so an `\Error` caught by ACPT's own safety nets (Breakdance, field-group visibility, location rules...) threw a new fatal from inside the logger. It now accepts any `\Throwable`.
- **PHP 8.4 deprecation notices** - `OptionPageModel::duplicate()` and `MetaBoxModel::__construct()` implicitly marked a typed parameter as nullable via a `null` default instead of an explicit `?type`, both deprecated as of PHP 8.4.
Decryption key:
ACPT - Custom post Types Plugin for Wordpress v2.1.0 Nulled
## [2.1.0] - 2026-09-21
2.1.0 is a major feature release. It introduces **Custom Content Types** (your own MySQL tables, fully independent of `wp_postmeta`), the unified **Canvas UI** drag-and-drop builder, the **Meta Keys Manager**, WordPress-native **Block Bindings**, and a complete **Abilities API** (57 MCP-exposed operations), and completes the **WCAG 2.1 AA** accessibility roadmap for the React admin UI - alongside several hundred bug fixes accumulated across the 2.1.0-beta cycle and this release's pre-ship regression pass. It consolidates the 2.1.0-beta-1 through 2.1.0-beta-6 pre-releases into a single stable entry.
### Added
#### Custom Content Types (CCT)
- **Custom Content Types** - create and manage fully custom MySQL (InnoDB) tables directly from the ACPT admin, each with its own schema, auto-generated record manager, and optional REST API, completely independent from `wp_postmeta`. Opt-in via ACPT → Settings → Content settings.
- **Table Groups** - link one or more CCT tables to WordPress contexts (post types, taxonomies, users, option pages) via configurable location rules, with four display modes: Standard, Accordion, Vertical Tabs, Horizontal Tabs.
- **30+ column types** - `VARCHAR`, `TEXT`, `LONGTEXT`, `BIGINT`, `DECIMAL`, `DATE`, `DATETIME`, `TIME`, `TINYINT(1)`, `JSON`, `BLOB`, plus VIRTUAL pseudo-types for Repeater and Flexible block columns. Each maps to a generated admin input and a typed REST property.
- **Repeater and Flexible block columns** - nestable column types stored as JSON.
- **Relational columns** - link a record to another CCT table, a post, a term, a user, or an option page, with optional bidirectional sync.
- **Foreign keys** - database-level `FOREIGN KEY` constraints with configurable `ON DELETE` / `ON UPDATE` (`CASCADE`, `SET NULL`, `RESTRICT`, `NO ACTION`).
- **Database indexes** - `INDEX`, `UNIQUE`, `FULLTEXT`, `SPATIAL` on any column or combination.
- **Custom primary keys** - designate any column as the primary key, with optional `AUTO_INCREMENT`; or use the implicit `AUTO_INCREMENT` / `UUID v4` / `ULID` id column (Ticket #1166).
- **Timestamps and soft delete** - opt-in `created_at` / `updated_at` and a `deleted_at` soft-delete column, with an All/Trash records view (per-row and bulk Restore / Delete Permanently / Empty Trash).
- **Schema sync** - ACPT creates and migrates the physical table on save; the table list shows a per-row schema-status indicator and a one-click sync.
- **CCT REST API** - per-table CRUD at `/wp-json/acpt/v1/{tableName}` (opt-in per table), with `page`, `per_page`, `orderby`, `order`, and per-column filters; file columns accept `multipart/form-data`.
- **Table metabox settings** - per-table `context` (normal/side/advanced), `priority`, hide-title, and hide-toggle controls for the record metabox, matching meta-group box settings.
- **CCT fallbacks in core functions** - `get_acpt_fields()`, `acpt_field_has_rows()`, `acpt_field_has_blocks()`, and `is_acpt_field_visible()` transparently resolve CCT tables/columns, so existing templates work unchanged.
- **Import / export** - Tables and Table Groups can be exported and re-imported alongside CPTs, taxonomies, option pages, meta groups, and forms, preserving repeater/flexible hierarchies and foreign keys regardless of order in the file.
#### Canvas UI
- **Unified Canvas UI** - one drag-and-drop builder across meta fields, forms, CCT table columns, dynamic block controls, option pages, and WooCommerce product data. Built on `@dnd-kit` and `react-resizable-panels`.
- **No-distraction mode**, **resizable panels**, and an **advanced-mode toggle**, all persisted per entity.
- **Inline editing** - click-to-edit a field's label / name / type directly on the canvas, plus inline switch toggles (Show in archive, Filterable, Quick edit, Required) on each row, with name-uniqueness validation shared between canvas and sidebar.
- **Keyboard-accessible drag-and-drop** with live-region announcements (WCAG 2.1.1 / 4.1.3).
#### Meta Keys Manager
- **Meta Keys Manager** (ACPT → Tools → Meta Keys Manager) - lists every meta key in the database regardless of origin, with Key / Field type / Context / Associated to / Value / Actions columns, search, context filter, sorting, pagination, single-click inline value editing, and bulk Delete / Export CSV / Export JSON.
#### Meta Fields
- **Message field** - static, HTML-formatted informational text (no stored value); available for Meta Fields, Forms, and CCT columns.
- **Post Format** as a meta-group location condition (Ticket #1192).
- **Box-level conditional visibility** - a metabox's visibility can depend on another field's live value ("Other fields" / "Other columns"), matching field-level conditional rendering.
#### Forms
- **"Fill table" action** - write a submission directly into a CCT record (create or update), with a per-column mapping UI.
- **`record_id` attribute** on `[acpt_form]` - bind a form to an existing CCT record for editing.
- **Submission limits** converted to a flexible list layout.
#### Gutenberg
- **Block Bindings** - bindable meta fields (20 types including Text, Textarea, Editor, Number, Email, Image, Url, Select, Date, Color) can be connected to core blocks (Paragraph, Heading, Image, Button, ...) through WordPress's own native Block Bindings UI (WP 6.7+), with an inline-edit affordance for eligible text bindings. ACPT registers `acpt/field` as a core binding source - there is no custom panel.
#### Abilities API
- **Full Abilities API** - 57 MCP-exposed, schema-validated operations covering custom post types, taxonomies, meta groups/boxes/fields, field values, option pages, forms, dynamic blocks, and **Custom Content Types** (tables, table groups, records). All share one `AbstractAbility` base and register through both WP core's Abilities API and the ACFW (agent-connector-for-wp) integration with audit-log wrapping. Requires WordPress 6.9+ (or the Abilities API feature plugin).
#### Integrations
- **CCT support** across Divi, Elementor, Bricks, Breakdance, Yoast, WPML, RankMath, WPGraphQL, WP All Export, WP All Import, GenerateBlocks, WP Grid Builder, SEOPress, and Slim SEO.
- **FacetWP** - new integration indexing ACPT meta fields (including Repeater) for facets.
- **Divi 5** - Dynamic Tags integration.
- **Etch** - native integration (no external patches required).
#### Import / Export
- **Import review step** - lists every entity that will be created or updated before committing.
- **Dynamic Blocks** can now be exported and imported.
#### Developers
- `append_acpt_meta_field_value()` - append a single Repeater row without resending the others (also the `acpt/append-meta-field-value` ability).
- `WPAttachmentFactory` - centralised resolution of File / Image / Gallery values (ID, URL, or array) into attachment objects.
- New Table-field functions: `SQRT`, `ABS`, `MOD`, `MEDIAN`, `COUNT`.
- New `acpt/*` action/filter hooks for FacetWP, Elementor Pro, and integration-active checks.
- **CI pipeline** (`.github/workflows/tests.yml`) - ESLint (jsx-a11y), PHPStan level 7, Jest, and a 4-way-sharded PHPUnit matrix on PHP 8.3 / MySQL 8.0.
### Changed
- **Boot performance** - warm-boot DB queries cut from ~5 to 1 on wp-admin and 0 on the front end: boot-critical options are consistently `autoload=true` (with a one-time migration), the settings table has its own bootstrap-safe cache, `wp_enqueue_media()` only runs on ACPT's own screens, and the media-library month query is served via WP core's `media_library_months_with_files` filter. Textdomain loading is deferred to `plugins_loaded`.
- **Accessibility (WCAG 2.1 AA)** - completed the admin-UI roadmap: keyboard-accessible drag-and-drop with announcements, global focus-visible outlines, accessible Modal / Monaco / Quill editors, corrected colour-contrast tokens (including `:laceholder`, Ticket #1210), fixed heading order across wizards and Canvas builders, a WCAG-accessible shared Tooltip and breadcrumb, and numerous screen-reader label fixes (row-action menus, `CardRow`-wrapped controls, the Permissions matrix). A self-assessed conformance report is published. Front-end form field output is separately covered by a `pa11y` test gate.
- **PHPStan level 7** - the 227-entry baseline was fully fixed and emptied; `src/` stays baseline-free.
- **Testing** - ~2,200 new Jest tests across the whole React admin app (every component, page, and Redux slice) plus further coverage this cycle, fixing dozens of smaller UI bugs along the way. The e2e suite was migrated from Cypress to Playwright (`data-cy` -> `data-testid`).
- **Forms settings UI** - General / Email / CSS / Submission Limits tabs and the canvas field-settings sidebar reorganised into grouped, icon-labelled sections, with a syntax-highlighted custom-CSS editor.
- **Option Pages** - first-level pages can be nested under a native WP admin page via a `parent_slug`.
- **RTL** - consolidated ~25 files' duplicated RTL-detection onto one shared helper and added a `dir` attribute on the admin app root.
- **Renamed** the "Import data" / "Export data" tools to "Import settings" / "Export settings".
- **License checks** - bounded the boot-time license-validation network call with a 30-minute backoff and shorter timeouts, and honour the dev-mode skip flag.
- **Release pipeline** - `release.sh` builds with `pnpm` (matching CI) and fails loudly on any error.
- Field / table / column descriptions are sanitised to preserve safe HTML instead of being stripped (rich text is required by the Message field).
- Regenerated the hand-maintained `assets/static/js/*.min.js` for this release.
### Fixed
#### Security
- **REST API authentication** - `ACPT_Api_Auth::authenticate()` only checked that credentials belonged to *some* valid user, not any capability - any authenticated user (including a Subscriber) could call every "secured" REST v1 route. Now requires `manage_options`. Reported by Patchstack.
- **SQL injection** - WooCommerce product-data field cleanup concatenated client IDs into a `NOT IN (...)` clause unescaped; a crafted ID could delete the whole field table. Rebuilt with prepared statements. Reported by Patchstack.
- **Privilege escalation** - a public form submission could set `acpt_form_user_id` / `_post_id` / `_term_id` to update an existing user/post/term with no capability check - an anonymous "create user" form could overwrite an administrator. Added `current_user_can()` checks. Reported by Patchstack. Two follow-up id-extraction bugs in the same code were found and fixed during this release's security regression pass (Tickets #1274 / #1275).
- **PHP Object Injection** - hardened all 30 `unserialize()` / `maybe_unserialize()` call sites to reject embedded objects. Originally reported by Patchstack against 2 of these sites.
- **Stored XSS** - the meta-field sanitizer's allowed-tags list admitted `<script>`, so `wp_kses` never stripped it from rich-text output.
- **XSS hardening** - 13 unsanitised `dangerouslySetInnerHTML` usages in the admin UI now pass through DOMPurify via a shared `DangerousContent` component.
- **REST v1 + Table permissions** - the Table Permission System is now enforced on the REST API auth path (Ticket #1206).
#### Custom Content Types (CCT)
- **Column reorder silently reverting after save** (Tickets #1186 / #1187) - the reordered order never reached the save request.
- **Advanced-mode column drag corrupting the column's database type / repeater nesting** (Tickets #1186 / #1195 / #1196) - a reorder in Advanced mode could rewrite a column's DB type to a literal string, or lose repeater nesting.
- **CCT UI-type to MySQL-type mapper divergence** (Tickets #1218 / #1219) - the client and server disagreed on the physical type for several column kinds; the mapping is now server-authoritative. Also fixed column type / UI-type changes being reverted on save.
- **Options input losing focus after one character** (Ticket #1186).
- **Column sync crash after adopting a table** without its real primary key flagged (Ticket #1186); **primary-key + nullable column saved without a validation error** (Ticket #1197).
- **Stats panel crash** for any table with a Date or Text column (Ticket #1186).
- **Foreign-key "referenced columns" dropdown empty** for tables whose primary key had no UNIQUE index (Ticket #1166); **nullable toggle reverting to on** after save (Ticket #1166).
- **Index / foreign-key save & sync** - many fixes to index and FK persistence and to the schema-sync executor, including dropping FKs before altering their columns (Tickets #1212 / #1215 / #1216 / #1217 / #1220 / #1221 / #1223), and removing the unsupported `SET DEFAULT` FK action (Ticket #1222).
- **Hyphenated table names 404 on the REST API** (Ticket #1201).
- **CCT admin / REST data loss & permission bypass** (Tickets #1202 / #1204 / #1205) - partial updates could delete column data, and several endpoints didn't enforce table/group permissions (Ticket #1266).
- **Incomplete relationship config silently dropped on save** (Ticket #1200).
- **Wizard General tab not reflecting persisted toggle values** (Ticket #1224); **Indexes-step row delete was a no-op** (Ticket #1223); **decimal columns rejected fractional values** on the record form.
- **Flexible-Content block reorder on the post-edit screen losing data and fataling the edit screen** (Ticket #1241) - four compounding JS bugs; a new `reindexFlexibleBlocks()` routine.
- **CCT column conditional rendering never evaluated** on the record-edit form - a column set to "show only when X" always rendered (Ticket #1307).
- **CCT column validation rules** not enforced server-side and not API-writable; MAX / MIN / REGEX rejected; unguarded hydration could brick a table (Tickets #1238 / #1239 / #1240).
- **CCT column-level permissions were inert** - now enforced via `TableColumnModel::userColumnPermissions()` (Ticket #1242).
- **Stale sync / cache** - assorted CCT sync and cache-staleness gaps closed for stable; the "Flush cache" button now also clears the settings and schema caches (Tickets #1208 / #1213).
- **Trash / restore counts stale**, plus infinite recursion in `countRecords()` on tables without soft delete.
- **Duplicate success toast** after saving a table; **"Register table" button label** wrong after reload (Ticket #1232).
- **`SaveTableGroupCommand` silently ignoring an explicit "unlink all tables" save** - submitting a table group with an empty table list left the previous associations in place instead of clearing them.
#### Meta Fields
- **Meta group editor reliability** - a crash when deselecting/deleting a field mid-edit; the wrong field's form state removed in nested repeater/flexible scenarios; location-rule IDs corrupted on every save; two never-wired delete-confirmation modals; several settings-panel bugs.
- **Colliding auto-generated field names silently breaking saving and disabling the group's Save button** (Ticket #1229); the **box-name collision guard** weakened in the Canvas migration was restored (Tickets #1234 / #1248).
- **Repeater / Flexible children silently wiped** by a partial update that didn't resend `children` (Tickets #1178 / #1231 / #1233), plus invisible Relationship-field warnings.
- **Relation fields** (Ticket #1178) - a schema mismatch could reject or drop a saved relation; an unconfigured Post relation silently no-op'd.
- **`get_acpt_fields()` cross-box field collisions** - fields keyed by position within their box, so a later box overwrote an earlier one (Ticket #1174).
- **`getAdvancedOptions()` index instability** - now index-stable via placeholder models; also fixed a `restrict_image_extensions` key mismatch (Ticket #1235).
- **"Autoincrement" ID field never got a value outside wp-admin** - now generated on save regardless of how the post is created, with a one-time backfill (Ticket #1181). The ID-format contract is enforced in `save_acpt_meta_field_value()` (Ticket #1250).
- **Site-wide crash from an invalid `save-meta-group` operator** - a `belongs` rule with an empty operator crashed every later read of that structure; it is now validated on write and tolerated on read (Ticket #1182).
- **Live conditional rendering** - an orphaned Flexible Content reference could fatal the whole live visibility check on every keystroke; also fixed N+1 lookups and duplicate AJAX.
- **CPT wizard icon field** - selecting an icon didn't clear a stale "mandatory" error; **Windows menu-icon uploads** were broken by a URL-building bug (Tickets #1173 / #1178).
- **Gallery field losing images on drag-reorder** (and Gallery-in-Repeater locating the wrong input); "hide unless this field has a value" never detecting an empty Gallery / Audio (multiple) / Video (multiple) / Image Slider on first render.
- **Screen-reader label markup leaking into `aria-label`** (Ticket #1178).
- **FileField fatal on missing advanced options** and on a post-less-screen metabox render (Ticket #1211).
- **An explicit-null required key** on a Save*Command (e.g. `save_acpt_meta_group(['name' => null])`) caused a WSOD - now a graceful validation error (Ticket #1249).
#### Meta Keys Manager
- **Prefix-overlapping sibling data destroyed** - `DeleteMetaFieldValueCommand` ran an unescaped `LIKE '<dbName>%'` that also matched other fields sharing the prefix; a new `keyPredicate()` scopes the delete (Ticket #1244).
- SelectMulti / Checkbox inline value editing now pre-selects and saves a proper array (Ticket #1245); further fixes (Ticket #1246).
#### Permissions
- **An orphaned-role permission row white-screened the entire site**, front end included (Ticket #1271).
- **Custom-role cascade lockout** - granting a capability to one custom role could remove it from others, across Table / TableGroup / OptionPage / Taxonomy / MetaField permissions (Ticket #1269).
- **Field- and column-level permissions were enforced on render only, not on save** (Tickets #1242 / #1243).
- **"Add permission" row rendered every checkbox pre-checked**, and toggled state wasn't visible (a CSS sibling selector couldn't reach past the screen-reader span); **"Delete all" / single-row Delete never persisted** to the server (Tickets #1267 / #1268 / #1270).
- **`TableGroupController` never enforced edit/read permissions** (Ticket #1266); an **OptionPage read-only role could bypass edit** via a crafted POST (Ticket #1273).
- **`SavePermissionCommand` couldn't clear all permissions** - `deleteByEntityId()` ran after the empty-items guard.
- Constructing Table permissions threw (`create` / `update` missing from `$allowedPermissions`); a `gerPermissionsAsArray` typo was fixed; `ACPT_Permissions` never actually applied saved table/group caps to WP roles.
#### Admin UI
- **Crash on first load of the Taxonomy / CPT / Block detail view** ("Nothing was returned from render").
- **CPT / Taxonomy association** - a failed association threw a silent JS error instead of showing the toast.
- **Wizard navigation** (Table Group / Taxonomy / CPT / Table) could skip an incomplete step or crash stepping back; wizards mutated shared form state in place, bleeding edits between unrelated fields.
- **Failed save/action toasts showed a blank message** - 58 Redux thunks weren't propagating the failure reason.
- **Health Check** stuck on "running" after a failed request, and checked/created the wrong cache directory.
- **Export / Import / Settings** - stuck loading indicators; Import didn't validate file type/size; Settings' Save button stuck on a stale loading state.
- **`<Tabs>` remount race** on the Settings page; added a `keepMounted` prop (Ticket #1209).
- **Pagination totals ignored active search / filters** across nine list views.
- **Placeholder / readonly input contrast** below WCAG AA (Ticket #1210).
- Numerous smaller fixes across form controls, list pages, and shared components, found via the new Jest suite.
#### Forms
- **`field_key` varchar(12) collision** - `acpt/save-form` (and the `save_acpt_form_field` sibling path) silently collapsed fields whose keys collided after truncation (Ticket #1254).
- **Front-end form crashes** - a Date field with no explicit format fataled the page; `front-end.js` died on block themes where jQuery loaded after it; the textarea character counter crashed on typing (Tickets #1255 / #1256 / #1261).
- **Submission 500s** - on a `null` `$_FILES` entry and on a missing nonce field (Tickets #1257 / #1260).
- **Saving one form deleted every other form's *and* every Meta field's validation rules** - `removeOrphanValidationRules` ran `WHERE 1=1` (Ticket #1262).
- **Re-saving a form with a populated `fields[]` and no ids deleted every field** (Ticket #1263).
- **The Form Settings editor kept the previous form's key / CSS / meta on an in-app form switch** (Ticket #1264).
- **A non-required field with a format / comparison rule was de-facto mandatory** (Ticket #1258); **`<Input>` dropped `min={0}` / `max={0}`** and the redirect timeout had no range validation (Ticket #1265).
- **Form metadata schema rejected object values**, breaking `get-form` / `list-forms` for CSS-customised forms (Ticket #1259).
- **Duplicate / misattributed submission-log rows** (a join with no `ON` clause); a **stale Forms list**; forms using the "None" action **never rendered an opening `<form>` tag**.
#### Taxonomy / CPT
- **CPT "Rewrite" toggle silently disabled** when editing a post type whose stored settings predate the `rewrite` key - saving for any reason persisted `rewrite: false` and 404'd the CPT (Tickets #1153 / #1160 / #1251). The same bug was fixed for taxonomies (Ticket #1253).
- **A reserved-slug taxonomy save reported success while persisting nothing** (Ticket #1252).
- **`capabilities_0..3` read unconditionally** in `TaxonomyController::save()` - `Undefined array key` warnings on every taxonomy save without the optional capability selects.
- The field group for the `product` post type leaking onto the WooCommerce attribute edit page.
#### Integrations
- **Elementor (free + Pro) front-end rendering regressions** from the PHPStan level-7 pass - `: string` return-type hints turned `echo` into `return`, blank-screening bound fields (Tickets #1286 / #1288 / #1290).
- **Breakdance / Oxygen 6** - binding a CCT column white-screened the front end (`hasParent()` on `null`, no try/catch) (Ticket #1284).
- **Bricks** - `get_tag_value()` unguarded `$post->ID` on term archives (Ticket #1283); a repeater-nested relation to a post type now resolves (Ticket #1228); plus through-relationship tags, query-loop relation fields, and top-level term-archive loop fields.
- **Divi 5** - CCT columns were unrenderable in dynamic content; Date / Time format override (Tickets #1291 / #1292).
- **Etch** - user-context ACPT fields never resolved (Ticket #1293); Image-in-Repeater fatal.
- **GenerateBlocks** - user-context fields in single dynamic tags (Ticket #1294); `{acpt.*}` record tags were keyed by position, not field name; multi-value media fields (Video / Gallery / Slider / Audio multiple) had no dynamic-tag provider (Ticket #1175).
- **WP Grid Builder** - CCT columns in pickers; a `returnValue(array)` front-end WSOD guard (Tickets #1295 / #1296).
- **FacetWP** - `isActive()` lost a load-order race and the integration was inert; `acpt/` source resolution (Tickets #1297 / #1298).
- **Slim SEO** - an option-page token leak; taxonomy / user variables were never resolved (Tickets #1299 / #1300).
- **SEOPress** - a relational field's array value hit a `wp_strip_all_tags()` `TypeError`, white-screening the front end; taxonomy / user variables (Tickets #1301 / #1302).
- **Yoast** - a classic-editor snippet-preview shim; lazy variable-replacement registration; term-archive context (Tickets #1303 / #1304).
- **RankMath** - a positional-arg `%acpt_field(x)%` variable fataled the front end (Ticket #1305).
- **License page unrecoverable after a site migration** - an unrecognised stored activation id always rendered the dead "Activate" screen; the error is now surfaced (Ticket #1164). A **fatal on every request when license reconciliation can't reach acpt.io** from a cloned/staging domain now degrades gracefully.
- Logical-operator cleanup (`and` / `or` to `&&` / `||`) surfaced three real bugs: nested Checkbox field input names, Zion / Yoast staying inactive when only the second plugin variant was installed, and a Divi blog-query check ignoring the property value.
#### Abilities API
- **Partial-update data loss across 8 ability families** (Table, MetaField, FormField, DynamicBlock, TableGroup, Form, MetaBox, TableRecord) - a payload omitting an optional field silently deleted it; omitting `columns` on a Table update deleted every column / index / FK definition and the next sync dropped the physical columns. All 8 now merge onto the existing record. `OptionPage` had the same class of bug on partial save (Ticket #1277).
- **`save-meta-field` never found the field being edited** - it matched the wrong data shape, so non-rename edits silently no-op'd and renames created orphan duplicates.
- **`ability_invalid_output` on `rest_base`** - `list-*` / `get-*` for any taxonomy / post type with no explicit REST base (e.g. core's `post_format`); fixed at the read layer so stored data self-heals.
- **`acpt/save-post-type` defaulting `capability_type` to the post slug** - generated meta caps assigned to no role, so the CPT was invisible in wp-admin and rejected every edit. The default is now `post` (Ticket #1170).
- **`MetaFieldSchema` didn't declare `label` as writable**; `save_acpt_table()` could duplicate the `ENGINE` table option on a partial update.
- **ACFW boot-order race** - its audit-log / MCP decoration silently never applied when both integrations were active; abilities were missing `meta.mcp.public`, so `wordpress/mcp-adapter` hosts rejected every call.
- **`acpt/sync-table` and `acpt/delete-table*` are now flagged `destructive`** (and require `DELETE` through WP's REST layer).
#### Datasets
- **Inverted import guard** - "import into an existing dataset" rejected the only valid case and passed invalid requests to a fatal.
- **`delete_acpt_option_page($slug, true)` never removed the field values** (Ticket #1237).
- **"Delete all" modals** (Datasets, Permissions, WooCommerce fields, Meta boxes, Option pages) stuck open after confirming.
#### Import / Export
- **XML re-import data loss** - an empty value round-tripped as indistinguishable from an empty array and aborted the whole import; `.acpt` re-import failed on legacy double-escaped / backslash payloads.
- **Export bugs** - CPT / taxonomy lists capped at 20; XML / YAML export of Tables or Forms failed or dropped data; range-selection never worked; bulk CSV export always produced an empty file (a `CSVFormatter` data-shape mismatch).
#### Accessibility
- Additional axe-core violations fixed in the field / column settings sidebar and across the Canvas builders (nested-interactive select wrappers, focus management), from this release's accessibility regression spot-check (Tickets #1278 / #1279 / #1280 / #1282).
- Block Bindings: `computeBindableFields()` is memoised to stop a `useSelect` re-render warning in the editor (Ticket #1281).
#### Miscellaneous
- **WooCommerce product-data field save failing on every attempt** - adding a field via the toolbar and saving without opening the settings panel returned HTTP 500 with 5 PHP warnings (Ticket #1230).
- A multi-value media field value is now stored as flat URL strings rather than a nested structure (Ticket #1289).
- Image / media field values not saving when served from a different host (CDN / offloaded media) - attachment resolution falls back to matching on the URL path.
- Image / Audio / Video / File values silently not persisting via the REST save path - `WPAttachment::fromUrl()` now tries query-string, URL-encoding, and `-scaled` variants, and the REST callback returns a `WP_Error` on failure instead of discarding it.
- WPML custom field translations stuck in one language (Ticket #1118).
- Dynamic blocks not rendering in the FSE site editor; a REST block-renderer live-preview error on insert.
### Known issues
- **Relational (Post / User) meta fields render empty in page-builder dynamic data on Elementor (free) and Breakdance / Oxygen** (Tickets #1285, #1287) - the value resolves correctly in ACPT's own output and in Bricks, Gutenberg, Divi, and the Pro builders. A central relational-rendering pass for the remaining free builders is scheduled for a 2.1.x point release.
- **No automated test coverage** for legacy Oxygen <= 4.9, Zion Builder, or Polylang - these integrations are exercised manually only (accepted risk).
Decryption key:
ACPT - Custom post Types Plugin for Wordpress v2.0.67 Nulled
## [2.0.67] - 2026-08-18
### Changed
#### Performance
- **License, plugin-version and ID-field-backfill options queried on every request** - These three tracking options were stored with `autoload=no`, forcing WordPress to issue a dedicated `SELECT` for each on literally every front-end and admin request instead of folding into its single bulk options query. Now stored autoloaded, with a one-time migration that fixes the flag on sites already storing these from an earlier version.
- **Settings table queried on every request without ever hitting the plugin's cache** - Reading the settings table happens during the plugin's own bootstrap, before its file-based query cache has been initialized, so this specific read could never benefit from it no matter how warm the cache was elsewhere. It now has its own lightweight cache, invalidated whenever a setting is saved.
- **`wp_enqueue_media()` running on every wp-admin screen** - ACPT called WordPress's media-library bootstrap function unconditionally on every `admin_enqueue_scripts`, triggering a `wp_posts` query on every wp-admin page for every plugin - not just ACPT's own screens. It's now only called on screens where ACPT actually registered assets.
- **Media library "date filter" dropdown query re-run on every `wp_enqueue_media()` call** - Hooked WordPress core's `media_library_months_with_files` filter (provided by core specifically to avoid this cost, see `core.trac.wordpress.org` ticket #31071) to cache the dropdown's month/year data instead of recomputing it with an uncached `wp_posts` scan every time.
### Fixed
#### Security
- **REST API authentication** - `ACPT_Api_Auth::authenticate()` only verified that Basic Auth credentials or an API key belonged to *some* valid WordPress user, without checking any capability - any authenticated user (including a Subscriber) could call every "secured" REST v1 route. Now requires `manage_options`, matching the plugin's own AJAX proxy. Reported by Patchstack.
- **SQL injection** - WooCommerce product-data field cleanup built its `DELETE` queries by string-concatenating client-supplied IDs into a `NOT IN (...)` clause with no escaping; a crafted ID could delete every row of the field table, not just orphans. Rebuilt with prepared-statement placeholders. Reported by Patchstack.
- **Privilege escalation** - A public form submission could set a client-controlled `acpt_form_user_id`/`_post_id`/`_term_id` field to update an *existing* WordPress user/post/term instead of creating a new one, with no ownership or capability check - an anonymous "create new user" form submission could overwrite an administrator account. Added `current_user_can()` checks before any update.
- **PHP Object Injection** - Hardened all 30 `unserialize()`/`maybe_unserialize()` call sites across the plugin (form metadata, relation-field sync, box/field-rename sync, form/block/permission builders, WooCommerce and WP All Import integrations) to reject embedded objects, closing a gadget-chain risk originally reported by Patchstack against 2 of these sites.
- **Stored XSS** - The meta-field sanitizer's allowed-tags list admitted `<script>`, so `wp_kses`-based sanitization never actually stripped it from rich-text field output.
#### Meta Fields
- **Site-wide crash from an invalid `save-meta-group` operator** - A `belongs` rule with a missing/empty operator could be persisted with an empty value and then crash *every* subsequent read of that structure (admin, front-end, REST, every Ability) as soon as it was re-hydrated from the database. The operator is now validated and invalid rules are rejected gracefully, both when saving and when reading a pre-existing row (Ticket #1182).
- **"Autoincrement" ID field never got a value outside wp-admin** - An ID-type meta field only ever generated its value inside the wp-admin edit-screen form; a post created via REST, the Abilities API, an import, or `wp_insert_post()` directly permanently had no value for that field. The value is now generated automatically on save regardless of how the post was created, and a one-time migration backfills every already-existing post on update (Ticket #1181).
- **`get_acpt_fields()` cross-box field collisions** - Fetching every field across a whole meta group (no specific box - the call ACPT's native Etch integration uses for `{options.acpt}`) could silently drop entire boxes' worth of data: fields were keyed by their position *within* their own box, which resets to 0 for every box, so a later box's fields overwrote an earlier box's fields at the same position (Ticket #1174).
- **Gallery field losing images on drag-reorder** - Dragging to reorder a Gallery field's images in wp-admin could silently drop entries: the preview only rendered a thumbnail for attachments that still resolved (e.g. not deleted from the media library since being selected), and reordering rebuilt the field's saved value from only the *rendered* thumbnails, discarding anything without one - occasionally emptying the field entirely. A Gallery field nested inside a Repeater/Flexible block had a second, more reliable trigger: reordering located the wrong field's hidden input as soon as a page had more than one gallery or rows were added/removed. Also fixed "hide unless this field has a value" conditional rules never correctly detecting an empty Gallery/Audio (multiple)/Video (multiple)/Image Slider field on the initial page render, only on later live updates. (Reported on Facebook)
#### Abilities API
- **`ability_invalid_output` on `rest_base`** - `list-post-types`/`list-taxonomies`/`get-taxonomy` could fail output validation for any taxonomy or post type registered without an explicit REST base (e.g. WP core's `link_category`/`post_format`), since `WP_Taxonomy`/`WP_Post_Type::$rest_base` defaults to the literal boolean `false`, not `string|null` as declared. Fixed at the read layer so already-stored data self-heals, not just new syncs.
- **`acpt/save-post-type` defaulting `capability_type` to the post slug** - A settings payload that omitted `capability_type` explicitly (rather than omitting `settings` entirely) defaulted it to the post type's own slug, generating meta capabilities never assigned to any role - the resulting CPT was registered but invisible in wp-admin and rejected edits for every role, including administrator. Default is now `post`, matching WP core (Ticket #1170).
#### Integrations
- **GenerateBlocks Dynamic Data for multi-value media fields** - Video (multiple), Gallery, Image Slider, and Audio (multiple) fields had no Dynamic Tag provider and never appeared as usable dynamic data; only their single-value counterparts were supported (Ticket #1175).
- **Windows image URLs** - Image/media field URL-building used `DIRECTORY_SEPARATOR` (a backslash on Windows) to join URL segments instead of a forward slash, silently breaking meta box saves on Windows hosts (Ticket #1173).
Decryption key:
ACPT - Custom post Types Plugin for Wordpress v2.0.66 Nulled
## [2.0.66] - 2026-07-24
### Changed
- **Abilities API architecture** - Unified all ~41 abilities under a shared `AbstractAbility` base class (`src/Core/Ability/`), registered consistently through both the core WordPress Abilities API and the ACFW (agent-connector-for-wp) integration, with the same exception-handling, permission checks, and audit-log wrapping applied everywhere. Brings along the crash and data-loss fixes below.
### Fixed
- License page stuck unrecoverable after a site migration: when the stored activation id is no longer recognized by the license server (e.g. `Activation ID not found`), the React app silently discarded the error and always rendered the "Activate your license" screen with a dead (linkless) button, with no way to reach the "Deactivate license" action that would clear the stale local record. The fetch error is now surfaced and routes to the license details screen so it can be deactivated and re-activated normally.
- Fatal error on every request when license reconciliation can't reach acpt.io (e.g. cloned/staging domains) - the unguarded API call is now wrapped so a network failure degrades gracefully instead of fataling the whole site (Ticket #1164).
- CPT rewrite rules silently disabled when editing existing post types: the "Rewrite" toggle defaulted to unchecked for existing post types whose stored settings lacked an explicit `rewrite` key, so saving the form for any reason (e.g. just updating the front URL prefix) silently persisted `rewrite: false`, registering zero rewrite rules and 404ing the CPT - not fixable by flushing permalinks. Also hardens the `custom_rewrite`/front-URL-prefix priority check so a stale `custom_rewrite` value can no longer silently shadow the front URL prefix (regression of Ticket #1153, Ticket #1160).
- Image/media field values not saving when served from a different host (CDN, offloaded media, image accelerator, etc.) - attachment resolution now falls back to matching on the URL path alone when the host differs from the site's own upload base URL.
- Bricks Query Filter showed no checkbox options for POST_TYPE relation fields, and a cold indexer run could produce zero index rows; relational-loop dynamic data tags also resolved against the archive's queried object instead of the loop target (#1161, #1165).
- Site-wide crash (front-end, admin, REST, AJAX) from a missing/empty location-rule operator on `save-meta-group` - the operator is now validated and invalid rules are rejected gracefully.
- Partial updates across 8 ability families (Table, MetaField, FormField, DynamicBlock, TableGroup, Form, MetaBox, TableRecord) were silently deleting data the payload didn't mention - most seriously, omitting `columns` on a Table update deleted every column/index/foreign-key definition, and the next schema sync then dropped the corresponding database columns. All 8 now merge onto the existing record instead of rebuilding it from scratch.
- `save-meta-field` matched against the wrong data shape and never actually found the field being edited, so non-rename edits silently no-op'd and renames created orphan duplicates.
- ACFW's audit-logging/MCP registration always lost a boot-order race against the core Abilities API integration, so its decoration silently never applied when both were active.
- ACPT abilities were missing `meta.mcp.public`, so the official `wordpress/mcp-adapter` package (used by ACFW and other MCP host plugins) rejected every call with "not exposed via MCP" even though the ability registered fine.
Decryption key:
ACPT - Custom post Types Plugin for Wordpress v2.0.65 Nulled
### Changed
- **Abilities API architecture** - Unified all ~41 abilities under a shared `AbstractAbility` base class (`src/Core/Ability/`), registered consistently through both the core WordPress Abilities API and the ACFW (agent-connector-for-wp) integration, with the same exception-handling, permission checks, and audit-log wrapping applied everywhere. Brings along the crash and data-loss fixes below.
### Fixed
- License page stuck unrecoverable after a site migration: when the stored activation id is no longer recognized by the license server (e.g. `Activation ID not found`), the React app silently discarded the error and always rendered the "Activate your license" screen with a dead (linkless) button, with no way to reach the "Deactivate license" action that would clear the stale local record. The fetch error is now surfaced and routes to the license details screen so it can be deactivated and re-activated normally.
- Fatal error on every request when license reconciliation can't reach acpt.io (e.g. cloned/staging domains) - the unguarded API call is now wrapped so a network failure degrades gracefully instead of fataling the whole site (Ticket #1164).
- CPT rewrite rules silently disabled when editing existing post types: the "Rewrite" toggle defaulted to unchecked for existing post types whose stored settings lacked an explicit `rewrite` key, so saving the form for any reason (e.g. just updating the front URL prefix) silently persisted `rewrite: false`, registering zero rewrite rules and 404ing the CPT - not fixable by flushing permalinks. Also hardens the `custom_rewrite`/front-URL-prefix priority check so a stale `custom_rewrite` value can no longer silently shadow the front URL prefix (regression of Ticket #1153, Ticket #1160).
- Image/media field values not saving when served from a different host (CDN, offloaded media, image accelerator, etc.) - attachment resolution now falls back to matching on the URL path alone when the host differs from the site's own upload base URL.
- Bricks Query Filter showed no checkbox options for POST_TYPE relation fields, and a cold indexer run could produce zero index rows; relational-loop dynamic data tags also resolved against the archive's queried object instead of the loop target (#1161, #1165).
- Site-wide crash (front-end, admin, REST, AJAX) from a missing/empty location-rule operator on `save-meta-group` - the operator is now validated and invalid rules are rejected gracefully.
- Partial updates across 8 ability families (Table, MetaField, FormField, DynamicBlock, TableGroup, Form, MetaBox, TableRecord) were silently deleting data the payload didn't mention - most seriously, omitting `columns` on a Table update deleted every column/index/foreign-key definition, and the next schema sync then dropped the corresponding database columns. All 8 now merge onto the existing record instead of rebuilding it from scratch.
- `save-meta-field` matched against the wrong data shape and never actually found the field being edited, so non-rename edits silently no-op'd and renames created orphan duplicates.
- ACFW's audit-logging/MCP registration always lost a boot-order race against the core Abilities API integration, so its decoration silently never applied when both were active.
- ACPT abilities were missing `meta.mcp.public`, so the official `wordpress/mcp-adapter` package (used by ACFW and other MCP host plugins) rejected every call with "not exposed via MCP" even though the ability registered fine.
Decryption key:
# Changelog
## [2.0.65] - 2026-07-13
### Added
- Integration with the [Abilities API](https://docs.acpt.io/abilities-api), including output-schema fixes for `save-post-type` and 9 other providers whose output validation was broken.
- `append_acpt_meta_field_value()` function/ability to append a single Repeater row without resending existing ones - new `AppendMetaFieldRowCommand`, wired into the Abilities API as `acpt/append-meta-field-value`.
- New Table field arithmetic functions: `SQRT`, `ABS`, `MOD`, `MEDIAN`, `COUNT`.
- New telemetry insight keys (DB engine, multisite, active theme, PHP memory limit, WooCommerce version, feature usage counters) plus a deactivation ping.
### Fixed
- Table field `Maths` singleton memoization (was comparing flattened data against raw input, so caching never worked); malformed formulas (e.g. `=(ROUND("abc",2))`) now return a graceful error instead of crashing the live AJAX formula editor.
- CodeMirror text overflow in admin meta field editors - long lines/URLs now wrap instead of overflowing the layout.
- Etch fatal error when an Image field is nested inside a Repeater (`WPAttachment` private property access via `property_exists()`).
- Dynamic blocks not appearing/rendering in the FSE site editor.
- REST block-renderer live-preview error when inserting a dynamic block in the FSE site editor.
- ACPT loop fields empty on Bricks top-level term-archive templates.
- Front URL prefix causing 404s on Custom Post Type permalinks (Ticket #1153).
- WPML custom field translations getting stuck in one language (Ticket #1118).
- Image/Audio/Video/File field values silently not persisting to `wp_postmeta` via the REST save path: `WPAttachment::fromUrl()` now resolves attachments through query-string, URL-encoding, and `-scaled` suffix variants instead of only an exact `_wp_attached_file` match, and `ACPT_Api_Rest_Fields::updateCallback()` now returns a `WP_Error` when a field fails to save instead of silently discarding the failure.
### Changed
- Refactored `Request`: replaced ambiguous `has()` with explicit `hasGet()`/`hasPost()`; `all()` now delegates to `requestAll()`.
Decryption key:
ACPT - Custom post Types Plugin for Wordpress v2.0.64
# Changelog
## [2.0.64] - 2026-06-25
### Fixed
- `PostField::renderRelationFieldSelector()` fatal error.
- `FORMAT_NATIONAL` fallback for PHP < 8.1 environments.
- `s.charAt` crash when Phone field has null `defaultValue` or Etch key in description.
Decryption key:
ACPT - Custom post Types Plugin for Wordpress v2.0.63 Nulled
### Added
- New advanced option: `restrictLoggerUserPosts` in Post, Post multiple, and Relational fields.
### Changed
- Etch integration - no longer requires external patches; native `WPAttachment` conversion and filter fixes.
- Bricks: through-relationship dynamic data tags (up to 2 hops).
- Batch-prime WP post cache before gallery loops to eliminate N+1 queries.
### Fixed
- `Restrict image extensions` option was being polluted by `Input file accepts` values.
- Repeater sort blanked the second item - reindex regex extended to cover `_id` / `_required` hidden inputs.
- Field group for `product` post type was leaking onto the WooCommerce attribute edit page.
- PHPFastCache created per-host cache directories due to `HTTP_HOST` fallback; added cache folder setting.
- Logged-out users could bypass form role restrictions.
- DateTime picker always showed AM/PM regardless of the configured field format.
- `Url::fullUrl()` and `Url::baseUri()` no longer emit warnings in PHP CLI / WP-CLI / server-cron contexts.
- Gallery drag & drop lost attachment IDs after reorder.
- RankMath integration script no longer enqueued on the frontend.
- Meta box migrated to the wrong field group when saving an unrelated group.