== Changelog ==

= 1.17.22 =
* Restyled the public file upload field with a modern drag-and-drop area, upload button, selected-file list, and remove action.
* Added independent English and Arabic upload title, helper text, and button labels in the form builder.
* Keep existing file upload limits and String attachment synchronization unchanged.

= 1.17.21 =
* Fixed PHP 8+ file uploads by passing the upload array to wp_handle_upload() by reference-compatible variable.
* Fixed the WordPress admin menu icon selector so The String CRM icon is visible on all wp-admin screens.
* Route multipart submission uploads through the WordPress HTTP and Filesystem APIs instead of direct cURL calls.
* Use prepared identifier placeholders for submission table queries and WordPress file deletion helpers for temporary exports.
* Escape dynamic admin output and add translator comments for strings with placeholders required by Plugin Check.

= 1.17.17 =
* Enqueue content mapping and notice cleanup scripts through WordPress.
* Sanitize submission input and restrict filter context to validated form values.
* Leave duplicate plugin activation choices to administrators.

= 1.17.16 =
* Harden database queries for WordPress.org security scanning and use prepared identifier placeholders.
* Fix non-literal translation calls for WordPress internationalization compatibility.

= 1.17.15 =
* Fixes HPOS/admin live-order auto sync when an early incomplete save fails before billing identity or line items are complete.
* Live order fingerprints now include billing email/phone/country/address and line-item identity, quantity and totals.
* Failed foreground sync attempts are no longer memoized, so later hooks in the same request retry immediately instead of waiting for cron/manual Sync Now.
* Phone-only guest orders can recognize unambiguous international numbers entered without a leading plus sign (for example 962...).
* Queues/backfill remain fallback/repair paths; successful live saves still deduplicate repeated hooks in the same request.

= 1.17.14 =
* Make WooCommerce new/update order hooks perform an immediate String sync instead of only queueing work.
* Make HPOS `woocommerce_after_order_object_save` and `woocommerce_order_object_updated_props` use the immediate order-sync path.
* Keep the persistent queue, Action Scheduler/WP-Cron, shutdown processor, and retry hooks as fallbacks only when the immediate String request fails or is rate-limited.
* Preserve one String Client per matched email/phone while keeping each WooCommerce order isolated by its own order-specific Submission ID/integration ID.
* Queue one repair backfill after upgrade so orders missed by older queue-only live hooks are reconciled automatically.

= 1.17.13 =
* Fix WooCommerce order notes that some admin/REST flows report as `system`; String now syncs them instead of silently discarding them.
* Verify notes returned by the String Submission API and append only note lines that are actually missing, preventing both false-success and duplicate note snapshots.
* Add direct REST/comment note hooks plus one-time reconciliation so note auto-sync does not depend on the normal order-save lifecycle.

= 1.17.12 =
* Sync WooCommerce customer/manual order notes to the linked String Submission on create and later note changes.
* Listen to order-note add/delete hooks so note synchronization is automatic and does not depend on Sync Now.
* Ignore WooCommerce-generated system notes and preserve 1.17.11 live order/customer/product synchronization behavior.

= 1.17.11 =
* Orders / Submissions no longer fail just because a WooCommerce product needs a String currency lookup.
* Existing String products are resolved before currency lookup and are attached with their WooCommerce sub-category using a minimal product update that does not require currency.
* A product/category dependency failure no longer blocks the base Submission, status, price, or WooCommerce Additional Data; the plugin records a warning and retries the product attachment automatically.
* Added direct final-save synchronization for WooCommerce orders, products, and customers while retaining the persistent queue as a retry/fallback path.
* Added a one-shot repair backfill for existing Orders / Submissions mappings.

= 1.17.10 =
* Resolve WooCommerce order currency by exact String currency-code search with forced-cache fallback.
* Make order status re-sync idempotent when the Submission already has the mapped status.
* Queue one repair backfill after upgrade so previously blocked WooCommerce orders retry automatically.

= 1.17.9 =
* Orders -> Submissions no longer requires a Products mapping. Each Woo order line item resolves its own product_cat hierarchy automatically, creates/reuses the String parent Category and Sub-category, creates/reuses the String Product, then sends category_ids + product_ids with the Submission.
* Woo top-level-only product categories are safely placed under one stable WooCommerce Products parent because String products require a sub-category.

