=== Field Forge – Custom Fields, Relational Fields & Builder ===
Contributors: avakodeforge
Donate link: https://avakode.com
Tags: custom-fields, meta-fields, custom-table, relational-fields, builder
Requires at least: 6.5
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.1.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Custom fields, ACF compatible, unlimited groups: custom-table storage and 31 field types including relational. ACF and Pods alternative.

== Description ==

**Field Forge** is a modern custom-fields plugin. Fields live in dedicated tables (`wp_fieldforge_values`) instead of the bloated `wp_postmeta`, so listing pages stay fast even with 50+ fields per post. Drag-drop the field group editor, then read values via PHP or REST.

= Free =
* Unlimited field groups
* 31 field types — text, textarea, number, select, image, file, WYSIWYG, oEmbed, Gallery, Calculation, date/time/color pickers, Google Map, link, and the relational set (Relationship, Post Object, Page Link, Taxonomy, User)
* Location rules (post type, taxonomy, template, user role)
* ACF compatibility layer (import existing ACF groups + values)
* Custom-table storage (not `wp_postmeta`)
* Migration UI from ACF Free
* Visual field group builder
* Local JSON sync (write field groups to disk for version control)
* Options-page values via `get_field()` / `update_field()`
* REST API field exposure
* Schema versioning + revision history for field groups

= Field Forge Pro =

Pro is a separate add-on plugin, distributed from https://fieldforgewp.com and not
included in this download. Everything listed above is part of this plugin and works
without it.

* Compound field types: Repeater, Group, Flexible Content, Clone
* Options pages management screen (creating and editing the pages themselves)
* PHP Blocks (register Gutenberg blocks from field groups)
* AI schema generator (describe the data → generates a field group)
* Native WPGraphQL schema + resolvers (no add-on plugin needed)
* TypeScript / JSON sync (export field groups to your repo)
* Bulk JSON export / import
* Priority email support with an active Pro licence

Part of the **Forge Suite** — bundle includes Lang Forge, Rank Forge, Form Forge.

== External services ==

Every outbound request this plugin makes is listed below. Activating it, and opening its screens, contacts nobody.

* **oEmbed field.** An oEmbed field asks WordPress to fetch the embed from the provider of the URL an editor enters, exactly as the block editor does: when the field's value is shown, in the preview under the field in the editor and wherever a theme or a plugin reads the field through the ACF-compatible `get_field()`, WordPress asks that provider's oEmbed address about the URL. The provider receives the URL and sees the network address of your server. Which provider that is depends on the URL; its terms and its privacy policy are its own. A site that uses no oEmbed field makes no such request.


**The Forge API at https://api.avakode.com, when you open the Forge Suite screen or answer the feedback card:**

* **Health check — `/health`.** Only when an administrator presses "Run diagnostics" in Setup & Health on the Forge Suite screen, or a repair button next to it, which runs the diagnostics again. It asks https://api.avakode.com/health whether the service is up: an ordinary GET with no body, no licence key and nothing about your site in the request itself. It sends its own User-Agent (`ForgeSuite/health-check`) instead of WordPress's default one, so neither your WordPress version nor your site's address is in it. As with any HTTP request, our server also sees the network address it came from.
* **Feedback card — `/feedback`.** The card appears in the admin footer of the Forge screens, to administrators only, not before the plugin has been installed for thirty days, at most once every sixty days for each administrator, and not for fourteen days after you dismiss it. Pressing "Send feedback" posts your 0–10 score, whatever you typed in the comment box, which product's screen the card was shown on, and the plugin and WordPress version numbers. No licence key, e-mail address or content of yours is sent, and pressing "Not now" sends nothing at all. The request has no User-Agent of its own, so it carries WordPress's default one, which names your WordPress version and your site's address.

**The Forge API at https://api.avakode.com, only when the Field Forge Pro add-on asks for it:**

