{"id":243466,"date":"2025-07-27T16:43:35","date_gmt":"2025-07-27T16:43:35","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/init-review-system\/"},"modified":"2026-03-25T05:04:50","modified_gmt":"2026-03-25T05:04:50","slug":"init-review-system","status":"publish","type":"plugin","link":"https:\/\/pcd.wordpress.org\/plugins\/init-review-system\/","author":14479633,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"1.17","stable_tag":"1.17","tested":"6.9.4","requires":"5.5","requires_php":"7.4","requires_plugins":null,"header_name":"Init Review System","header_author":"Init HTML","header_description":"Add a simple and flexible star rating system with schema support, REST API, shortcode display, and localStorage tracking.","assets_banners_color":"fffe99","last_updated":"2026-03-25 05:04:50","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/inithtml.com\/plugin\/init-review-system\/","header_author_uri":"https:\/\/inithtml.com\/","rating":0,"author_block_rating":0,"active_installs":30,"downloads":1715,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.10":{"tag":"1.10","author":"brokensmile.2103","date":"2025-11-03 08:22:50"},"1.11":{"tag":"1.11","author":"brokensmile.2103","date":"2025-11-05 11:23:40"},"1.12":{"tag":"1.12","author":"brokensmile.2103","date":"2025-11-13 17:22:03"},"1.13":{"tag":"1.13","author":"brokensmile.2103","date":"2026-01-19 09:16:51"},"1.14":{"tag":"1.14","author":"brokensmile.2103","date":"2026-01-29 04:36:45"},"1.14.1":{"tag":"1.14.1","author":"brokensmile.2103","date":"2026-01-29 05:51:04"},"1.15":{"tag":"1.15","author":"brokensmile.2103","date":"2026-02-25 07:11:05"},"1.16":{"tag":"1.16","author":"brokensmile.2103","date":"2026-03-01 13:04:07"},"1.17":{"tag":"1.17","author":"brokensmile.2103","date":"2026-03-25 05:04:50"},"1.2":{"tag":"1.2","author":"brokensmile.2103","date":"2025-07-27 16:43:25"},"1.2.1":{"tag":"1.2.1","author":"brokensmile.2103","date":"2025-08-19 14:38:16"},"1.3":{"tag":"1.3","author":"brokensmile.2103","date":"2025-08-24 18:42:05"},"1.4":{"tag":"1.4","author":"brokensmile.2103","date":"2025-09-01 13:05:24"},"1.5":{"tag":"1.5","author":"brokensmile.2103","date":"2025-09-01 15:58:25"},"1.6":{"tag":"1.6","author":"brokensmile.2103","date":"2025-09-04 11:23:30"},"1.7":{"tag":"1.7","author":"brokensmile.2103","date":"2025-09-13 13:38:12"},"1.7.1":{"tag":"1.7.1","author":"brokensmile.2103","date":"2025-09-24 03:13:23"},"1.7.2":{"tag":"1.7.2","author":"brokensmile.2103","date":"2025-09-27 04:49:52"},"1.8":{"tag":"1.8","author":"brokensmile.2103","date":"2025-10-06 14:42:02"},"1.8.1":{"tag":"1.8.1","author":"brokensmile.2103","date":"2025-10-22 12:44:27"},"1.9":{"tag":"1.9","author":"brokensmile.2103","date":"2025-10-31 07:03:53"}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3334954,"resolution":"128x128","location":"assets","locale":""},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3334954,"resolution":"256x256","location":"assets","locale":""}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3334954,"resolution":"1544x500","location":"assets","locale":""},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3334954,"resolution":"772x250","location":"assets","locale":""}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.10","1.11","1.12","1.13","1.14","1.14.1","1.15","1.16","1.17","1.2","1.2.1","1.3","1.4","1.5","1.6","1.7","1.7.1","1.7.2","1.8","1.8.1","1.9"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3334954,"resolution":"1","location":"assets","locale":""},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3334954,"resolution":"2","location":"assets","locale":""},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3334954,"resolution":"3","location":"assets","locale":""},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3355999,"resolution":"4","location":"assets","locale":""}},"screenshots":{"1":"<strong>Plugin Settings Page<\/strong> \u2013 Configure general options like login requirement, IP restriction, auto-display position, and up to 5 custom criteria fields.","2":"<strong>Single-Star Rating Display<\/strong> \u2013 Star-based rating shown on a post with average score and vote count.","3":"<strong>Multi-Criteria Review Display<\/strong> \u2013 Frontend layout showing score breakdown per criteria and full user review content.","4":"<strong>Reactions Bar<\/strong> \u2013 Emoji-based reactions under the post, showing total counts, current user reaction highlight, and requiring login to interact."},"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[2295,25046,110,1117,9827],"plugin_category":[53,55],"plugin_contributors":[242666],"plugin_business_model":[],"class_list":["post-243466","plugin","type-plugin","status-publish","hentry","plugin_tags-rating","plugin_tags-reaction","plugin_tags-review","plugin_tags-schema","plugin_tags-vote","plugin_category-ratings-and-reviews","plugin_category-seo-and-marketing","plugin_contributors-brokensmile2103-1","plugin_committers-brokensmile2103-1"],"banners":{"banner":"https:\/\/ps.w.org\/init-review-system\/assets\/banner-772x250.png?rev=3334954","banner_2x":"https:\/\/ps.w.org\/init-review-system\/assets\/banner-1544x500.png?rev=3334954","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/init-review-system\/assets\/icon-128x128.png?rev=3334954","icon_2x":"https:\/\/ps.w.org\/init-review-system\/assets\/icon-256x256.png?rev=3334954","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/init-review-system\/assets\/screenshot-1.png?rev=3334954","caption":"<strong>Plugin Settings Page<\/strong> \u2013 Configure general options like login requirement, IP restriction, auto-display position, and up to 5 custom criteria fields."},{"src":"https:\/\/ps.w.org\/init-review-system\/assets\/screenshot-2.png?rev=3334954","caption":"<strong>Single-Star Rating Display<\/strong> \u2013 Star-based rating shown on a post with average score and vote count."},{"src":"https:\/\/ps.w.org\/init-review-system\/assets\/screenshot-3.png?rev=3334954","caption":"<strong>Multi-Criteria Review Display<\/strong> \u2013 Frontend layout showing score breakdown per criteria and full user review content."},{"src":"https:\/\/ps.w.org\/init-review-system\/assets\/screenshot-4.png?rev=3355999","caption":"<strong>Reactions Bar<\/strong> \u2013 Emoji-based reactions under the post, showing total counts, current user reaction highlight, and requiring login to interact."}],"raw_content":"<!--section=description-->\n<p><strong>Init Review System<\/strong> adds a clean and customizable 5-star rating system to your WordPress site. Votes are stored via REST API, tracked with <code>localStorage<\/code>, and the average score is auto-calculated and optionally displayed with schema markup.<\/p>\n\n<p>Built to be lightweight, developer-friendly, and easy to integrate into any theme or custom UI. Now with <strong>multi-criteria reviews<\/strong> and an <strong>emoji reactions system<\/strong> for richer user interaction.<\/p>\n\n<p>This plugin is part of the <a href=\"https:\/\/en.inithtml.com\/init-plugin-suite-minimalist-powerful-and-free-wordpress-plugins\/\">Init Plugin Suite<\/a> \u2014 a collection of minimalist, fast, and developer-focused tools for WordPress.<\/p>\n\n<p>GitHub repository: <a href=\"https:\/\/github.com\/brokensmile2103\/init-review-system\">https:\/\/github.com\/brokensmile2103\/init-review-system<\/a><\/p>\n\n<p><strong>Highlights:<\/strong><\/p>\n\n<ul>\n<li>5-star voting via frontend<\/li>\n<li><strong>NEW: Multi-criteria review support<\/strong><\/li>\n<li><strong>NEW: Emoji Reactions with Login Enforcement<\/strong><\/li>\n<li>Average score display<\/li>\n<li>Optional login requirement<\/li>\n<li>Optional strict IP checking<\/li>\n<li>REST API for vote submission<\/li>\n<li>JSON-LD schema for SEO<\/li>\n<li>Works with any post type<\/li>\n<li>Minimal, theme-friendly UI<\/li>\n<\/ul>\n\n<h3>Features<\/h3>\n\n<ul>\n<li>5-star rating system<\/li>\n<li>Multi-criteria review scoring (up to 5 custom criteria)<\/li>\n<li>Emoji-based reactions bar with live counts (requires login)<\/li>\n<li>REST API endpoint for reactions: <code>\/wp-json\/initrsys\/v1\/reactions\/toggle<\/code><\/li>\n<li>Reactions stored in both post meta and dedicated user\u2194post mapping table<\/li>\n<li>Accessibility-ready with <code>aria-pressed<\/code> + <code>aria-live<\/code> updates<\/li>\n<li>Shortcode-based integration<\/li>\n<li>Auto-insert blocks before\/after content or comments<\/li>\n<li>Optional login + IP check to prevent abuse<\/li>\n<li>REST API endpoint: <code>\/wp-json\/initrsys\/v1\/vote<\/code><\/li>\n<li>Developer filters and extensible architecture<\/li>\n<li>No jQuery, only minimal assets loaded when needed<\/li>\n<\/ul>\n\n<h3>Usage<\/h3>\n\n<h3>[init_review_system]<\/h3>\n\n<p>Displays interactive 5-star voting block.<\/p>\n\n<p>Attributes:\n- <code>id<\/code>: Post ID (default: current post)\n- <code>class<\/code>: Custom CSS class\n- <code>schema<\/code>: <code>true|false<\/code> \u2013 Output JSON-LD schema markup<\/p>\n\n<h3>[init_review_score]<\/h3>\n\n<p>Displays average score (read-only).<\/p>\n\n<p>Attributes:\n- <code>id<\/code>: Post ID (default: current post)\n- <code>icon<\/code>: <code>true|false<\/code> \u2013 Show star icon (default: false)\n- <code>sub<\/code>: <code>true|false<\/code> \u2013 Show <code>\/5<\/code> subtext (default: true)\n- <code>class<\/code>: Custom CSS class\n- <code>hide_if_empty<\/code>: <code>true|false<\/code> \u2013 Hide if no reviews (default: false)<\/p>\n\n<h3>[init_review_criteria]<\/h3>\n\n<p>Displays multi-criteria review block.<\/p>\n\n<p>Attributes:\n- <code>id<\/code>: Post ID (default: current post)\n- <code>class<\/code>: Custom CSS class\n- <code>schema<\/code>: <code>true|false<\/code> \u2013 Output schema markup (default: false)\n- <code>per_page<\/code>: Number of reviews to show (default: 0 = all)\n- <code>paged<\/code>: Current review page number (default: 1)<\/p>\n\n<h3>[init_reactions]<\/h3>\n\n<p>Displays emoji reactions bar under a post.<\/p>\n\n<p>Attributes:\n- <code>id<\/code>: Post ID (default: current post)\n- <code>class<\/code>: Custom CSS class\n- <code>require_login<\/code>: Always true (login required)<\/p>\n\n<h3>Filters for Developers<\/h3>\n\n<p>This plugin provides filters and actions to let developers customize auto-insert behavior, schema output, review permissions, and REST API logic.<\/p>\n\n<p><strong><code>init_plugin_suite_review_system_auto_insert_enabled_score<\/code><\/strong>\nEnable or disable automatic score output (before\/after content).\n<strong>Applies to:<\/strong> Frontend filter\n<strong>Params:<\/strong> <code>bool $enabled<\/code>, <code>string $position<\/code>, <code>string $post_type<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_auto_insert_enabled_vote<\/code><\/strong>\nEnable or disable automatic voting block insertion.\n<strong>Applies to:<\/strong> Frontend filter\n<strong>Params:<\/strong> <code>bool $enabled<\/code>, <code>string $position<\/code>, <code>string $post_type<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_default_score_shortcode<\/code><\/strong>\nChange the default shortcode used for score auto-insertion.\n<strong>Applies to:<\/strong> Frontend\n<strong>Params:<\/strong> <code>string $shortcode<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_default_vote_shortcode<\/code><\/strong>\nChange the default shortcode used for voting block auto-insertion.\n<strong>Applies to:<\/strong> Frontend\n<strong>Params:<\/strong> <code>string $shortcode<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_require_login<\/code><\/strong>\nForce login for submitting reviews, even if disabled in settings.\n<strong>Applies to:<\/strong> REST <code>\/submit-criteria-review<\/code>\n<strong>Params:<\/strong> <code>bool $require_login<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_min_len_for_ws_check<\/code><\/strong>\nAdjust minimum length threshold for triggering no-whitespace check.\n<strong>Applies to:<\/strong> Backend + JS precheck\n<strong>Params:<\/strong> <code>int $threshold<\/code> (default <code>20<\/code>)<\/p>\n\n<p><strong><code>init_plugin_suite_review_system_repetition_threshold<\/code><\/strong>\nAdjust repetition threshold for detecting excessive word repetition.\n<strong>Applies to:<\/strong> Backend + JS precheck\n<strong>Params:<\/strong> <code>int $threshold<\/code> (default <code>8<\/code>)<\/p>\n\n<p><strong><code>init_plugin_suite_review_system_schema_type<\/code><\/strong>\nCustomize schema.org type (e.g., <code>Book<\/code>, <code>Product<\/code>, <code>Course<\/code>).\n<strong>Applies to:<\/strong> Shortcode output\n<strong>Params:<\/strong> <code>string $type<\/code>, <code>string $post_type<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_schema_data<\/code><\/strong>\nModify JSON-LD schema output array.\n<strong>Applies to:<\/strong> Shortcode output\n<strong>Params:<\/strong> <code>array $data<\/code>, <code>int $post_id<\/code>, <code>string $schema_type<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_after_vote<\/code><\/strong>\nRun custom logic after a single-star vote is submitted.\n<strong>Applies to:<\/strong> REST <code>\/vote<\/code>\n<strong>Params:<\/strong> <code>int $post_id<\/code>, <code>float $score<\/code>, <code>float $avg_score<\/code>, <code>int $total_votes<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_after_criteria_review<\/code><\/strong>\nTrigger custom logic after a multi-criteria review is submitted.\n<strong>Applies to:<\/strong> REST <code>\/submit-criteria-review<\/code>\n<strong>Params:<\/strong> <code>int $post_id<\/code>, <code>int $user_id<\/code>, <code>float $avg_score<\/code>, <code>string $review_content<\/code>, <code>array $scores<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_get_reaction_types<\/code><\/strong>\nCustomize available reaction types (labels + emojis).\n<strong>Applies to:<\/strong> Reactions system\n<strong>Params:<\/strong> <code>array $types<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_reaction_meta_key<\/code><\/strong>\nCustomize the meta key used for storing reaction counts.\n<strong>Applies to:<\/strong> Reaction counts storage\n<strong>Params:<\/strong> <code>string $meta_key<\/code>, <code>string $rx_key<\/code><\/p>\n\n<p><strong><code>init_plugin_suite_review_system_ttl<\/code><\/strong>\nSet TTL (in seconds) for object cache on review queries. Defaults to <code>0<\/code> (cache disabled). Set a value greater than <code>0<\/code> to enable caching via <code>wp_cache_set<\/code> with group <code>init_review_system<\/code>.\n<strong>Applies to:<\/strong> REST get reviews, get total reviews\n<strong>Params:<\/strong> <code>int $ttl<\/code> (default <code>0<\/code>)<\/p>\n\n<h3>License<\/h3>\n\n<p>This plugin is licensed under the GPLv2 or later.\nYou are free to use, modify, and distribute it under the same license.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload plugin to <code>\/wp-content\/plugins\/<\/code><\/li>\n<li>Activate via Plugins menu<\/li>\n<li>Go to <strong>Settings &gt; Init Review System<\/strong> to configure options<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"is%20login%20required%20to%20vote%3F\"><h3>Is login required to vote?<\/h3><\/dt>\n<dd><p>Not by default. You can enable it in plugin settings.<\/p><\/dd>\n<dt id=\"does%20it%20support%20ip%20protection%3F\"><h3>Does it support IP protection?<\/h3><\/dt>\n<dd><p>Yes. You can enable strict IP check to prevent duplicate votes.<\/p><\/dd>\n<dt id=\"can%20i%20use%20this%20with%20custom%20post%20types%3F\"><h3>Can I use this with custom post types?<\/h3><\/dt>\n<dd><p>Yes, it works with any post type that uses <code>the_content()<\/code> or <code>comment_form()<\/code>.<\/p><\/dd>\n<dt id=\"does%20it%20support%20multi-criteria%20reviews%3F\"><h3>Does it support multi-criteria reviews?<\/h3><\/dt>\n<dd><p>Yes. You can define up to 5 custom criteria and show them using the provided shortcode.<\/p><\/dd>\n<dt id=\"does%20it%20support%2010-star%20ratings%3F\"><h3>Does it support 10-star ratings?<\/h3><\/dt>\n<dd><p>No. The plugin currently supports only a 5-star scale.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.17 \u2013 March 25, 2026<\/h4>\n\n<ul>\n<li>Added object cache (1 hour TTL) to <code>init_plugin_suite_review_system_get_score_summary_by_post_id()<\/code><\/li>\n<li>Added object cache (1 hour TTL) to <code>init_plugin_suite_review_system_has_user_reviewed()<\/code><\/li>\n<li>Added object cache (1 hour TTL) to <code>init_plugin_suite_review_system_get_user_reaction()<\/code><\/li>\n<li>Cache for <code>has_user_reviewed<\/code> and <code>get_user_reaction<\/code> stores sentinel values to distinguish cache miss from negative results<\/li>\n<li>Cache invalidation for score summary and has-reviewed fires on <code>init_plugin_suite_review_system_after_insert<\/code> action hook<\/li>\n<li>Cache invalidation for user reaction fires inside <code>init_plugin_suite_review_system_apply_user_reaction()<\/code> after each write<\/li>\n<\/ul>\n\n<h4>1.16 \u2013 March 1, 2026<\/h4>\n\n<ul>\n<li>Fixed Load More showing wrong user avatar and display name<\/li>\n<li>Fixed post-submit review rendering hardcoded HTML incompatible with custom templates<\/li>\n<li>Added <code>review-item.php<\/code> as standalone overridable template<\/li>\n<li>Added <code>init_plugin_suite_review_system_get_criteria_by_post_id()<\/code> helper<\/li>\n<li>Added <code>init_plugin_suite_review_system_get_review_by_id()<\/code> helper<\/li>\n<li>REST endpoints now server-render review HTML; JS only injects, no longer builds DOM<\/li>\n<li>Removed unused <code>insertNewReview()<\/code> JS function<\/li>\n<\/ul>\n\n<h4>1.15 \u2013 February 25, 2026<\/h4>\n\n<ul>\n<li>Added <code>$per_page<\/code> cap (max 100) in REST endpoint to prevent excessive data queries<\/li>\n<li>Added <code>init_plugin_suite_review_system_ttl<\/code> filter (default <code>0<\/code>) to opt-in object cache for review queries<\/li>\n<li>When TTL &gt; 0, query results are cached via <code>wp_cache_set<\/code> with group <code>init_review_system<\/code><\/li>\n<li>Cache invalidation can be handled via <code>init_plugin_suite_review_system_after_insert<\/code> action hook<\/li>\n<\/ul>\n\n<h4>1.14 \u2013 January 29, 2026<\/h4>\n\n<ul>\n<li>Introduced <strong>Bayesian Weighted Rating<\/strong> for reliable ranking calculations\n\n<ul>\n<li>New derived meta key <code>_init_review_weighted<\/code> generated <strong>on vote submission<\/strong><\/li>\n<li>Prevents low-sample bias (e.g. 1\u00d75\u2605 no longer outranks 1000\u00d74.9\u2605)<\/li>\n<li>Uses configurable minimum vote threshold via filter<br \/>\ninit_plugin_suite_review_system_min_votes_threshold<\/li>\n<\/ul><\/li>\n<li>Rating architecture improvements:\n\n<ul>\n<li>Weighted score is calculated <strong>on-write<\/strong> (at REST endpoint), not at query time<\/li>\n<li>Establishes clear separation between <strong>raw data<\/strong> and <strong>ranking data<\/strong><\/li>\n<li>Plugin now acts as the single source of truth for rating-based sorting<\/li>\n<\/ul><\/li>\n<li>Performance &amp; stability:\n\n<ul>\n<li>Global average rating is cached using <strong>transients<\/strong> for cross-environment reliability<\/li>\n<li>Automatic transient invalidation on new vote to prevent stale calculations<\/li>\n<\/ul><\/li>\n<li>Developer experience:\n\n<ul>\n<li>Enhanced <code>init_plugin_suite_review_system_after_vote<\/code> hook now passes:<\/li>\n<li>New average score<\/li>\n<li>Total vote count<\/li>\n<li>Weighted ranking score<\/li>\n<li>Fully backward compatible \u2014 no changes required for existing consumers<\/li>\n<\/ul><\/li>\n<li>No UI or frontend behavior changes<\/li>\n<li>No breaking changes to REST API responses<\/li>\n<\/ul>\n\n<h4>1.13 \u2013 January 19, 2026<\/h4>\n\n<ul>\n<li>Added <code>.dark<\/code> modifier for <code>.init-reaction-bar<\/code> to support Dark Mode<\/li>\n<li>Improved visual contrast for reactions in dark environments<\/li>\n<li>Polished hover, active and disabled states in Dark Mode<\/li>\n<li>Pure CSS enhancement, no JS or logic changes<\/li>\n<\/ul>\n\n<h4>1.12 \u2013 November 14, 2025<\/h4>\n\n<ul>\n<li>Added <strong>anti\u2013double-submit protection<\/strong> to the front-end rating widget\n\n<ul>\n<li>New <code>isSubmitting<\/code> state prevents rapid multi-clicks from firing multiple requests<\/li>\n<li>Fully compatible with both <strong>single-click<\/strong> and <strong>double-click confirmation<\/strong> modes<\/li>\n<li>Pending hover logic (<code>.hovering<\/code>) remains intact with zero behavior changes<\/li>\n<\/ul><\/li>\n<li>Improved client-side stability:\n\n<ul>\n<li>Ensures only <strong>one<\/strong> vote request is sent at a time<\/li>\n<li>Allows retrying when the API returns an error (non-blocking UX)<\/li>\n<\/ul><\/li>\n<li>No changes to REST API, server logic, or existing rating flow \u2014 fully backward compatible<\/li>\n<\/ul>\n\n<h4>1.11 \u2013 November 5, 2025<\/h4>\n\n<ul>\n<li>Added <strong>User Review Fetching API<\/strong>\n\n<ul>\n<li>New function <code>init_plugin_suite_review_system_get_reviews_by_user_id()<\/code><\/li>\n<li>Supports pagination (<code>paged<\/code>, <code>per_page<\/code>) just like the post-based fetcher<\/li>\n<li>Automatically joins with <code>wp_posts<\/code> to <strong>exclude orphaned reviews<\/strong><\/li>\n<li>Returns unserialized <code>criteria_scores<\/code> for direct UI rendering<\/li>\n<\/ul><\/li>\n<li>Added <strong>Total Pages Counter for User Reviews<\/strong>\n\n<ul>\n<li>New function <code>init_plugin_suite_review_system_get_total_pages_by_user_id()<\/code><\/li>\n<li>Counts reviews belonging to a specific user (filtered by <code>status<\/code>)<\/li>\n<li>Returns the total number of pages (minimum value: <code>1<\/code> for UX consistency)<\/li>\n<\/ul><\/li>\n<li>Performance and internal improvements:\n\n<ul>\n<li>Consistent sanitization and safety (<code>absint()<\/code>, <code>max()<\/code>, typed values)<\/li>\n<li>All SQL queries use <code>$wpdb-&gt;prepare()<\/code> \u2014 no unbound parameters<\/li>\n<li>PHPCS\/WPCS compliant and follows plugin prefix standard<\/li>\n<\/ul><\/li>\n<\/ul>\n\n<h4>1.10 \u2013 November 3, 2025<\/h4>\n\n<ul>\n<li>Added <strong>Admin Reset &amp; Manual Score Adjustment Metabox<\/strong>\n\n<ul>\n<li>Visible <strong>only when a post already has rating data<\/strong><\/li>\n<li>New UI: compact <strong>stat chips<\/strong> showing Avg \/ Votes \/ Total (premium-style mini cards)<\/li>\n<li>Supports manual override: admin can set <strong>Average (0\u20135)<\/strong> and <strong>Vote Count<\/strong><\/li>\n<li>Internal logic auto-calculates <code>Total = Avg \u00d7 Count<\/code> (rounded to 2 decimals)<\/li>\n<li>All displayed values are fully escaped (<code>esc_html() \/ esc_attr()<\/code>) following PHPCS<\/li>\n<li>Metabox is registered <strong>per-post<\/strong>, not globally \u2014 zero UI clutter<\/li>\n<\/ul><\/li>\n<li>Security and permissions:\n\n<ul>\n<li>Only users with capability <code>edit_others_posts<\/code> (<strong>Editor+<\/strong>) can view or interact with the metabox<\/li>\n<li><code>save_post<\/code> handler validates <strong>nonce + capability<\/strong>, protects against unauthorized POST submissions<\/li>\n<li>Input sanitized: <code>sanitize_text_field( wp_unslash() )<\/code> before casting to float\/int<\/li>\n<\/ul><\/li>\n<li>UX improvements:\n\n<ul>\n<li>No inline <code>&lt;style&gt;<\/code> tags \u2014 every style moved to inline attribute (WordPress admin standard)<\/li>\n<li>Metabox does <strong>not appear at all<\/strong> until the first vote exists (no \"empty\" box)<\/li>\n<\/ul><\/li>\n<\/ul>\n\n<h4>1.9 \u2013 October 31, 2025<\/h4>\n\n<ul>\n<li>Added <strong>Double-Click Confirmation Rating<\/strong> (anti-misclick mechanic)\n\n<ul>\n<li>New setting: <code>Require double-click to rate<\/code><\/li>\n<li>When enabled, users must click the same star <strong>twice<\/strong> to confirm rating<\/li>\n<li>First click enters <strong>pending state<\/strong>, visually marked with <code>.hovering<\/code><\/li>\n<li>Second click submits rating and disables the block as usual<\/li>\n<\/ul><\/li>\n<li>JavaScript improvements:\n\n<ul>\n<li>New pending handler with auto-timeout (2.2s) \u2014 no accidental lock state<\/li>\n<li><code>.hovering<\/code> class persists across mouseleave while pending<\/li>\n<li>Clean async state teardown ensures no ghost states<\/li>\n<\/ul><\/li>\n<li>No UI popups, no alerts \u2014 rating confirmation is <strong>purely action-based<\/strong><\/li>\n<li>Zero breaking changes \u2014 existing rating logic untouched<\/li>\n<\/ul>\n\n<h4>1.8 \u2013 October 6, 2025<\/h4>\n\n<ul>\n<li>Updated function <code>init_plugin_suite_review_system_get_reviews_by_post_id()<\/code>:\n\n<ul>\n<li>When <code>$post_id = 0<\/code>, orphaned reviews are now automatically excluded (posts that no longer exist across all CPTs).<\/li>\n<\/ul><\/li>\n<li>Shortcode <code>[init_review_criteria]<\/code> enhanced:\n\n<ul>\n<li>Added new attribute <code>paged<\/code> to control review pagination.<\/li>\n<li>Internal call now passes <code>$paged<\/code> dynamically to <code>init_plugin_suite_review_system_get_reviews_by_post_id()<\/code>.<\/li>\n<\/ul><\/li>\n<\/ul>\n\n<h4>1.7 \u2013 September 13, 2025<\/h4>\n\n<ul>\n<li>Added content moderation: banned words, banned phrases, no-whitespace, excessive repetition<\/li>\n<li>New settings: enable JS precheck (optional), manage banned words\/phrases in textarea fields<\/li>\n<li>Improved modal UX: must rate all required criteria, inline error\/success messages under submit button<\/li>\n<li>JavaScript updated: i18n error mapping, client-side prechecks, red outline highlight for missing scores<\/li>\n<li>CSS enhancements: <code>.init-review-inline-msg<\/code> for messages, <code>.init-review-criteria-error<\/code> for criteria validation (with dark mode support)<\/li>\n<\/ul>\n\n<h4>1.6 \u2013 September 2, 2025<\/h4>\n\n<ul>\n<li>Reactions endpoint <code>\/reactions\/toggle<\/code> now <strong>requires login<\/strong>: enforced <code>is_user_logged_in()<\/code> and nonce validation<\/li>\n<li>Updated REST API registration: <code>permission_callback<\/code> for <code>\/reactions\/toggle<\/code> now only allows logged-in users<\/li>\n<li>Shortcode <code>[init_reactions]<\/code> updated: <code>require_login<\/code> is always <code>true<\/code>, ensuring consistent frontend behavior<\/li>\n<li>Improved JS logic: \n\n<ul>\n<li>Removed guest\/localStorage fallback (no more anonymous reactions)<\/li>\n<li>Preserved initial <code>disabled<\/code> state for buttons; guest users always see counts but cannot interact<\/li>\n<li>Fixed bug where guest buttons could be re-enabled after API calls<\/li>\n<\/ul><\/li>\n<li>CSS adjustments: new <code>.is-disabled<\/code> style keeps emoji + counts <strong>fully visible<\/strong>, while visually indicating login requirement<\/li>\n<li>Enhanced accessibility: reaction buttons now toggle <code>aria-pressed<\/code> accurately and support <code>is-active<\/code> state for current user reaction<\/li>\n<li>Code cleanup: removed obsolete guest handling code paths and simplified state management<\/li>\n<\/ul>\n\n<h4>1.5 \u2013 September 1, 2025<\/h4>\n\n<ul>\n<li>Enhanced Reactions System with <strong>total reactions counter<\/strong> displayed under \u201cWhat do you think?\u201d<\/li>\n<li>Added unique <code>id<\/code> for total counter span (<code>irs-total-reactions-{post_id}<\/code>) to support JS live updates<\/li>\n<li>Updated JavaScript: total reaction count now updates instantly when users toggle reactions<\/li>\n<li>Synced UIkit theme template with total reactions output for consistent frontend display<\/li>\n<li>Added CSS styles for <code>.init-reaction-total<\/code> (font weight, spacing, responsive display)<\/li>\n<li>Improved accessibility: total reactions wrapped with <code>aria-live=\"polite\"<\/code> for screen reader updates<\/li>\n<li>Minor code cleanups and consistency improvements<\/li>\n<\/ul>\n\n<h4>1.4 \u2013 August 31, 2025<\/h4>\n\n<ul>\n<li>Introduced <strong>Reactions System<\/strong>: emoji-based reactions (\ud83d\udc4d \ud83d\ude04 \ud83d\ude0d \ud83d\ude2f \ud83d\ude20 \ud83d\ude22)<\/li>\n<li>Added shortcode + template for reactions bar<\/li>\n<li>Reactions stored in both post meta (counts) and dedicated <code>init_reactions<\/code> table (user\u2194post map)<\/li>\n<li>Guest-friendly: works without login (tracked via localStorage)<\/li>\n<li>Added developer filters:\n\n<ul>\n<li><code>init_plugin_suite_review_system_get_reaction_types<\/code><\/li>\n<li><code>init_plugin_suite_review_system_reaction_meta_key<\/code><\/li>\n<\/ul><\/li>\n<li>Internal refactor: extracted reaction-core functions, silent table creation with <code>dbDelta()<\/code><\/li>\n<\/ul>\n\n<h4>1.3 \u2013 August 25, 2025<\/h4>\n\n<ul>\n<li>Restructured admin interface: moved from Settings submenu to dedicated main menu with star icon<\/li>\n<li>Added comprehensive review management system with bulk operations and filtering capabilities<\/li>\n<li>Implemented review approval workflow with pending\/approved\/rejected status management<\/li>\n<li>Enhanced admin dashboard with review statistics, search functionality, and pagination<\/li>\n<li>Added individual review actions: approve, reject, delete with proper nonce security<\/li>\n<li>Integrated bulk actions for managing multiple reviews simultaneously<\/li>\n<li>Created dedicated review management page with detailed review display and user information<\/li>\n<li>Improved database queries with proper prepared statements and PHPCS compliance<\/li>\n<li>Added admin-only review management scripts with proper enqueueing standards<\/li>\n<li>Refined plugin architecture for better scalability and maintainability<\/li>\n<\/ul>\n\n<h4>1.2 \u2013 July 27, 2025<\/h4>\n\n<ul>\n<li>Standardized all output with <code>esc_html()<\/code>, <code>esc_attr()<\/code>, and <code>wp_kses()<\/code> for frontend safety<\/li>\n<li>Secured REST API endpoint with enforced login + nonce validation for logged-in users<\/li>\n<li>Added <code>uninstall.php<\/code> to clean up plugin options when uninstalled<\/li>\n<li>Refined UI labels and descriptions on settings page<\/li>\n<li>Improved shortcode documentation and attributes in <code>readme.txt<\/code><\/li>\n<li>Enhanced multi-criteria input layout for better clarity<\/li>\n<\/ul>\n\n<h4>1.1 \u2013 July 11, 2025<\/h4>\n\n<ul>\n<li>Added support for multi-criteria reviews<\/li>\n<li>New shortcode for criteria-based score display<\/li>\n<li>Separate logic and schema handling for criteria reviews<\/li>\n<li>Improved review interface and modal UX<\/li>\n<li>Refactored code to support both single and multi-criteria review paths<\/li>\n<\/ul>\n\n<h4>1.0 \u2013 June 28, 2025<\/h4>\n\n<ul>\n<li>Initial release<\/li>\n<li>Shortcode <code>[init_review_system]<\/code> for 5-star voting block<\/li>\n<li>Shortcode <code>[init_review_score]<\/code> for average score display<\/li>\n<li>REST API endpoint <code>\/wp-json\/initrsys\/v1\/vote<\/code> with conditional login and nonce check<\/li>\n<li>Vote tracking via <code>localStorage<\/code> for guest users<\/li>\n<li>Optional login restriction + strict IP check using hashed IP + transient<\/li>\n<li>JSON-LD schema output using <code>AggregateRating<\/code><\/li>\n<li>Auto-insert system: before\/after post content or comment form<\/li>\n<li>Admin settings page with shortcode builder and control toggles<\/li>\n<li>Minimal, responsive, theme-inheriting design<\/li>\n<li>Developer-friendly: filters, actions, and reusable helpers<\/li>\n<\/ul>","raw_excerpt":"Fast 5-star rating plugin with schema, REST API, shortcode control, localStorage voting. Now with multi-criteria review support.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/243466","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=243466"}],"author":[{"embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/brokensmile2103-1"}],"wp:attachment":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=243466"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=243466"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=243466"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=243466"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=243466"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=243466"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}