= 1.17.8 =
* Fix upgrade packaging so WordPress replaces the existing plugin directory instead of installing a duplicate copy.
* Fix internal plugin version/duplicate-activation guard to match the installed release.
* Fix WooCommerce Order -> Submission product attachment so line-item products are always resolved and attached automatically.
* Force on-demand product sync to bypass bulk catalog filters for products that were actually purchased.
* Persist WooCommerce status -> String status IDs locally and add a cross-request creation lock to prevent duplicate status creation during live order sync.
* Make the configured Lead Journey mapping authoritative for order status resolution; fallback defaults are only used when no Lead Journey mapping exists.
* Queue a one-time order reconciliation after upgrade.

= 1.17.5 =
* Live WooCommerce sync no longer depends on Action Scheduler/WP-Cron: final order/product/customer saves are processed at request shutdown with persistent retry queues as fallback.
* Added HPOS/admin/REST order save hooks and one-time reconciliation for orders missed by older versions.

= 1.17.4 =
* Make WooCommerce live sync truly automatic: new/updated orders, customers, products, and mapped services are queued through WooCommerce Action Scheduler with WP-Cron fallback; no manual **Sync Now** is required.
* Add checkout-complete order hooks for classic and Store API checkout flows.
* Apply order products before the final String status transition, then use the dedicated Submission status endpoint so Stage/Status history is updated reliably.
* Treat an order line item as strong sync intent: an enabled Product mapping is applied on demand even when normal catalog filters would exclude that purchased product.
* Retry transient/non-rate-limit order dependency failures automatically instead of silently dropping the queued order.
* Auto-create/reuse the WooCommerce Orders Stage/status mapping on demand when Orders sync is enabled without a separate Lead Journey card.
* One-time upgrade repair re-syncs existing WooCommerce orders and turns product attachment on for previously created Orders mappings.

= 1.17.3 =
* Prevent fatal redeclaration errors when an older duplicate The String CRM installation is still present or active.
* Automatically deactivates duplicate active copies while keeping the current plugin installation active.

= 1.17.2 =
* Fix WooCommerce Order → Submission linkage when the order is synchronized before catalog/workflow backfills finish.
* Resolve/create the mapped String status on demand for the current WooCommerce order status.
* Resolve/synchronize mapped WooCommerce products on demand and attach their String product IDs to the Submission.
* Queue one dependency-ordered repair backfill on upgrade from earlier versions so existing synced orders receive their missing status/products.


= 1.17.1 =
* Packaging fix: keep the existing plugin directory so WordPress upgrades/replaces the active plugin instead of installing a duplicate copy.
* Includes all WooCommerce customer/order sync functionality from 1.17.0.

= 1.17.0 =
* Add **Customers / Contacts** Content Sync for registered WooCommerce customers. Customers are matched to existing String clients by email/phone before a new Contact is created.
* Add **Orders / Submissions** Content Sync with a required String Branch and no dependency on a separate customer mapping.
* Every WooCommerce order automatically resolves or creates its related String client from billing email/phone, including guest-checkout orders.
* Group multiple WooCommerce orders for the same email/phone under the same String client/Lead while keeping one separate Submission per order.
* Stop conflicting orders safely when the email and phone point to different String clients.
* Map WooCommerce order status to the String status created by the Lead Journey mapping, attach already-synced String Products when available, and send the order total as the Submission manual price.
* Persist the remote String Submission ID on the WooCommerce order so repeat syncs update the same Submission rather than creating another one.
* Add rate-limited background queues for future WooCommerce order/customer changes and rate-limited backfill for existing customers/orders.

= 1.16.0 =
* Add **Lead Journey — Stages / Statuses** as a Content Sync mapping entity for WooCommerce order statuses.
* Create or reuse one String Stage by bilingual name, then create/update enabled WooCommerce statuses under it.
* Let administrators map each WooCommerce status to an English/Arabic String status name and an explicit String status type.
* Give every synchronized status a stable WordPress/WooCommerce `integration_id` so repeat syncs update instead of duplicating.
* Process workflow synchronization through the same adaptive partner rate-limit batching used by large catalog backfills.
* Require `workflow.read` / `workflow.write` for this mapping; WooCommerce Orders → String Submissions remains intentionally deferred to the next step.