* **Licence check, free trial and AI schema generation — `/licenses/validate`, `/public/trial/activate`, `/ai/process`.** The free plugin carries the client of the Forge API that the Pro add-on uses for these three, and nothing in the free plugin itself calls it: Field Forge on its own never sends a request to these paths, and without the add-on there is no licence key to send. With the add-on active, they are asked for from the add-on's own screens and buttons, and its readme says when, what is sent and why. When the add-on asks for AI schema generation, api.avakode.com passes the description you typed and the names and labels of your public post types on to OpenAI, through Cloudflare AI Gateway, to produce the field groups; your licence key (or trial token) is not passed on. OpenAI's terms: https://openai.com/policies/terms-of-use/ — OpenAI's privacy policy: https://openai.com/policies/privacy-policy/; Cloudflare's terms: https://www.cloudflare.com/website-terms/ — Cloudflare's privacy policy: https://www.cloudflare.com/privacypolicy/.

The free plugin sends no usage statistics. The Pro add-on has an optional statistics feature that is off until you say yes; it is described in the add-on's readme. When the last Forge plugin or add-on on a site is deleted, everything Forge stored on the site is removed, on every site of a network (the statistics settings and the install ID included); a plugin's own content follows its own “delete data” setting. While another Forge product stays, only the deleted one's own share goes.

Terms: https://avakode.com/terms — Privacy: https://avakode.com/privacy

== Installation ==

1. Upload `fieldforge` to `/wp-content/plugins/`, or install via Plugins → Add New.
2. Activate the plugin.
3. Go to **Field Forge → Field Groups → New Field Group**.
4. Read values in PHP: `$value = get_field('my_field', $post_id);`
5. Or via REST: `GET /wp-json/wp/v2/posts/123/fieldforge`
6. With the separate Field Forge Pro add-on, also via GraphQL: `posts { nodes { fieldforge { myField } } }`

== Frequently Asked Questions ==

= Can I migrate from ACF? =

Yes. Field Forge → Migration → ACF detects existing field groups + values and imports them into Field Forge tables. The ACF compat layer keeps your `get_field()` calls working during migration.

= Will it slow down my admin? =

The opposite — values are not autoloaded from `wp_postmeta`. Listing 100 posts with 50 fields each loads in ms instead of seconds.

= Is GraphQL support a separate add-on? =

No. Native WPGraphQL schema is built-in (Pro). You don't need "WPGraphQL for ACF" or similar bridge plugins.

== Screenshots ==

1. Field group editor
2. Repeater field on post edit (Pro)
3. Migration from ACF
4. GraphQL schema preview (Pro)
5. AI schema generator (Pro)

== Changelog ==

= 1.1.0 =
* Local JSON Sync writes field group files only inside the uploads folder (uploads/fieldforge-json by default) and no longer reads <theme>/fieldforge-json on its own. Groups saved from the site are in the database and are not affected. Groups that exist only as JSON in the theme folder stay on disk but are not listed until you add the folder with the fieldforge/local_json/load_paths filter and sync. A save path outside uploads falls back to the default; files already there are not moved.
* The ACF importer asks ACF where its Local JSON folders are, instead of working out the theme folder itself.
* Adding a Flexible Content row (a field type of the Field Forge Pro add-on) no longer leaves an output buffer open when one of its field renderers fails.
* Deleting the last Forge plugin or add-on on a site removes everything Forge stored there, on every site of a network, including its scheduled events. While another Forge product stays, only the deleted one's share goes. A WooCommerce Forge product left on the site no longer counts as a neighbour that keeps it.
* The Forge Suite screen lists Renew Forge as available on wordpress.org, and its Recent activity is sorted on one UTC clock.

= 1.0.41 =
* The empty Field Groups list now says how many ACF field groups it found on the site and links to the migration screen. Only that screen, and only while the list is empty, looks for them, and only administrators see the note.
* The Forge Suite dashboard no longer counts the test submissions sent from Form Forge's "Send a test submission" button: they are left out of the 30-day Form submissions counter, the conversion rate built on it and the "New submission" activity entry.

= 1.0.40 =
* Deleting the plugin leaves the job queue the Forge plugins share in place while another Forge plugin or add-on is still on the site. The check used to miss add-ons, and Rank Forge installed from wordpress.org, so the queue could be dropped while a neighbour still had jobs in it.
* Deleting the plugin removes the site's Avakode account binding, and now the hourly statistics event too, only when it is the last Forge plugin on the site. It used to remove the binding every time, which unbound every other Forge plugin.
* The dashboard's “Run diagnostics” request to api.avakode.com/health no longer carries your site's address: it identifies itself as ForgeSuite/health-check instead of using WordPress's default User-Agent, which includes the address.
* The Forge Suite screen lists Renew Forge, shows Guard Forge and Velocity Forge as available on wordpress.org, and carries the other products' current plans and taglines.
* The readme's External services section lists every request the plugin can make and what goes with it, and says that an AI request is passed on to OpenAI through Cloudflare AI Gateway, with the licence key held back.

