Title: EffortLess Simple Reviews Editor
Author: domclic
Published: <strong>June 14, 2026</strong>
Last modified: June 14, 2026

---

Search plugins

![](https://s.w.org/plugins/geopattern-icon/effortless-simple-reviews-editor.svg)

# EffortLess Simple Reviews Editor

 By [domclic](https://profiles.wordpress.org/domclic/)

[Download](https://downloads.wordpress.org/plugin/effortless-simple-reviews-editor.2.2.3.zip)

 * [Details](https://wordpress.org/plugins/effortless-simple-reviews-editor/#description)
 * [Reviews](https://wordpress.org/plugins/effortless-simple-reviews-editor/#reviews)
 *  [Installation](https://wordpress.org/plugins/effortless-simple-reviews-editor/#installation)
 * [Development](https://wordpress.org/plugins/effortless-simple-reviews-editor/#developers)

 [Support](https://wordpress.org/support/plugin/effortless-simple-reviews-editor/)

## Description

EffortLess Simple Reviews Editor lets visitors submit reviews (pending admin approval)
and displays published reviews in a responsive card grid with infinite scroll.

**Features:**

 * Front-end review submission form with star rating, name, title, and review text
   fields
 * Admin approval workflow — all submissions are set to “Pending”
 * Responsive card grid with configurable columns
 * Infinite scroll (IntersectionObserver) for seamless loading
 * Spam protection: honeypot field + rate limiting (1 submission per 60 s)
 * Accessible star rating with keyboard navigation
 * One-time-use review links — send unique links to clients
 * Programmatic link generation via `elsre_create_review_link()`
 * No external dependencies — pure CSS stars, vanilla JavaScript
 * i18n ready — `.pot` translation template included

### Shortcodes

#### [elsre_reviews] — Display Reviews Grid

Place this shortcode on any page or post to display published reviews.

Attributes:

 * `per_page` (default: `6`) — Reviews per load batch
 * `columns` (default: `3`) — Grid columns on desktop (1–6)
 * `ids` (default: empty) — Comma-separated review IDs; disables pagination
 * `order` (default: `desc`) — Sort order: `desc` for newest first, `asc` for oldest
   first
 * `star_size` (default: `18px`) — Star icon size (any CSS unit)
 * `text_size` (default: `15px`) — Review text font size
 * `name_size` (default: `14px`) — Reviewer name font size

Examples:

    ```
    [elsre_reviews]
    [elsre_reviews per_page="9" columns="3"]
    [elsre_reviews ids="12,45,78" columns="2"]
    [elsre_reviews star_size="28px" text_size="18px" name_size="16px"]
    ```

#### [elsre_form] — Review Submission Form

Place this shortcode on any page or post to display the submission form.

Attributes:

 * `require_token` (default: `no`) — Set to `yes` to require a one-time-use link
   token
 * `star_size` (default: `32px`) — Star icon size in the rating picker

Examples:

    ```
    [elsre_form]
    [elsre_form require_token="yes"]
    [elsre_form star_size="48px"]<h3>One-Time Review Links</h3>
    ```

1. Create a page with `[elsre_form require_token="yes"]`.
 2. Go to **Reviews  Review
Links** in the admin. 3. Click **Generate Link** (optionally add a label for your
reference). 4. Copy the link and send it to your client.

Each link works only once. After the client submits their review, the link is marked
as used.

### Developer Integration

Generate review links programmatically from your own plugin or theme:

    ```
    $link = elsre_create_review_link( 'client@example.com' );
    $link = elsre_create_review_link( 'client@example.com', 'John Doe', 42 );
    ```

 * First parameter: client email (unique identifier — reuses existing unused token
   if found)
 * Second parameter: optional label for admin reference
 * Third parameter: optional page ID containing `[elsre_form]` (auto-detected if
   omitted)
 * Returns the full URL with token, or empty string if no form page found

Check availability before calling: `function_exists( 'elsre_create_review_link' )`

### Admin Pages

#### Reviews List (Dashboard  Reviews)

All submitted reviews are listed here as a standard WordPress post list.
 Extra 
columns show the key review data at a glance:

    ```
    ┌──────────────┬────────┬──────────────┬─────────────┬────────────┐
    │ Title        │ Rating │ Reviewer     │ Date        │ Status     │
    ├──────────────┼────────┼──────────────┼─────────────┼────────────┤
    │ Great hotel! │ ★★★★★  │ Jane Doe     │ 2026-03-01  │ Pending    │
    │ Good service │ ★★★★☆  │ John Smith   │ 2026-02-28  │ Published  │
    └──────────────┴────────┴──────────────┴─────────────┴────────────┘
    ```

Publish a review to make it appear on the front end. Leave it as Pending to
 keep
it hidden until you have reviewed it.

#### Review Edit Screen

Each review has a **Review Details** meta box below the title field:

    ```
    ┌─────────────────────────────────────────┐
    │ REVIEW DETAILS                          │
    ├──────────────┬──────────────────────────┤
    │ Reviewer Name│ Jane Doe                 │
    │ Review Title │ Perfect weekend getaway! │
    │ Rating       │ ★ ★ ★ ★ ★               │
    │ Review Text  │ Fantastic experience...  │
    │ Review Date  │ 2026-03-01               │
    └──────────────┴──────────────────────────┘
    ```

The star picker is fully keyboard-accessible (arrow keys, Enter, Space).

#### Review Links Page (Dashboard  Reviews  Review Links)

Generate one-time-use links to send to specific clients:

    ```
    ┌──────────────────────────────────────────────────────────────┐
    │ GENERATE NEW LINK                                            │
    │  Client Email  [client@example.com          ]               │
    │  Label         [e.g. John's booking         ]  (optional)   │
    │  Form Page     [Leave a Review ▾            ]               │
    │                [ Generate Link ]                            │
    └──────────────────────────────────────────────────────────────┘

    ┌──────────────────────────────────────────────────────────────────────┐
    │ ALL LINKS                                                            │
    ├──────────────┬───────────┬────────┬────────────┬────────┬───────────┤
    │ Email        │ Label     │ Status │ Created    │ Used   │ Actions   │
    ├──────────────┼───────────┼────────┼────────────┼────────┼───────────┤
    │ jane@...     │ Jane Doe  │ Active │ 2026-03-01 │ —      │ Copy Link │
    │ john@...     │ John Smith│ Used   │ 2026-02-28 │ Mar 01 │ Expired   │
    └──────────────┴───────────┴────────┴────────────┴────────┴───────────┘
    ```

After generating, a success banner shows the link ready to copy:

    ```
    ┌─────────────────────────────────────────────────────────────┐
    │ ✓  Link generated! Send this link to your client:           │
    │   https://example.com/review/?elsre_token=abc123  [ Copy ] │
    └─────────────────────────────────────────────────────────────┘
    ```

## Installation

 1. Upload the `effortless-simple-reviews-editor` folder to `/wp-content/plugins/`.
 2. Activate the plugin through the **Plugins** menu in WordPress.
 3. A new **Reviews** menu (star icon) appears in the admin sidebar.
 4. Add `[elsre_reviews]` to a page to display reviews.
 5. Add `[elsre_form]` to a page to allow visitors to submit reviews.
 6. For one-time links: use `[elsre_form require_token="yes"]`, then generate links
    via **Reviews  Review Links**.

## FAQ

### Where do submitted reviews go?

All submissions are saved with “Pending” status. Go to **Reviews** in the admin 
to approve them.

### Can I display specific reviews only?

Yes, use the `ids` attribute: `[elsre_reviews ids="12,45,78"]`

### How do I translate the plugin?

Copy `languages/elsre.pot` to `languages/elsre-{locale}.po` (e.g. `elsre-fr_FR.po`),
translate, then compile to `.mo`.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“EffortLess Simple Reviews Editor” is open source software. The following people
have contributed to this plugin.

Contributors

 *   [ domclic ](https://profiles.wordpress.org/domclic/)

[Translate “EffortLess Simple Reviews Editor” into your language.](https://translate.wordpress.org/projects/wp-plugins/effortless-simple-reviews-editor)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/effortless-simple-reviews-editor/),
check out the [SVN repository](https://plugins.svn.wordpress.org/effortless-simple-reviews-editor/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/effortless-simple-reviews-editor/)
by [RSS](https://plugins.trac.wordpress.org/log/effortless-simple-reviews-editor/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 2.2.3

 * Security: added the `elsre_require_token` filter so sites can enforce invitation-
   only reviews server-side — when it returns true, tokenless submissions to `admin-
   ajax.php` are rejected (the `require_token="yes"` shortcode attribute only hid
   the form in the browser).
 * Fix: `elsre_create_review_link()` now keeps a reused token’s stored `page_id`
   in sync with the link it builds, matching the admin Generate Link flow.
 * Code: token rollback after a failed insert is now guarded so it only runs for
   token-based submissions; shared review-query and ID-parsing logic extracted to`
   ELSRE_Shortcodes` helpers; flash-notice transients read via a single `consume_transient()`
   helper.

#### 2.2.2

 * Code: removed `plugins_api` filter and associated `plugin_row_meta` “View details”
   link — WordPress.org hosting serves plugin information natively; the local interceptor
   was flagged as an unauthorized update/phone-home mechanism.

#### 2.2.1

 * Security: all table-name SQL references migrated from `esc_sql()` + backtick 
   interpolation to the `%i` identifier placeholder (WordPress 6.2+).
 * Security: `count_tokens()` now wraps `$wpdb->get_var()` in `prepare()` instead
   of passing a raw SQL string.
 * UX: invalid email on the Generate Link form now shows an admin error notice instead
   of silently ignoring the input.
 * Fix: `uninstall.php` now also removes `elsre_error_*` transients created by the
   email validation notice.

#### 2.2.0

 * Fix: token is now restored (un-consumed) when `wp_insert_post()` fails after 
   atomic consume, so the review link remains valid and the client can retry.
 * Fix: `uninstall.php` now also removes `_transient_timeout_` records for `elsre_generated_`,`
   elsre_deleted_`, and `elsre_form_pages` transients, preventing orphan rows in`
   wp_options`.
 * Performance: `get_form_pages()` result is now cached for one hour via transient(
   invalidated on `save_post` / `delete_post`).
 * Performance: Review Links admin page now paginates token rows (50 per page) instead
   of loading all rows at once.
 * Code: `render_admin_columns()` switch now has an explicit `default` branch.
 * Code: `render_form()` passes the template variable via `extract()` to match the`
   load_card_template()` pattern.
 * Security: removed the descriptive `<!-- Honeypot field -->` HTML comment from
   the front-end form.

#### 2.1.9

 * Fix: `post_title` auto-generation now only runs for new posts or posts with an
   empty/Auto Draft title — existing reviews with a manually set title are never
   overwritten.

#### 2.1.8

 * UX: removed the native “Add title” input from the review edit screen — `post_title`
   is now auto-generated from “Reviewer Name – Review Title” and remains visible
   in the admin list table.

#### 2.1.7

 * UX: admin “Review Details” meta box fields reordered to match the front-end form:
   Rating  Reviewer Name  Review Title  Review Text  Review Date.
 * Fix: `maxlength="100"` added to Reviewer Name input in admin meta box.
 * Fix: `maxlength="1000"` added to Review Text textarea in admin meta box.
 * Security: server-side `mb_strlen` / `mb_substr` guards added for reviewer name(
   100 chars) and review text (1000 chars) in `save_meta()`.

#### 2.1.6

 * Code: removed `load_plugin_textdomain()` call — WordPress 4.6+ loads translations
   automatically; the explicit call triggered a PluginCheck warning.
 * Code: `$token` variable in `review-form.php` template renamed to `$elsre_token`
   to satisfy WordPress global variable prefix requirement.

#### 2.1.5

 * Security: token now consumed **before** the review post is inserted — eliminates
   race window that allowed token reuse on server crash.
 * Security: REST API read access restricted to users with `edit_posts` capability
   via `ELSRE_REST_Controller` — review content (including pending) is no longer
   publicly readable via the REST API.
 * Security: token delete action changed from a GET link to a POST form, preventing
   accidental deletion by browser prefetch or link scanners.
 * Security: `handle_admin_actions()` now checks `current_user_can()` before reading
   any request parameters.
 * Fix: admin meta box now reads `post_content` first (authoritative) and falls 
   back to `_elsre_review_text` meta, matching the documented architecture and preventing
   translated content from being overwritten on save.
 * Fix: `load_plugin_textdomain()` added to `elsre_init()` so translations load 
   correctly on self-hosted installs.
 * Fix: `response.data` null guard added on JS success path to prevent TypeError
   when server returns `{success:true, data:null}`.
 * Fix: success message receives focus after form submission so keyboard and screen-
   reader users are not left on the hidden form.
 * Fix: `submit_button()` no longer receives a pre-escaped label — prevented double-
   escaping of special characters.
 * Code: `ms_gpt_translatable_post_types` filter converted to a named function so
   third parties can call `remove_filter()`.
 * Code: `uninstall.php` `DROP TABLE` uses `%i` identifier placeholder (WordPress
   6.2+) instead of `esc_sql()` workaround.
 * CSS: `prefers-reduced-motion` media query added — disables spinner animation 
   and CSS transitions for users who prefer reduced motion.

#### 2.1.4

 * Feature: live character counter on Name, Title, and Review fields — green while
   typing, orange within 5% of the limit, red at the limit. Counter is hidden until
   the user starts typing. Accessible via `aria-live` and `aria-describedby`.

#### 2.1.3

 * Fix: `uninstall.php` — `DROP TABLE` query now uses `esc_sql()` inline instead
   of a `$table` variable, resolving PluginCheck `DirectDB.UnescapedDBParameter`
   warning.

#### 2.1.2

 * Fix: `uninstall.php` — tokens table `DROP` query now guarded by a `preg_match()`
   pattern check on the table name, resolving PluginCheck `DirectDB.UnescapedDBParameter`
   warning.

#### 2.1.1

 * Fix: assets and script data (`elsreData`) now enqueued during `wp_enqueue_scripts`
   instead of inside the shortcode render — prevents “elsreData is not defined” 
   JS errors caused by caching and script-optimisation plugins (LiteSpeed, WP Rocket,
   Autoptimize, etc.).
 * Fix: form hidden on successful submission instead of calling `form.reset()` —
   resolves permanently disabled submit button on Safari/WebKit after token-based
   submissions.
 * Fix: XHR handlers now cover all failure paths (onerror, ontimeout, onabort) with
   a 30-second timeout, so the submit button is always re-enabled even if the server
   does not respond.

#### 2.1.0

 * Feature: review title field added to the submission form, review cards, and admin
   meta box.
 * Change: review text maximum length reduced from 2000 to 1000 characters.
 * Change: submission form field order is now Rating  Name  Title  Review.

#### 2.0.1

 * Code: PHPCS/WPCS zero errors, zero warnings. Alignment fixes auto-corrected by
   phpcbf. Rephrased doc comment to satisfy capitalisation rule. Removed unused `
   $blog_id` parameter from `elsre_uninstall_site()`. Added `PreparedSQL` ignore
   annotation for the dynamic-placeholder query in `get_form_pages()`.

#### 2.0.0

 * Security: REST API meta fields now require `edit_posts` capability via `auth_callback`—
   previously any authenticated user could read review meta via the REST API.
 * Security: `get_client_ip()` now defaults to `REMOTE_ADDR` only. Proxy header 
   trust (`X-Forwarded-For` / `X-Real-IP`) requires explicit opt-in via the `elsre_trust_proxy_headers`
   filter to prevent rate-limit bypass on sites not behind a reverse proxy.
 * Security: `inject_post_content_before_save()` now checks `current_user_can()`
   in addition to nonce verification before modifying `post_content`.
 * Fix: double-escaping of translatable submit button label — `esc_attr__()` replaced
   with `__()` to prevent corrupted output for translations containing apostrophes(
   e.g. French).
 * Fix: `uninstall.php` now loops over all sites on multisite network installs, 
   cleaning up posts, transients, tokens table, and options for each site.
 * Fix: token reuse now updates the stored `page_id` when the admin selects a different
   form page, keeping the token record consistent with the generated URL.
 * Fix: `wp_create_nonce()` is now called only when a shortcode is actually rendered
   on a page, not on every front-end page load.
 * Fix: copy-to-clipboard button now only shows “Copied!” when the clipboard write
   actually succeeded.
 * Code: `load_card_template()` uses `extract()` with an explicit named array instead
   of relying on PHP variable scope inheritance across `include`.
 * Code: `render_admin_columns()` now applies `esc_attr()` to inline star color 
   values (WPCS compliance).
 * New: `elsre_form_page_post_types` filter — allows custom post types to appear
   in the form page dropdown (useful for page-builder custom post types).
 * New: `elsre_trust_proxy_headers` filter — opt-in to reading `X-Forwarded-For`/`
   X-Real-IP` on sites behind a trusted reverse proxy.

#### 1.9.5

 * Fix: esc_sql() applied to table variable before interpolation in consume_token()
   query.

#### 1.9.4

 * Fix: JS — response.data null-guard added before accessing response.data.html 
   in infinite scroll callback.
 * Fix: JS — IntersectionObserver callback now checks entries.length before accessing
   entries[0].
 * Fix: JS — hardcoded ‘Submit Review’ fallback replaced with translatable elsreData.
   i18n.submit (added to wp_localize_script).
 * Fix: Accessibility — individual star spans in review-card.php now have aria-hidden
   =”true”; the parent div already carries the full aria-label.
 * Fix: readme.txt — stale version number 1.4.4 updated in plugin ASCII art example.

#### 1.9.3

 * Code: PHPCS/WPCS — zero errors, zero warnings. Fixed short ternary operator (
   replaced ?: with explicit if/else), added missing docblock short description,
   fixed indentation in review-card.php template. Added extensions and exclude-pattern
   to phpcs.xml to scope checks to PHP only.

#### 1.9.2

 * Fix: SQL table names now consistently wrapped in backticks across all queries
   in class-elsre-tokens.php and uninstall.php.
 * Fix: strtotime() return value now validated before passing to wp_date() — prevents
   current date/time showing for reviews with missing or malformed date meta.
 * Fix: missing esc_attr() on CSS class output in review-card.php (WPCS compliance).
 * Fix: replaced printf(esc_html__(…), ‘`') pattern with echo wp_kses_post(sprintf(
   __(...))) — correct approach for substituting HTML into translatable strings.`
 * Fix: added PHP 8.0 union type hint false|object on the $api parameter of elsre_plugins_api_info().

#### 1.9.1

 * Fix: blank “Add New Review” screen in WordPress 6.9+ — `replace_editor` filter
   returning `true` caused WP 6.9 to skip the entire edit form, showing only the
   admin footer. Replaced with CSS-based editor suppression (`.post-type-elsre_review#
   postdivrich` etc.).
 * Fix: added `use_block_editor_for_post` filter alongside `use_block_editor_for_post_type`
   for belt-and-suspenders block editor disabling.
 * New: plugin details modal — “View details” link on the Plugins page showing description,
   shortcode docs, installation guide, and changelog.

#### 1.9.0

 * Fix: editor suppression switched from `user_can_richedit` filter to `replace_editor`
   filter for WordPress 6.x compatibility.

#### 1.8.3

 * Fix: removed `postcustom` meta box (Custom Fields) from review edit screen to
   keep the admin UI clean.

#### 1.8.2

 * Fix: translation reverting to source — meta fallback in inject_post_content_before_save
   now only fires when post_content is genuinely empty, never when translated content
   is already present.
 * Fix: TinyMCE no longer appears on review edit screen (user_can_richedit filter).

#### 1.8.1

 * Fix: restored plain-textarea UI for review text (no TinyMCE, no image uploads).
   Native content editor hidden via remove_meta_box() while editor stays in CPT 
   supports.
 * Fix: removed sync_content_from_meta — its wp_update_post() fired a second save_post
   which triggered the translator twice, causing random translation results.
 * inject_post_content_before_save is the single reliable sync point.

#### 1.8.0

 * Fix: `editor` added to CPT supports — translation plugins check post_type_supports
   before including post_content in jobs. Without it, post_content was silently 
   skipped. Review text now translates correctly.
 * Block editor disabled for review posts; classic editor used. The content area
   holds the review text directly, like a standard post.
 * Removed “Review Text” textarea from the structured meta box — it is now the native
   content field. Reviewer name, rating, and date remain in the meta box.
 * Removed inject_post_content_before_save and sync_content_from_meta hooks — no
   longer needed with native editor support.
 * Backward compat: card template still falls back to _elsre_review_text meta for
   reviews created before 1.8.0.

#### 1.7.1

 * Security: token consumption is now atomic (UPDATE WHERE is_used = 0) — prevents
   race condition where two simultaneous requests with the same token could both
   succeed.
 * Security: REST API requests excluded from post_content restore hooks — translation
   plugins updating via REST no longer risk source-language overwrite.
 * Security: server-side max-length validation added for reviewer name (100 chars)
   and review text (2000 chars).
 * Security: REMOTE_ADDR validated as IP before use in rate limiting.
 * Fix: uninstall.php now cleans up admin-notice transients.

#### 1.7.0

 * Requires PHP 8.0+ and WordPress 6.9+.
 * PHP 8.0 type hints added to all methods and global functions.
 * `match` expressions replace if/else chains in token validation, AJAX order parsing,
   and error messages.
 * `wp_date()` replaces `date_i18n()` throughout.
 * Removed all `phpcs:ignore NonceVerification` suppressions: nonce verified directly
   in `inject_post_content_before_save()`; programmatic saves detected via `$_SERVER['
   REQUEST_METHOD']`; admin notices use per-user transients instead of unverified`
   $_GET` params.
 * Template variables renamed with `elsre_` prefix — removes all `phpcs:ignore NonPrefixedVariableFound`
   suppressions.

#### 1.6.3

 * Fix: Plugin URI updated from example.com to domclic.com.
 * Fix: removed deprecated load_plugin_textdomain() call.
 * Fix: esc_sql() applied to table name in get_all_tokens().
 * Fix: phpcs ignore on loop variable $i and $submit_label in templates.

#### 1.6.2

 * i18n: text domain changed from `elsre` to `effortless-simple-reviews-editor` 
   across all PHP files to match WordPress.org convention.

#### 1.6.1

 * Fix: infinite re-translation loop with multisite translation plugins — `inject_post_content_before_save`
   and `sync_content_from_meta` now skip programmatic saves (no `$_POST`) so translated`
   post_content` on destination sites is never overwritten with source-language 
   meta.

#### 1.6.0

 * Code: full PHPCS/WPCS compliance — zero errors, zero warnings.
 * Fix: Yoda conditions in `validate_token()` and token list rendering.
 * Fix: renamed `$posts`/`$post_id` in `uninstall.php` to avoid overriding WordPress
   globals.
 * Fix: suppressed false-positive nonce warnings on read-only redirect params.
 * Fix: alignment and whitespace issues auto-corrected by phpcbf.

#### 1.5.9

 * Fix: `$id_array` undefined variable notice when `[elsre_reviews]` is used without
   the `ids` attribute.
 * Fix: replaced `gmdate()`+`strtotime()` with `date_i18n()` — dates now respect
   WordPress timezone and locale.
 * Fix: rate limiting skips gracefully when client IP cannot be determined instead
   of hashing an empty string.
 * Fix: AJAX `per_page` capped at 100; `page` capped at 1000 to prevent DB abuse.
 * Fix: deprecated `bigint(20)` syntax replaced with `BIGINT UNSIGNED` in token 
   table (DB version 1.2).
 * Fix: front-end form now has `method="post"` for valid HTML.

#### 1.5.8

 * Compatibility: hooks `ms_gpt_translatable_post_types` filter so EffortLess Multisite
   Auto Translate picks up the non-public `elsre_review` CPT and syncs reviews across
   sites.

#### 1.5.7

 * Fix: PHP Notice “post type elsre_review is not registered” on REST API capability
   checks — `register_meta_fields()` now hooks to `init` at priority 11, after `
   register_post_type()` at priority 10.

#### 1.5.6

 * REST API support enabled on the `elsre_review` post type.
 * All custom meta fields registered with `show_in_rest: true` for REST-based translation
   plugins.
 * Added `custom-fields` to CPT supports.

#### 1.5.5

 * Fix: multisite translation plugins were receiving empty `post_content` because
   our sync hook ran after the translation plugin’s `save_post` hook.
 * New `wp_insert_post_data` filter injects review text into `post_content` before
   the database write, so translation plugins always sync the correct content.

#### 1.5.4

 * Fix: `$tokens_handler` variable scope bug in `submit_review()` — was potentially
   undefined at token consumption.
 * Fix: `wp_insert_post()` zero-return now treated as failure (not just `WP_Error`).
 * Fix: removed `$wpdb->prepare()` with no placeholders in `get_all_tokens()`.
 * Security: CSS size attributes on shortcodes now validated against a unit whitelist.

#### 1.5.3

 * Fix: infinite recursion — removed `wp_update_post()` from `save_meta()`.
 * Fix: WordPress was clearing `post_content` on every admin save (CPT without editor).`
   sync_content_from_meta()` now correctly restores it.
 * Replaced remove/re-add hook pattern with a static `$syncing` flag.

#### 1.5.2

 * Fix: quick edit and bulk edit now correctly sync `post_content` from `_elsre_review_text`
   meta.
 * Infinite-loop guard on the sync hook.

#### 1.5.1

 * Translation compatibility: review text now stored in `post_content` so multisite
   translators and translation plugins handle it natively.
 * Card display reads from `post_content` first, falls back to meta for reviews 
   created before this version.
 * Admin meta box keeps `post_content` in sync when review text is edited.

#### 1.5.0

 * New `order` attribute on `[elsre_reviews]`: `order="desc"` (newest first, default)
   or `order="asc"` (oldest first).
 * Sort order preserved across infinite scroll loads.

#### 1.4.4

 * Security: replaced MD5 with SHA-256 for rate-limit IP hashing.
 * Security: proxy-aware IP detection — reads `X-Forwarded-For` / `X-Real-IP` headers
   with validation before falling back to `REMOTE_ADDR`.
 * Security: moved inline `onclick` confirm on delete links to `addEventListener`
   in JS.
 * Security: nonce verified before processing delete action; added `token_id` guard.
 * Security: validate generated page ID exists before issuing a token.
 * Code: `get_all_tokens()` SQL query now uses `$wpdb->prepare()`.
 * Code: date validation uses `DateTime::createFromFormat()` for strict round-trip
   check.
 * Code: `ELSRE_Shortcodes::load_card_template()` is now static — no extra class
   instantiation in AJAX handler.

#### 1.4.3

 * Plugin renamed to EffortLess Simple Reviews Editor to match the `ELSRE_` prefix
   convention.

#### 1.4.2

 * i18n ready: `load_plugin_textdomain()` and `.pot` template file for translations.

#### 1.4.1

 * Review title now displayed in the card (between stars and review text).

#### 1.4.0

 * Customizable sizes: `star_size`, `text_size`, `name_size` attributes on `[elsre_reviews]`.
 * Customizable star size on `[elsre_form]` via `star_size` attribute.
 * Sizes powered by CSS custom properties for easy theming.

#### 1.3.0

 * Client email is now the unique identifier for review links.
 * If an unused link exists for the same email, it is reused (no duplicates).
 * Email column added to the tokens table and admin Review Links page.
 * `elsre_create_review_link()` first parameter is now `$email`.

#### 1.2.0

 * New `elsre_create_review_link()` PHP function for programmatic link generation.
 * Use it from your own plugin to automatically include a review link in emails.

#### 1.1.0

 * One-time-use review links: generate unique links for clients via Reviews  Review
   Links.
 * New `require_token` attribute on `[elsre_form]` shortcode.
 * Admin page to generate, copy, and manage review links.
 * Token consumed after submission — link can only be used once.

#### 1.0.0

 * Initial release.
 * Custom post type for reviews with admin meta boxes.
 * `[elsre_reviews]` shortcode with infinite scroll and responsive grid.
 * `[elsre_form]` shortcode with AJAX submission, honeypot, and rate limiting.

## Meta

 *  Version **2.2.3**
 *  Last updated **6 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.2 or higher **
 *  Tested up to **7.0**
 *  PHP version ** 8.0 or higher **
 * Tags
 * [infinite scroll](https://wordpress.org/plugins/tags/infinite-scroll/)[ratings](https://wordpress.org/plugins/tags/ratings/)
   [reviews](https://wordpress.org/plugins/tags/reviews/)[star rating](https://wordpress.org/plugins/tags/star-rating/)
   [testimonials](https://wordpress.org/plugins/tags/testimonials/)
 *  [Advanced View](https://wordpress.org/plugins/effortless-simple-reviews-editor/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/effortless-simple-reviews-editor/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/effortless-simple-reviews-editor/reviews/)

## Contributors

 *   [ domclic ](https://profiles.wordpress.org/domclic/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/effortless-simple-reviews-editor/)