= 1.15.2 =
* Sync taxonomy-backed Categories from the complete WordPress taxonomy catalog, including terms with zero assigned posts/products.
* Keep new/edited empty taxonomy terms synchronized automatically while respecting the partner API rate limit.

= 1.15.1 =
* Fix category taxonomy sync so multiple assigned WordPress/WooCommerce terms are created as separate String sub-categories instead of a single comma-separated child name.
* Keep the existing simple mapping UI: fixed parent + taxonomy child is supported without extra hierarchy controls.
* Store all resolved remote category IDs locally while preserving one deterministic primary category for String Product compatibility.


= 1.15.0 =
* Large Content Sync jobs are split automatically into API-safe batches using the Business Partner `rate_limit_per_minute` returned by String.
* Each sync window uses only 70% of the configured partner request limit, leaving headroom for normal site/API activity.
* Backfills track the real number of String API requests made, pause before exhausting the safe budget, and resume automatically in the next one-minute window.
* HTTP 429 remains a fallback safety path: the current item is preserved and retried after `Retry-After` instead of being marked failed.
* Future post/product create and update events now enter the same shared rate-limited queue instead of making immediate API calls, so bulk imports cannot create request bursts.
* Dependency mappings are processed in order (Categories/Sub-categories before Services and Products), and large 1k+ catalogs remain resumable across cron runs.

= 1.14.9 =
* Added optional per-mapping WordPress filters so only matching posts/products are synchronized to String.
* Filters support custom fields and taxonomies with equals, contains, one-of, empty/non-empty, and inverse operators.
* Taxonomy filter values use visible term names and show selectable existing terms.
* Backfill now reports filtered-out items as skipped instead of failed, and future create/update sync respects the same filters.


= 1.14.8 =
* Reduce External Partner API usage during Content Sync to avoid unnecessary 429 rate limits.
* Category-only mapper pages no longer fetch unrelated Products, Services, Currencies, Brands, Branches, or Users catalogs.
* Cache remote catalog collections briefly and reuse them across backfill batches.
* Category hierarchy sync reuses cached parent/child rows, avoids redundant refetches, and only PATCHes a category when its mapped data actually changed.
* Existing 429 pause/resume behavior remains enabled; rate-limited items are paused rather than counted as failed.

= 1.14.7 =
* Category hierarchy mappings now dereference WordPress term/post IDs and structured relationship values to their visible names before creating String categories.
* Field discovery shows relationship samples as ID → resolved name where possible, and taxonomy sources are clearly labeled as term-name mappings.
* Backfill is rate-limit aware: HTTP 429 pauses and resumes automatically instead of counting queued items as permanent failures.
* Future create/update sync retries automatically after partner API rate limits.

= 1.14.6 =
* Added Categories / Sub-categories as a first-class Content Sync mapping target.
* Map a WordPress field/taxonomy such as Make to the String parent Category and another such as Model to the String Sub-category.
* Category mappings create or update the required String parent/child hierarchy with stable integration IDs and reuse matching existing String categories when possible.
* Product Sub-category mapping can now choose “Use synced sub-category from Category mapping”; the plugin resolves/creates the dependency before creating or updating the Product.
* Existing published items are included in the same automatic backfill, and future WordPress creates/updates continue to sync automatically.
* Added preflight validation for missing/same Parent Category and Sub-category values and for missing Category mapping dependencies.

= 1.14.5 =
* Content Sync mapper now discovers WordPress taxonomies in addition to post meta/ACF keys.
* Mapping dropdowns show sample values from published content so fields such as make, category, and model are easier to identify.
* Catalog mappings can resolve String categories, brands, currencies, services, and relations from WordPress taxonomy terms.
* Required mapping preflight now reports the actual WordPress source value that failed to match a String catalog value.

= 1.14.4 =
* Show the exact per-post Content Sync backfill failures directly on the Content Sync screen.
* Improve Product/Service catalog mapping when WordPress/ACF fields store taxonomy term or post IDs: resolve the WordPress object name/slug first, then match it to the String catalog; only use a numeric value as a String ID when that ID actually exists.
* Clarify catalog mapping labels to support String ID, name, or code matching.