= 1.0.39 =
* **This release needs Field Forge Pro 1.1.5 or newer if you run the add-on.** The licence screen, the upgrade prompt and the upgrade banner moved into the separate Field Forge Pro add-on; this plugin only notes which screens the add-on provides, with a link to its product page. An older add-on stays switched off until it is updated: the Pro field types, Options Pages, the REST and GraphQL exposure and the AI actions stop, nothing already saved is changed, and an admin notice names both versions.
* The Options Pages screen and the JSON export and import on the Tools screen say that they belong to the add-on instead of showing a locked page.

= 1.0.38 =
* The "matches pattern" condition no longer changes PHP's regular-expression limits while it runs. A pattern that would run away is still stopped by PHP and treated as not matching.
* Options Pages management and the clone field check for the Field Forge Pro add-on at every place they use it. Nothing changes on a site with or without it.
* Fixed: the Forge Suite screen reported Rank Forge as not installed when it came from wordpress.org, which installs it into the rank-forge folder, and its Activate link pointed at a file that is not there.
* The Forge Suite screen looks for installed plugins only where WordPress keeps them, so a site that moved its content or plugin folder is read correctly.
* The Forge Suite licence panel finds Form Forge again: its licence code now ships in Form Forge Pro, so the free plugin is recognised by its own version.
* The Forge Suite menu entry is registered by the shared screen itself, so it appears even on a site where only the newer Forge plugins are active.

= 1.0.37 =
* The Forge Suite dashboard links Guard Forge, Velocity Forge and Flow Forge to their sites: guardforge.app, velocityforge.app and flowforgewp.app.

= 1.0.36 =
* **This release needs Field Forge Pro 1.1.0 or newer.** An older add-on is switched off whole rather than left running, because beside this core it would be present and wrong rather than absent. Until you update it the Pro field types Repeater, Group, Flexible Content and Clone, Options Pages, the REST and GraphQL exposure and the AI actions are unavailable. Nothing already saved is changed, an admin notice names both versions and what stopped, and installing the current add-on brings all of it back.
* Deleting the last Forge product on a site now clears the job queue the Forge plugins share — its table, its two scheduled events and its version marker. While any other Forge product is still installed, deleting this one leaves the queue exactly as it is, because the pending jobs in those rows are that product's too.
* Fixed: in a group laid out in columns, the buttons under an image field ran past the column and the "Remove" button was cut in half. They wrap now, and the preview never outgrows the column it sits in.

= 1.0.35 =
* Fixed: posts saved by 1.0.25–1.0.33 could hold a nested Group, Repeater or Flexible Content as a separate top-level field, which left it out of its parent group in the editor. Updating moves those records back where they belong, in the background. The repair only moves a record whose parent is unambiguous and already on the post; anything it cannot prove it leaves exactly as it is.

= 1.0.34 =
* Fixed: on a site migrated from ACF the post editor drew every custom field empty while the site itself still rendered the values, and pressing Update then blanked the page. The editor now reads the same values the site reads, and the first save moves them into Field Forge's own storage.
* Fixed: a Repeater, Group or Flexible Content nested inside a group could be saved as a separate top-level field, so it disappeared from its parent.

= 1.0.33 =
* Fixed: values in a Group, Repeater or Flexible Content field were dropped when a post was saved from the editor — an image picked into a group showed its preview and was empty again after Update. Simple fields were never affected. Introduced in 1.0.25; if you saved compound fields since then, re-enter and save those values once.

= 1.0.32 =
* Forge Suite dashboard: results are the first screen — each tool's own results with window and completeness, detected and confirmed apart, a Needs-attention filter and a local CSV export for administrators.
* Set discounts in the Suite banner follow the three-step ladder (2 tools 15%, 3 tools 25%, 4 or more 35%).
* Translations refreshed for all catalogues.

