=== ID Popup ===
Contributors: indesignmedia
Tags: popup plugin, responsive popup, roadblock, woocommerce popup
Requires at least: 5.6
Tested up to: 6.7
Stable tag: 1.5
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Professional WordPress popup plugin — display responsive image popups with advanced display rules, WooCommerce support, and flexible scheduling.

== Description ==

**ID Popup** is a powerful, lightweight WordPress plugin for displaying fully customizable and responsive image popups on your website. Built on a **Custom Post Type** architecture, you can create and manage **unlimited independent popups**, each with their own settings, display rules, and scheduling.

Whether you're running a flash sale, announcing a new product, or displaying a promotional banner, ID Popup gives you complete control over when, where, and to whom your popups appear.

### Key Features

**Multiple Popups**
* Create unlimited independent popups, each with their own individual settings.
* Manage all popups from a dedicated **Popups** menu in the WordPress admin.

**Smart Display Rules**
* Show on the **Entire Website**, **Home Page Only**, **All Pages**, or **All Single Posts**.
* Target **Specific Page(s)** or **Specific Post(s)** using a live-search Select2 picker.
* **WooCommerce Support**: Display on **All Product Pages** or target **Specific Product Page(s)** — only shown when WooCommerce is active.

**Responsive Image Support**
* Upload separate images for **Desktop** and **Mobile** devices via the native WordPress Media Library.
* If no mobile image is set, the popup is automatically **suppressed on mobile devices**.
* If no desktop image is set, the popup is automatically **suppressed on desktop devices**.
* Remove images with a single click using the built-in remove (×) button.

**Popup Scheduling**
* Set independent **Start Date & Time** and **End Date & Time** for each popup.
* Each date bound is evaluated independently — set only a start date, only an end date, or both.

**Appearance & Behavior**
* Configurable **Delay Before Opening** (default: 3 seconds).
* Auto-close timer — set to 0 to disable auto-close entirely (default: 15 seconds).
* Customizable **Overlay Color** and **Overlay Opacity**.
* Linkable popup image with **Target URL** (opens in a new tab, with `rel="noopener noreferrer"`).
* **Desktop Max Width** control in pixels (default: 900px).

**Native WordPress Integration**
* Built on WordPress **Custom Post Type** — no custom database tables.
* Uses the native **WordPress Media Uploader** — no third-party upload dependencies.
* **Select2** live search for selecting specific pages, posts, or products.
* Automatic one-time **data migration** from older single-setting versions.

### Use Cases
* Flash sales and limited-time promotions
* New product announcements
* Email list opt-ins and lead capture
* WooCommerce product-specific upsells
* Event announcements and countdowns
* Site-wide notices and alerts

== Installation ==

1. **Upload the Plugin**
   * Download the plugin ZIP file.
   * Go to **Plugins > Add New > Upload Plugin** in your WordPress admin.
   * Select the `id-popup.zip` file and click **Install Now**.

2. **Activate the Plugin**
   * Click **Activate** after installation.

3. **Create Your First Popup**
   * Navigate to **Popups > Add New** in the WordPress admin sidebar.
   * Give your popup a title, upload images, configure display rules and scheduling, then click **Publish**.

4. **Adding More Popups**
   * Go to **Popups > Add New** again. Each popup is fully independent with its own settings.

== Frequently Asked Questions ==

= Can I create multiple popups? =

Yes! Version 1.4 introduced a full **Custom Post Type** architecture. You can create unlimited independent popups, each with its own images, display rules, and schedule, all managed from the **Popups** menu in your admin sidebar.

= Can I use different images for desktop and mobile? =

Yes. You can upload separate images for desktop and mobile in the **Media Setup** section of each popup. If one is missing, the popup is automatically hidden on that device type — no broken images, no empty containers.

= Can I schedule the popup to appear only on specific dates? =

Yes. Set a **Start Date & Time** and/or **End Date & Time** for each popup. Each boundary is evaluated independently — you can have an end-date-only popup that phases out on a deadline without requiring a start date.

