{"id":306314,"date":"2026-05-28T23:28:48","date_gmt":"2026-05-28T23:28:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/d11-random-quote-loader\/"},"modified":"2026-05-29T05:47:31","modified_gmt":"2026-05-29T05:47:31","slug":"d11-random-quote-loader","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/d11-random-quote-loader\/","author":2467878,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"2.3","stable_tag":"2.3","tested":"7.0","requires":"6.9","requires_php":"7.4","requires_plugins":null,"header_name":"D11 Random Quote Loader","header_author":"Gregory Wilker","header_description":"A widget that displays a random quote from a database on page load. Manage quotes via the admin panel with full CSV import\/export support. Supports quote categories.","assets_banners_color":"614228","last_updated":"2026-05-29 05:47:31","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/www.paypal.com\/paypalme\/gregorywilker","header_plugin_uri":"https:\/\/gregorywilker.com\/things","header_author_uri":"https:\/\/gregorywilker.com\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":38,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"2.3":{"tag":"2.3","author":"briz_dad","date":"2026-05-29 05:47:31"}},"upgrade_notice":{"2.3":"<p>Security update: database table renamed to {prefix}d11rql_quotes, CSV import transaction fixed, CSV parser hardened. Existing installs migrate automatically on next page load \u2014 no manual steps.<\/p>","2.2":"<p>Internal prefix rename from rqw_ to d11rql_. No database schema changes. Safe drop-in for 2.1.<\/p>","2.1":"<p>Important: shortcode renamed from [random_quote] to [d11rql_random_quote] \u2014 update any posts or pages using the old shortcode.<\/p>","2.0.6":"<p>Compatibility update for WordPress 7.0. No code or database changes.<\/p>","2.0.5":"<p>Adds pagination to the admin Manage Quotes page. No database changes.<\/p>","2.0.4":"<p>Adds a database index on the category column. No data changes.<\/p>","2.0.3":"<p>Important fix for caching plugins \u2014 random quotes now display correctly for logged-out visitors.<\/p>","2.0.2":"<p>Database hardening: transactional CSV import. Safe drop-in for 2.0.1.<\/p>","2.0.1":"<p>Security and reliability hardening. No database changes.<\/p>","2.0":"<p>Adds quote categories with a safe automatic database upgrade.<\/p>","1.9":"<p>Adds the shortcode. No database changes required.<\/p>","1.8":"<p>Coding standards compliance and full i18n. No database changes required.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3552976,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3552976,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3552976,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3552976,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["2.3"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3552988,"resolution":"1","location":"assets","locale":"","width":1837,"height":2300},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3552988,"resolution":"2","location":"assets","locale":"","width":1837,"height":1276},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3552988,"resolution":"3","location":"assets","locale":"","width":967,"height":529}},"screenshots":{"1":"A random quote displayed live on the front end of a WordPress site","2":"The Manage Quotes admin page \u2014 add, edit, delete, export, and import quotes","3":"Configuring the D11 Random Quote Loader widget in the WordPress Widgets screen"}},"plugin_section":[],"plugin_tags":[31308,5055,244,168,162],"plugin_category":[43],"plugin_contributors":[264855],"plugin_business_model":[],"class_list":["post-306314","plugin","type-plugin","status-publish","hentry","plugin_tags-inspirational","plugin_tags-quote","plugin_tags-random","plugin_tags-sidebar","plugin_tags-widget","plugin_category-customization","plugin_contributors-briz_dad","plugin_committers-briz_dad"],"banners":{"banner":"https:\/\/ps.w.org\/d11-random-quote-loader\/assets\/banner-772x250.png?rev=3552976","banner_2x":"https:\/\/ps.w.org\/d11-random-quote-loader\/assets\/banner-1544x500.png?rev=3552976","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/d11-random-quote-loader\/assets\/icon-128x128.png?rev=3552976","icon_2x":"https:\/\/ps.w.org\/d11-random-quote-loader\/assets\/icon-256x256.png?rev=3552976","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/d11-random-quote-loader\/assets\/screenshot-1.png?rev=3552988","caption":"A random quote displayed live on the front end of a WordPress site"},{"src":"https:\/\/ps.w.org\/d11-random-quote-loader\/assets\/screenshot-2.png?rev=3552988","caption":"The Manage Quotes admin page \u2014 add, edit, delete, export, and import quotes"},{"src":"https:\/\/ps.w.org\/d11-random-quote-loader\/assets\/screenshot-3.png?rev=3552988","caption":"Configuring the D11 Random Quote Loader widget in the WordPress Widgets screen"}],"raw_content":"<!--section=description-->\n<p><strong>D11 Random Quote Loader<\/strong> adds a classic WordPress widget that pulls a random quote from a custom database table each time a page loads.<\/p>\n\n<p>Quotes are managed entirely from within your WordPress dashboard, and the plugin ships with three sample quotes so it works immediately after activation.<\/p>\n\n<p><strong>Features:<\/strong><\/p>\n\n<ul>\n<li>Displays a random quote on every page load using an efficient COUNT + OFFSET strategy (not ORDER BY RAND())<\/li>\n<li>Full admin panel \u2014 add, edit, and delete quotes without touching code<\/li>\n<li>CSV Export \u2014 download all your quotes as a spreadsheet-compatible .csv file<\/li>\n<li>CSV Import \u2014 bulk-upload quotes with automatic encoding detection (UTF-8 and Windows-1252 \/ Excel), BOM stripping, per-row validation, and a 5,000-row safety limit<\/li>\n<li>Clean, semantic HTML output using blockquote, p, and cite elements \u2014 easy to style with your theme's CSS<\/li>\n<li>Fully internationalised \u2014 every string is ready for translation via the d11-random-quote-loader text domain<\/li>\n<li>Safe uninstall \u2014 drops the custom table only when the plugin's own signature column is detected<\/li>\n<li>Security hardened \u2014 nonces on every form, current_user_can() capability checks, full output escaping, and wp_rand() throughout<\/li>\n<li>[d11rql_random_quote] shortcode \u2014 insert a random quote into any post, page, or text widget<\/li>\n<li>Quote categories \u2014 tag quotes and display different sets on different pages or sidebars<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the d11-random-quote-loader folder to \/wp-content\/plugins\/, or install directly through the WordPress plugin screen.<\/li>\n<li>Activate the plugin through the Plugins screen in WordPress.<\/li>\n<li>Go to Appearance &gt; Widgets and drag the D11 Random Quote Loader into your desired sidebar.<\/li>\n<li>Optionally set a widget title and click Save.<\/li>\n<li>Visit Quotes in your admin menu to add, edit, or delete quotes, or to import\/export via CSV.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"how%20do%20i%20add%20quotes%3F\"><h3>How do I add quotes?<\/h3><\/dt>\n<dd><p>Navigate to Quotes in your WordPress admin sidebar. Use the form at the top of the page to add a new quote and an optional author name.<\/p><\/dd>\n<dt id=\"can%20i%20import%20quotes%20in%20bulk%3F\"><h3>Can I import quotes in bulk?<\/h3><\/dt>\n<dd><p>Yes. Prepare a .csv file with two column headers: quote and author. Use the Import CSV section at the bottom of the Quotes admin page. The import replaces all existing quotes and supports up to 5,000 rows. Files saved from Excel (Windows-1252 encoding) are converted automatically.<\/p><\/dd>\n<dt id=\"how%20do%20i%20export%20my%20quotes%3F\"><h3>How do I export my quotes?<\/h3><\/dt>\n<dd><p>Click Export to CSV on the Quotes admin page. The file downloads immediately.<\/p><\/dd>\n<dt id=\"can%20i%20style%20the%20widget%20output%3F\"><h3>Can I style the widget output?<\/h3><\/dt>\n<dd><p>Yes. The widget outputs a blockquote.rqw-quote element containing a p.rqw-quote-text and, when an author is present, a cite.rqw-quote-author. Target these CSS classes in your theme's stylesheet.<\/p><\/dd>\n<dt id=\"will%20my%20quotes%20be%20deleted%20if%20i%20deactivate%20the%20plugin%3F\"><h3>Will my quotes be deleted if I deactivate the plugin?<\/h3><\/dt>\n<dd><p>No. Deactivating the plugin leaves the database table intact. Quotes are only deleted when you choose Delete on the Plugins screen, which triggers the uninstall routine.<\/p><\/dd>\n<dt id=\"is%20the%20plugin%20translation-ready%3F\"><h3>Is the plugin translation-ready?<\/h3><\/dt>\n<dd><p>Yes. All user-facing strings use the d11-random-quote-loader text domain and are ready for translation via .po\/.mo files in the \/languages\/ folder, or via translate.wordpress.org.<\/p><\/dd>\n<dt id=\"what%20php%20version%20is%20required%3F\"><h3>What PHP version is required?<\/h3><\/dt>\n<dd><p>PHP 7.4 or higher. PHP 8.0+ is fully supported and recommended.<\/p><\/dd>\n<dt id=\"how%20do%20i%20use%20the%20shortcode%3F\"><h3>How do I use the shortcode?<\/h3><\/dt>\n<dd><p>Place [d11rql_random_quote] anywhere in a post or page. Available parameters:<\/p>\n\n<p>[d11rql_random_quote]\n  [d11rql_random_quote title=\"Daily Quote\"]\n  [d11rql_random_quote category=\"inspiration\"]\n  [d11rql_random_quote title=\"Food for Thought\" category=\"philosophy\"]<\/p>\n\n<p>The shortcode outputs a div.rqw-shortcode wrapper containing a blockquote.rqw-shortcode-quote element, and an h3.rqw-shortcode-title when a title is provided.<\/p><\/dd>\n<dt id=\"how%20do%20categories%20work%3F\"><h3>How do categories work?<\/h3><\/dt>\n<dd><p>Assign a category name to any quote when adding or editing it in the Quotes admin page. Then use [d11rql_random_quote category=\"your-category\"] in a shortcode, or set a category in the widget settings. Quotes with no category assigned are treated as uncategorized and will appear in all category queries as a fallback.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>2.3<\/h4>\n\n<ul>\n<li>Security: renamed database table from {prefix}quotes to {prefix}d11rql_quotes, eliminating collision risk with other plugins. Existing installs are migrated automatically.<\/li>\n<li>Security: replaced TRUNCATE TABLE with DELETE FROM inside the CSV import transaction. TRUNCATE causes an implicit commit in MySQL, meaning a failed import could not be rolled back. DELETE FROM is fully transactional.<\/li>\n<li>Security: replaced explode()\/str_getcsv() CSV parser with a php:\/\/memory stream + fgetcsv(). The previous approach broke on quoted multi-line fields. The memory stream approach has no filesystem writes and correctly handles all RFC 4180 CSV edge cases.<\/li>\n<li>Synced D11RQL_MIN_WP_VERSION constant and plugin header to 6.9 to match readme.txt.<\/li>\n<\/ul>\n\n<h4>2.2<\/h4>\n\n<ul>\n<li>Renamed all internal function, constant, option, and transient prefixes from rqw_ (3 chars, too short) to d11rql_ to comply with WordPress.org prefix length requirements (minimum 4 characters).<\/li>\n<li>Updated plugin_signature value in database from rqw_v1 to d11rql_v1.<\/li>\n<li>No database schema changes \u2014 existing installs upgrade cleanly on next page load.<\/li>\n<\/ul>\n\n<h4>2.1<\/h4>\n\n<ul>\n<li>Changed shortcode tag from [random_quote] to [d11rql_random_quote] to comply with WordPress.org prefix requirements.<\/li>\n<li>Rewrote CSV import to use in-memory str_getcsv() parsing \u2014 no temporary filesystem writes.<\/li>\n<li>Removed load_plugin_textdomain() call, which is no longer needed for WordPress.org hosted plugins since WordPress 4.6.<\/li>\n<li>Fixed Contributors field in readme.txt to use correct WordPress.org username (briz_dad).<\/li>\n<\/ul>\n\n<h4>2.0.6<\/h4>\n\n<ul>\n<li>Compatibility: updated \"Tested up to\" to WordPress 7.0.<\/li>\n<li>Updated \"Requires at least\" to WordPress 6.9.<\/li>\n<li>No code or database changes.<\/li>\n<\/ul>\n\n<h4>2.0.5<\/h4>\n\n<ul>\n<li>Admin: added pagination to the Manage Quotes page. Defaults to 10 quotes per page with numbered page links and Previous\/Next controls.<\/li>\n<li>Admin: added a per-page dropdown (10, 25, 50, 75, 100) that persists across page navigation and category filtering.<\/li>\n<li>Admin: quote count display shows current range and total (e.g. \"Showing 1\u201310 of 74 quotes\").<\/li>\n<li>Admin: category filter links now reset to page 1 and preserve the current per-page setting.<\/li>\n<li>Admin: export description clarified to confirm all quotes are exported regardless of current page or filter.<\/li>\n<\/ul>\n\n<h4>2.0.4<\/h4>\n\n<ul>\n<li>Database: added an index on the category column for faster category-filtered queries on larger quote libraries. Applied automatically via dbDelta on next page load \u2014 no manual steps required.<\/li>\n<\/ul>\n\n<h4>2.0.3<\/h4>\n\n<ul>\n<li>Fix: Added DONOTCACHEPAGE constant to both the shortcode and widget output functions. This tells WP Super Cache, W3 Total Cache, WP Rocket, and other major caching plugins not to serve a static cached copy of pages containing a random quote \u2014 ensuring the quote is genuinely random on every page load for logged-out visitors.<\/li>\n<li>Data: encoding fix for smart quotes, em dashes, and emoji in imported CSV data (Mojibake caused by Windows-1252 bytes being mis-interpreted as UTF-8 during export).<\/li>\n<\/ul>\n\n<h4>2.0.2<\/h4>\n\n<ul>\n<li>Database: replaced all SELECT * queries with explicit column lists (id, quote, author, category) across all files.<\/li>\n<li>Database: CSV import now runs inside a MySQL transaction \u2014 if any insert fails mid-import, a ROLLBACK fully restores the original quotes rather than leaving a partial data set.<\/li>\n<li>Database: admin quote listing queries now use explicit column selection.<\/li>\n<li>No database schema changes \u2014 safe drop-in replacement for 2.0.1.<\/li>\n<\/ul>\n\n<h4>2.0.1<\/h4>\n\n<ul>\n<li>Security: capability check in admin form handler now fires before any superglobal access, closing a trivial bypass via spoofed $_GET['page'].<\/li>\n<li>Security: admin success notices (added\/updated\/deleted) now use per-user transients instead of URL parameters, preventing anyone from flashing misleading notices via crafted URLs.<\/li>\n<li>Security: uninstall.php now verifies the table exists before running SHOW COLUMNS, preventing a DB error on edge-case removal.<\/li>\n<li>Reliability: rqw_maybe_upgrade_db() now uses a static guard to prevent repeated dbDelta calls if update_option() fails transiently.<\/li>\n<li>Reliability: rqw_get_random_quote() now handles the COUNT\/OFFSET race condition \u2014 if a quote is deleted between the two queries, it falls back to the first available quote instead of silently returning nothing.<\/li>\n<li>Version bump to 2.0.1 (no database changes).<\/li>\n<\/ul>\n\n<h4>2.0<\/h4>\n\n<ul>\n<li>Added quote categories \u2014 assign a category to each quote and filter by category in the widget, shortcode, and admin page.<\/li>\n<li>Shortcode now accepts a category parameter: [d11rql_random_quote category=\"inspiration\"].<\/li>\n<li>Widget settings now include an optional Category field.<\/li>\n<li>Admin page: Category column added to the quotes table, category field in Add\/Edit forms, filter bar to view quotes by category, category autocomplete using HTML datalist.<\/li>\n<li>CSV export now includes the category column. CSV import supports an optional category column (backwards compatible with old files).<\/li>\n<li>Database: added category column (varchar 100) via dbDelta \u2014 safe, non-destructive upgrade for existing installations.<\/li>\n<li>Uncategorized quotes (empty category) appear in all category-filtered queries as a fallback.<\/li>\n<\/ul>\n\n<h4>1.9<\/h4>\n\n<ul>\n<li>Added [d11rql_random_quote] shortcode for displaying a random quote in any post or page.<\/li>\n<li>Shortcode supports an optional title parameter: [d11rql_random_quote title=\"Daily Quote\"].<\/li>\n<li>Shortcode output uses semantic blockquote\/cite markup with CSS class hooks (rqw-shortcode, rqw-shortcode-quote, rqw-shortcode-title).<\/li>\n<\/ul>\n\n<h4>1.8<\/h4>\n\n<ul>\n<li>WordPress.org submission release.<\/li>\n<li>Added Requires PHP: 7.4 header and runtime PHP\/WP version checks on activation.<\/li>\n<li>Added RQW_VERSION constant.<\/li>\n<li>Full WordPress Coding Standards pass: tabs for indentation, absint() replacing intval(), wp_rand() replacing rand(), gmdate() replacing date().<\/li>\n<li>All user-facing strings now use the d11-random-quote-loader text domain (previously some used the bare text_domain placeholder).<\/li>\n<li>Widget output updated to use semantic blockquote\/cite markup with CSS class hooks.<\/li>\n<li>Widget now renders before_title\/after_title when a title is set.<\/li>\n<li>Admin page function renamed to rqw_render_admin_page for consistent rqw_ namespacing.<\/li>\n<li>All $wpdb insert\/update\/delete calls now pass explicit format arrays.<\/li>\n<li>Added GPL-2.0-or-later SPDX licence identifier and @package docblock to every file.<\/li>\n<\/ul>\n\n<h4>1.7<\/h4>\n\n<ul>\n<li>CSV import: added per-row UTF-8 validation with skip-and-report for unreadable characters.<\/li>\n<li>CSV import: 5,000-row limit with count of skipped rows reported to the user.<\/li>\n<\/ul>\n\n<h4>1.6<\/h4>\n\n<ul>\n<li>CSV import: added BOM stripping and Windows-1252 to UTF-8 encoding conversion.<\/li>\n<li>CSV import: server-side MIME type and file-extension validation.<\/li>\n<\/ul>\n\n<h4>1.5<\/h4>\n\n<ul>\n<li>CSV export moved to admin-post.php for a proper browser file-download response.<\/li>\n<\/ul>\n\n<h4>1.4<\/h4>\n\n<ul>\n<li>Added CSV import and export functionality.<\/li>\n<\/ul>\n\n<h4>1.3<\/h4>\n\n<ul>\n<li>Added inline edit functionality for existing quotes.<\/li>\n<\/ul>\n\n<h4>1.2<\/h4>\n\n<ul>\n<li>Security pass: nonces added to all forms, current_user_can() checks on all admin actions.<\/li>\n<\/ul>\n\n<h4>1.1<\/h4>\n\n<ul>\n<li>Replaced ORDER BY RAND() with COUNT + OFFSET strategy for better database performance.<\/li>\n<\/ul>\n\n<h4>1.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Display a random quote from your own database on every page load, with a full admin panel for managing quotes and CSV import\/export.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/306314","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=306314"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/briz_dad"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=306314"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=306314"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=306314"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=306314"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=306314"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=306314"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}