= 1.0.31 =
* Licensing no longer depends on a third-party SDK. The plugin asks avakode.com whether this site is licensed and caches the answer for a day; if the check cannot be completed — a network hiccup, a timeout, our own error — your paid features stay on. Only a clear “this licence is not active” turns them off.
* Deactivating from the Forge Suite dashboard now releases the site slot directly, instead of the three-step fallback the old SDK needed when a licence had been cancelled server-side.
* Smaller package and one less admin surface: the SDK’s own menu, opt-in screen and promotional notices are gone.

= 1.0.30 =
* Forge Suite dashboard: names of the builder-rail tools (Clearway, Profit, Inclusive Forge) no longer truncate next to the “Not installed” badge.

= 1.0.29 =
* The Forge Suite dashboard now shows the whole seven-tool line-up from the product registry — Clearway Forge, Profit Forge and Inclusive Forge join the four WordPress tools — counts active tools against seven, and its cross-sell banner points at the Forge Builder on avakode.com (one checkout, set discount up to 45%) instead of the retired Freemius bundle.

= 1.0.28 =
* The shared inline assets (docs link, feedback widget) are now emitted as a literal nowdoc block instead of being assembled in an output buffer — the same hardening Lang Forge 1.0.31 and Rank Forge 1.1.3 received.
* Lang Forge is detected by its current class name (LANGFORGE_Core), so field-value language sync, the migration helper and the shared dashboard cards keep working with Lang Forge 1.0.31 and later.
* The Bundle License card no longer shows the Connect result twice; translations synced.

= 1.0.27 =
* Declares support for WordPress 7.1. Checked against 7.1-RC3: the field-group builder's drag-and-drop still works there, jQuery UI having gone to 1.14.2.
* The sibling plugin formerly called SEO Forge is now Rank Forge, so the shared Forge screens and the cross-links name it correctly.

= 1.0.26 =
* The directory listing now names what the plugin does alongside the brand, matching how Lang Forge is listed. The plugin, its folder and its URL are unchanged — only the displayed title.
* Japanese: parentheses in running text are half-width with a space outside, following the Japanese translation style guide. Chinese: parentheses are full-width, as the WordPress core Chinese catalogue writes them.

= 1.0.25 =
* Fixed a database error printed on every activation. The longtext and text columns were declared with DEFAULT '', which MySQL does not allow on BLOB/TEXT, so dbDelta kept trying to set it and failed loudly. Found by activating with WP_DEBUG on a clean install.


= 1.0.24 =
* Local JSON now writes only to the uploads directory. A theme folder is no longer a write target even when the developer created one — wp-content/themes is not a location a plugin may write to. Files already committed under a theme are still read, so existing setups keep working; a filtered save path that points at a theme, plugin or core directory falls back to uploads.
* The metabox save path no longer passes the whole request array on. Only this plugin's own submitted values are read, reduced to the fields that belong to the post, and each is sanitized by its declared field type before anything downstream sees it.
* Renamed the two ACF-migration options off the reserved "_fdf_" prefix onto "fieldforge_". Existing values, including the ACF-group id map, are carried over by a schema migration, so a site that already imported from ACF does not re-import duplicates.
* ACF's own hooks are consulted only when ACF is actually active.

= 1.0.23 =
* The Gallery field and the Calculation field are now part of this plugin with no restriction. Both were marked Pro while their implementations shipped here, which meant built-in functionality was gated — that was wrong and is fixed.
* Options-page values, the Import / Export screen and the ACF importer are likewise unrestricted. Nothing shipped in this download is withheld any more: features that genuinely belong to the separate Pro add-on are detected by whether that plugin is installed, not by a licence check.
* Field definitions received over AJAX and REST are now sanitized key by key before storage, instead of only their conditional-logic block.
* oEmbed previews are escaped at the output site with an explicit tag allowlist.
* Local JSON now writes to the uploads directory by default and never creates a directory inside a theme. An existing <theme>/fieldforge-json is still used when the developer has created one.
* Admin CSS moved out of inline <style> blocks into the enqueued stylesheet.
* Removed the red counter bubble on the License menu item — it reused core's update-notification styling.
* Field-group schema REST reads now require manage_options, and the aggregate endpoint no longer accepts an arbitrary post status.
* Dropped the manual text-domain loading call; WordPress loads the translations by itself.