= 1.14.2 =
* Rebuilt Content Sync as a compact two-column field mapper: String Product/Service fields on the left and WordPress fields/custom keys on the right.
* String entity is selected first; only Product or Service fields for the active target are submitted.
* Selecting a WordPress post type now fetches its available custom-field/meta keys automatically, including ACF field definitions when available.
* Preserves all existing Product/Service sync behavior, multilingual resolution, existing mapping settings, backfill, and future create/update synchronization.
* WooCommerce-specific source fields are shown only when a WooCommerce Product post type is selected.

= 1.14.1 =
* Added multilingual-aware Product/Service Content Sync for WPML, Polylang, and TranslatePress.
* Normal title/content mappings now resolve English and Arabic translations automatically when available.
* Single-language sites safely mirror the available Product/Service name into both `name.en` and `name.ar`; descriptions use the same fallback unless a language is explicitly set to Do not sync.
* Explicit English/Arabic custom-field and static mappings keep highest priority over automatic multilingual discovery.
* WPML/Polylang translation siblings now share one stable Content Sync `integration_id`, preventing translated posts from creating duplicate String Products/Services.
* Added extension filters so other multilingual plugins can provide translation IDs/values without replacing the sync engine.

= 1.14.0 =
* Expanded Content Sync to cover every field currently accepted by the String External Partner Product and Service create/update APIs.
* Product mapping now includes bilingual name/description, price, SKU, quantity, category, currency, brand, address/location, phone/WhatsApp/email, status, working hours, Google Map URL, Product URL, branches, users, related services, and related products.
* Service mapping now includes bilingual name/description, price, parent service, expiry, insurance, reminders, upsell, instructions, Service URL, related services/products/users, plus prepared advanced duration/share-button mappings.
* Added WordPress featured-image, attached-media, WooCommerce main-image/gallery, and custom-media-reference mapping. Media URLs are prepared in the payload; actual remote attachment requires corresponding String External Partner API media support.
* Enabling Content Sync now automatically queues a complete backfill of all existing published mapped content; future published creates/updates continue syncing automatically.
* Added a visible backfill progress summary and safe full re-sync action.
* Expanded Content Sync catalog loading to Categories, Currencies, Brands, Branches, Users, Services, and Products.
* Fixed duplicate catalog API loading on the Content Sync settings screen and improved cleanup of background sync state on deactivation/uninstall.

= 1.13.4 =
* Renamed the public plugin branding from String Form to The String CRM.
* Kept the existing `string-form` plugin folder, text domain, shortcodes, database keys, and internal identifiers for backward compatibility.

= 1.13.3 =
* Fixed custom builder fields not being persisted in String Additional Data.
* Unmapped WordPress fields are now sent under `attribute[...]`; native String fields and explicitly mapped String Field Keys remain top-level.
* Preserved UTM attribution in the dedicated `utm[...]` payload and merged click IDs/integration provenance without overwriting custom attributes.
* Additional phone fields now reliably remain Additional Data unless explicitly mapped to a native String field.

= 1.13.2 =
* Fixed fatal errors/memory exhaustion when submitting forms with file uploads.
* File-bearing String submissions now stream attachments from disk instead of loading binary files into PHP memory.
* Multiple File Upload fields are merged into one attachments collection without changing their String upload contract.
* Added graceful transport errors when PHP cURL is unavailable instead of crashing the form submission.

= 1.13.1 =
* Appointment Branch/Product/Services controls now follow the public form language and direction.
* Appointment Services use a multi-select dropdown instead of inline checkboxes.
* Appointment options support editable English and Arabic public labels while preserving String IDs.


= 1.13.0 =
* Added configurable Appointment context for Branch, Product, and Services.
* Branch/Product/Service can be preset and hidden or exposed as visitor choices.
* Appointment calendar now loads real String availability through a secure WordPress proxy.
* Appointment slot duration follows the selected String service duration(s).
* Added Services to the editor catalog and appointment relationship filtering.

= 1.12.9 =
* Added Dynamic / Static Data workflow for String Branch and Product fields.
* Select Branch/Product records from String, then generate locked-ID options for the form.
* Added independent English and Arabic labels for every generated Branch/Product option.
* Custom labels can be renamed without changing the String ID submitted for routing.