= Can I target specific pages, posts, or WooCommerce products? =

Yes. Use the **Display Rules** dropdown to select **Specific Page(s)**, **Specific Post(s)**, or (if WooCommerce is active) **Specific Product Page(s)**. A live Select2 search lets you search and choose items by name without needing to know their IDs.

= Does it work with WooCommerce? =

Yes. When WooCommerce is active, two additional display rules appear in the dropdown: **All Product Pages** and **Specific Product Page(s)**, allowing you to target your WooCommerce store with surgical precision.

= How does Auto Close work? =

The **Auto Close After (s)** field sets a timer in seconds after which the popup automatically closes. Set it to **0** to disable auto-close entirely and keep the popup open until the user manually closes it.

= What happens if I had the old single-settings version installed? =

The plugin automatically detects and migrates your old settings into a new popup post called "Default Popup" on the first admin load after upgrading. No data is lost.

== Changelog ==

= 1.5 =
*Released: March 2026*
* Updated short description and tags.
* Synchronised plugin version with stable tag.

= 1.4 =

**Security Hardening**
* Added `wp_die()` after `wp_send_json_error()` in AJAX handler to prevent continued execution after unauthorized access.
* Whitelisted the `type` parameter in the AJAX search handler against known post types — unknown types are rejected with `wp_die()`.
* Switched `popup_link` sanitization from `sanitize_text_field()` to `esc_url_raw()` — correct WordPress standard for URL fields stored in the database.
* Added strict allowlist validation for `display_rules` using `in_array()` with type checking.
* Cast all `specific_ids` to integers using `intval` — eliminates any possibility of string injection through ID fields.
* Applied `esc_html()` to post titles and `absint()` to IDs in AJAX JSON responses.
* Applied `esc_attr()` to `desktop_max_width` in inline style output.

**Bug Fixes**
* Fixed auto-close value of `0` not working — `parseInt(0) || 15000` was incorrectly evaluating to `15000`. Now uses `isNaN()` check so `0` correctly disables auto-close.
* Fixed mobile skip logic — `data()` returns a string but was compared with `=== 0` (integer). Wrapped with `parseInt()` for correct type coercion.
* Fixed scheduling logic — previously required both start AND end dates to evaluate; now each date boundary is checked independently.
* Removed dead `$preview_style` PHP variable that was computed but never used.

**Performance**
* Added `no_found_rows: true` and `update_post_term_cache: false` to the frontend `WP_Query` to skip unnecessary database queries.
* Popup HTML is now skipped in PHP entirely if neither desktop nor mobile images are set.

= 1.3 =
*Released: March 2026*

**New: WooCommerce Display Rules**
* Added **All Product Pages** display rule — shows popup on any WooCommerce single product page.
* Added **Specific Product Page(s)** display rule — target individual WooCommerce products by name using the Select2 search interface.
* WooCommerce rules are only rendered in the admin dropdown when WooCommerce is active (`class_exists('WooCommerce')`).
* AJAX search handler now supports `product` post type when `specific_products` rule is selected.

**Select2 Improvements**
* Placeholder text dynamically updates based on selected display rule: "Search pages…", "Search posts…", or "Search products…".
* Select2 search field now appears for `specific_products` rule in addition to `specific_pages` and `specific_posts`.

**Display Rule Precision**
* "All Single Posts" now uses `is_singular('post')` instead of `is_single()` — correctly excludes custom post types and WooCommerce products.
* "Specific Post(s)" rule now uses `is_singular('post')` + `get_queried_object_id()` matching — consistent with the specific pages and products pattern.
* "Specific Page(s)" now uses `get_queried_object_id()` for ID matching instead of passing an array to `is_page()`.

= 1.2 =
*Released: March 2026*