= 1.0.22 =
* Security hardening: all dynamic output is now escaped late at the output site with the context-appropriate function (esc_html/esc_attr/esc_url, esc_html__ for translated strings used as format strings, and wp_kses for trusted pre-built admin/field markup). No behavioural changes.

= 1.0.21 =
* Local JSON sync is now available on the Free plan (like ACF's Local JSON) — enabled by the setting alone, no license required.
* ACF value migration (importing existing ACF field values) is now available on the Free plan.
* Field values are now exposed on the standard REST post endpoints for every plan (opt-in per field).
* Removed the leftover license-gated field-group count limit and its "locked" UI — Free has always supported unlimited field groups.

= 1.0.17 =
* New: Support menu item that opens the Avakode support dashboard.
* New: Opt-in anonymous usage analytics (OFF by default) — see Third-Party Services.
* New: Contextual, dismissible Pro feature tips on the plugin dashboard (Free users only).
* New (Pro): Calculation field — compute a total from a formula over sibling fields ({price} * {qty}) or by summing a numeric sub-field across repeater rows, with number/currency/percentage formatting and a live per-keystroke preview.
* New (Free): [fieldforge_total] shortcode and fieldforge_aggregate_field() to total a numeric field across posts; REST /aggregate and GraphQL fieldForgeAggregate (Pro).


= 1.0.16 =
* Accessibility: Button Group field radios are now keyboard- and screen-reader-accessible. They were hidden with `display:none`, which removed them from the tab order and accessibility tree; they are now visually hidden the accessible way (the visible button label still toggles the selection).

= 1.0.14 =
* WordPress.org compliance and licensing hardening.
* Pro entitlement is now resolved by the Field Forge Pro add-on; the free plugin bundles no licensing SDK.
* readme metadata cleanup.

= 1.0.0 =
* Initial release.

== Upgrade Notice ==

= 1.1.0 =
Still needs Field Forge Pro 1.1.5 or newer if you run the add-on. Local JSON Sync no longer reads the theme folder on its own; see the changelog for how to add it back. Saved field groups are not changed.

= 1.0.41 =
Still needs Field Forge Pro 1.1.5 or newer if you run the add-on. The empty Field Groups list now points ACF users to the migration screen. Nothing already saved is changed.

= 1.0.40 =
Deleting the plugin leaves the job queue shared by the Forge plugins alone while another one is still installed. If you run Field Forge Pro, it must be 1.1.5 or newer.

= 1.0.39 =
Needs Field Forge Pro 1.1.5 or newer if you run the add-on: the licence screen moved into it, and an older add-on stays switched off until it is updated. Nothing already saved is changed.

= 1.0.38 =
Still needs Field Forge Pro 1.1.0 or newer. The "matches pattern" condition no longer changes PHP settings while it runs; results are the same.

= 1.0.37 =
Needs Field Forge Pro 1.1.0 or newer — an older add-on is switched off whole, so the Pro field types, Options Pages, REST and GraphQL exposure and AI actions stop until you update it. Nothing already saved is changed. Also fixes image-field buttons cut off in column layouts.

= 1.0.36 =
Needs Field Forge Pro 1.1.0 or newer — an older add-on is switched off whole, so the Pro field types, Options Pages, REST and GraphQL exposure and AI actions stop until you update it. Nothing already saved is changed. Also fixes image-field buttons cut off in column layouts.

= 1.0.35 =
Repairs nested Group, Repeater and Flexible Content records that older versions filed at the top level. Runs once, in the background, after the update.

= 1.0.34 =
Fixes empty fields in the editor on sites migrated from ACF, and the blank page that followed the next Update.

= 1.0.33 =
Fixes silent data loss: Group, Repeater and Flexible Content values were not saved from the post editor. Update, then re-save any compound field you edited since 1.0.25.

= 1.0.17 =
Adds a Support menu, optional anonymous analytics (off by default), and dashboard Pro tips. New Pro Calculation field + cross-post totals.


= 1.0.16 =
Accessibility fix for the Button Group field (keyboard / screen-reader support).

= 1.0.14 =
Licensing and WordPress.org compliance improvements.

= 1.0.0 =
Initial release.