= 1.12.8 =
* Fixed Grid column drop targets so palette fields and existing fields can be dropped directly into a column.
* Restored pointer interaction inside Grid rows while preserving the normal non-interactive field preview behavior elsewhere.
* Added stronger drag-enter/drag-over handling and clearer active-column feedback.
* Simplified Grid column and 12-unit width-control borders for a cleaner editor appearance.

= 1.12.7 =
* Redesigned Grid columns with a lighter, cleaner editor treatment and editable 12-unit column widths.
* Fields can now be dragged directly from the field palette into a Grid column.
* Existing fields can be dragged into a Grid column, between Grid columns, or back into the normal form flow.
* Added clear per-column drop targets and preserved mobile single-column rendering.

= 1.12.6 =
* Standardized the String routing field label as Product.
* Replaced the placeholder layout marker with a functional Grid Layout component.
* Grid rows support 1, 2, or 3 columns on a 12-unit layout system with configurable column spans that always total 12.
* Fields can be assigned to a grid row and column from Advanced Options, with a live layout preview in the builder.
* Grid columns collapse to a single column on small screens.

= 1.12.5 =
* Fixed the tracking modal so actions from the inactive step stay hidden.
* Replaced generated iframe/embed code with a native `[string_form]` shortcode carrying selected tracking and routing values.
* Routing overrides from generated links/shortcodes now work independently of the general UTM forwarding toggle.
* Empty/default routing values, including department `0`, are no longer added to generated tracking output.

= 1.12.4 =
* Prepared the public package for WordPress.org review.
* Removed remote JavaScript and image dependencies so plugin UI/assets are served locally.
* Removed suppression of other plugins' WordPress admin notices.
* Added a complete external-service and privacy disclosure plus WordPress Privacy Policy Guide text.
* Removes saved String credentials and Content Sync settings on uninstall while retaining business records.
* Added a PHP 7.4-compatible fallback when mbstring is unavailable.

= 1.12.3 =
* Distribution cleanup and documentation normalization for the public plugin package.
* Internal UI identifiers were normalized without changing form behavior or saved data.

= 1.12.2 =
* Form Builder follows the current WordPress admin language.
* Arabic WordPress admin renders the builder UI in Arabic with RTL direction; English remains LTR.

= 1.12.1 =
* Enabled multiple Phone fields, each with independent country and validation settings.
* The canonical phone field remains the main String CRM phone; additional phone fields remain available as additional submission data.

= 1.12.0 =
* Added WordPress-to-String Content Sync with WordPress as the V1 source of truth.
* Map WordPress post types or WooCommerce Products to String Products or Services.
* Added stable integration identifiers and manual Sync Now reconciliation.

= 1.11.7 =
* Fixed the String Form WordPress menu icon outside String Form pages.

= 1.11.3 =
* Added browser and server-side duplicate-submission protection.

= 1.11.2 =
* Added Excel export and a full Submission Profile view.

= 1.11.0 =
* Added optional country-aware phone validation, country filtering, and leading-zero normalization.

== Upgrade Notice ==

= 1.14.6 =
Adds dependency-aware Category/Sub-category hierarchy synchronization before Products, so mappings such as Make → Parent Category and Model → Sub-category can create everything required by the String Product API automatically.

= 1.14.2 =
Replaces the complex section-based Content Sync screen with a direct String-field-to-WordPress-key mapper and automatic custom-field discovery. Existing mappings remain compatible.

= 1.14.1 =
Adds multilingual Product/Service resolution. WPML/Polylang/TranslatePress translations are used when available; single-language content is mirrored safely into both String name languages, and translated post siblings update one remote entity.

= 1.14.0 =
Expands Product/Service mapping and automatically backfills existing published mapped content when Content Sync is enabled. Product/Service media URLs can be mapped now; remote media attachment still requires String External Partner API media support.

= 1.13.4 =
Renames the plugin display branding to The String CRM while preserving existing forms, shortcodes, settings, and integrations.

= 1.12.8 =
Fixes direct Grid drag-and-drop and cleans up Grid width/border styling.

= 1.12.7 =
Improves the Grid editor and adds direct drag-and-drop field placement into columns.

= 1.12.6 =
Adds the functional 12-column Grid Layout builder and standardizes the String Product field label.

= 1.12.5 =
Fixes tracking-link/shortcode generation and modal step actions.

= 1.12.4 =
Recommended for WordPress.org distribution: removes remote static assets and documents String data processing and external-service usage.