**Multiple Popups Architecture (Major Feature)**
* Migrated from a single WordPress Options API settings page to a **Custom Post Type** (`id_popup`).
* Each popup is now an independent WordPress post with its own title, settings, and lifecycle.
* Added dedicated **Popups** menu item in the WordPress admin sidebar with a custom dashicon.
* Three separate native WordPress Meta Boxes replace the single settings form: **Media Setup**, **Display Rules & Scheduling**, and **Appearance & Behavior**.
* Meta box headers styled with the plugin's red theme using CSS targeting native WP postbox elements.
* Added automatic one-time data migration from the old `id_popup_settings` option into a new "Default Popup" post — no data loss on upgrade.

**Frontend Multi-Popup Support**
* Frontend now uses `WP_Query` to loop all published `id_popup` posts.
* Each popup evaluated independently for scheduling and display rules.
* HTML output switched from singleton IDs (`#id-popup`) to classes (`.id-popup-container`, `.id-popup-overlay`) to support multiple simultaneous popups on one page.
* Per-popup delay and auto-close timings passed via `data-delay` and `data-autoclose` attributes — no global JS variables.

**Image Handling**
* Each popup independently skips rendering if no image is configured for the current device type.
* Device detection (`data-has-desktop`, `data-has-mobile`) evaluated fresh per popup per page load.

= 1.1 =
*Released: March 2026*

**WordPress Media Library Integration**
* Replaced plain URL input fields with the native **WordPress Media Uploader**.
* Plugin now stores WordPress **Attachment IDs** instead of raw image URLs — more robust, survives media library reorganization.
* Image URLs are dynamically resolved at render time using `wp_get_attachment_image_url()`.
* Added `attachment_url_to_postid()` fallback for any legacy string URL values still in the database.
* Added live image previews in the admin for both desktop and mobile images.
* Added remove (×) button on image thumbnails — clears the attachment ID and hides the preview without a page reload.

**Display Rules Expansion**
* Added **All Pages** display rule.
* Added **All Single Posts** display rule.
* Added **Specific Page(s)** display rule with Select2 live search.
* Added **Specific Post(s)** display rule with Select2 live search.
* "Specific Page/Post" field dynamically shows/hides based on the selected rule (hidden by default).

**Select2 Integration**
* Integrated Select2 library for the specific page/post ID selection.
* AJAX-powered live search for pages and posts.
* Selected items displayed as removable pill tags.
* Automatically clears selections when an incompatible display rule is chosen.

**Field Defaults**
* Desktop Max Width defaults to 900px.
* Auto Close defaults to 15 seconds.
* Delay Before Opening defaults to 3 seconds.
* Target URL defaults to `#`.

= 1.0 =
*Released: 2024*

* Initial release.
* Responsive popup image support for desktop and mobile.
* Popup scheduling with start and end dates.
* Display location control: entire site, homepage, or single post.
* Overlay color and opacity controls.
* Linkable popup image.
* Auto-close timer.
* Popup delay setting.

== Upgrade Notice ==

= 1.5 =
Minor update to readme description and tags for repository compatibility.

= 1.4 =

= 1.2 =
Major architecture upgrade introducing multiple popup support via Custom Post Type. Your existing settings are automatically migrated to a new "Default Popup" post on first admin load — no manual steps required.

== Screenshots ==

1. **Popup List** — The Popups admin screen showing all created popups with status.
2. **Media Setup** — Upload desktop and mobile images using the WordPress Media Library with live preview and remove button.
3. **Display Rules** — Dropdown with all targeting options including WooCommerce product rules.
4. **Appearance & Behavior** — Configure delay, overlay, auto-close, and target URL.
5. **Live Popup** — Example of the popup displayed on the frontend with overlay.

== Support ==

For assistance, documentation, or to report bugs, visit the [ID Popup Support Page](https://indesignmedia.net/contact-us/).

For further documentation and usage guides, please visit our [official documentation](https://indesignmedia.net/plugins/id-popup).

== License ==

ID Popup is licensed under the **GPLv2** or later. You can freely redistribute and modify it as per the terms of the license.

The full license can be found here: [GPLv2 License](https://www.gnu.org/licenses/gpl-2.0.html)
