Changelogs

Follow the improvements and fixes in each product release.

Products

Recent Releases

Permalink

GT Page Blocks Builder 2.7.4

  • The two builder filters and the four helper functions now carry the gt_ prefix, matching everything else the plugin exposes: gt_page_blocks_builder_preview_injection, gt_page_blocks_builder_post_types, gt_page_blocks_builder_url(), gt_page_blocks_builder_post_types(), gt_page_blocks_builder_nonce_action() and gt_page_blocks_preview_nonce_action().
  • Every old md_-prefixed name still works. The filters run immediately before their replacements, so the current one has the last word, and the functions delegate to theirs. Each points at its replacement under WP_DEBUG while in use and is silent otherwise, so existing snippets keep working and nobody gets a notice for a hook they never touched.
  • gt_page_blocks_builder_nonce_action() still returns its original string. It identifies nonces already issued into open builder tabs and saved URLs, and renaming the value would invalidate them for nothing.
Permalink

GT Page Blocks Builder 2.7.3

  • Page settings live in one dialog. Title, slug, template, import and export are page-level rather than section-level, so they sit together behind one button instead of being spread across the top bar and the section panel. The slug shows the permalink it will produce, and WordPress’ own sanitised result is adopted after saving rather than what was typed.
  • Sections get an id. Where the outermost element has none, the builder writes one in — an id you wrote yourself is never touched. The edit is made on the opening tag as text rather than by reparsing the markup, so quote style, self-closing tags and indentation survive, a > inside an attribute value does not end the tag early, and data-id= is not mistaken for id=. Sections named after a generated id are listed by their first ten characters of text instead.
  • Every section drags, from anywhere on its row. Reordering was HTML5 drag-and-drop on a row covered by buttons, and a mousedown on a form control does not start its draggable ancestor’s drag — in practice only a 14px grip worked. Locked and linked sections reorder too, a drop can land past the last row, and the drop point is shown while dragging.
  • Clicking anything in the preview selects the section it belongs to, without disturbing the inline edit the same click opens.
  • The AI assistant applies its own answers. A reply lands in the section and the preview updates, rather than arriving as code to copy into the editor beside it; bundled CSS and JS are unpacked into their own panes, so one prompt can fill all three. Undo restores the section exactly. A “Whole page” toggle sends every section’s code with the prompt, so generated markup matches the class names, spacing and variables already on the page.
  • Latest AI models, and one list behind them. The model list was duplicated in four places and had already drifted — the registered default and the request-path fallback named different models, so a saved choice could be silently replaced. GPT-5.6 Luna is the new default, alongside the Claude 5 family.
  • Locked blocks can be deleted from the section panel. Locked means the builder will not rewrite a block’s markup, not that the block has to stay on the page. It asks first, and the save guard that refuses to drop blocks the builder cannot rebuild stays exactly as strict. Their empty code panes are hidden.
  • The builder keeps its own palette on any theme. It renders on a front-end route, so the active theme’s stylesheet loads beside it — and themes style bare select, input, textarea, pre and details under a [data-theme] ancestor, which outranked the builder’s own rules. Controls were wearing the theme’s dark palette while the chrome around them stayed light, a tiled dropdown arrow filled the model picker with black triangles, and stray label and textarea margins pushed controls off their rows. The preview iframe had the mirror-image problem: a transparent body took the operating system’s dark canvas while the theme supplied its light-mode text.
  • Detach a copy is a real button again, with a broken-link icon. It carried two class names this plugin has never defined and fell through to the browser’s default.
  • Plainer names in the code toolbar: wpauto is Auto-format, PHP is Run PHP, and the bare “JS:” prefix is a Script label. The AI composer sends on Enter, so its button is an arrow.
Permalink

GT Page Blocks Builder 2.7.2

Fixed

Scrolling was slow, or stalled entirely, while blocks showed their visual preview.

Every Page Block in preview mode is a separate document carrying the whole theme stylesheet set — measured at roughly 25 stylesheets and 2,200 CSS rules to style about 30 elements, duplicated per block. A page of eight blocks therefore kept around 200 stylesheets and 17,600 rules alive at once, each in its own compositing context, and scrolling paid for all of it. Switching a block to code mode destroyed its frame, which is why code mode always felt fine.

Previews are now mounted only while within 800px of the viewport and unmounted beyond it. On a 12-block page that means at most 3 frames live instead of 12, and 75 stylesheets instead of 300. A holder element retains each frame’s measured height whether or not it is mounted, so unmounting never collapses a block or moves the scroll position.

Preview fidelity is unchanged: a mounted frame still loads the full theme stylesheet set and theme.json global styles.

Permalink

GT Page Blocks Builder 2.7.1

Fixed

Code editors were unusable inside the block canvas. wp.codeEditor loads into the admin document, but the block canvas has been an iframe since WP 6.3. A CodeMirror mounted there resolves focus and key events against the outer document, so it rendered correctly and could not be clicked into or typed in. The plain textarea is now used there, as core’s Custom HTML block does. Tab in that textarea also silently discarded its indent; it now commits properly.

Block editor UI shipped unstyled. Styles enqueued for the editor only reach the outer admin document, so the block’s own chrome had no CSS and the device-preview controls rendered as blank squares with no dashicons. The stylesheet is now registered as the block’s editor_style, which is what gets it into the canvas.

Inline block CSS could be silently dropped. Whether a block emitted its <style> was gated on a request-global flag raised by any block on the queried post. A block rendered from a widget, synced pattern, or template part was silenced by a flag raised on another block’s behalf. CSS is now tracked per block.

minify_css corrupted quoted strings and math functions. [style*="font-weight: 300"] and [style*="font-weight:300"] are different selectors; collapsing the space merged them. Separately, clamp(6.75rem, 6rem + 2.2vw, 9rem) requires the spaces around +, while the sibling combinator requires collapsing them. Both are now handled.

Changed

  • Previews load theme.json global styles alongside every theme stylesheet, so var() resolves as it does on the front end.
  • The CSS editor suggests the custom properties the active theme defines, harvested from its stylesheets and theme.json.
  • The block editor chrome now follows the WordPress admin: its palette, 2px radii, system font, and standard button treatment.
  • The format toggle applies wpautop(), matching its label, instead of running the whole the_content filter chain from inside a block that is itself rendering during the_content.
Permalink

Dynamic Month & Year into Posts 1.8.1

What’s Changed

  • Fixed: Recurring February 29 countdowns now produce the same valid leap-day result in PHP and the browser.
  • Fixed: Invalid countdown dates no longer display as zero days, and the default day label is plural-aware.
  • Fixed: WP-CLI accepts both complete plugin shortcodes and date types with named options.
  • Improved: Added WordPress 7.1 compatibility, content-role block metadata, current dependency security fixes and wider runtime checks.
  • Improved: Corrected countdown, editor, cache, pattern and WP-CLI documentation.

Commits

  • Release 1.8.1 (5e79c05)

Full Changelog: https://github.com/wpgaurav/dynamic-month-year-into-posts/compare/v1.8.0…v1.8.1

Permalink

GT Performance 1.0.5

Fixed

  • Uninstalling with data removal enabled deleted this plugin’s options and tables but never touched the filesystem, so wp-content/cache/gt-performance/ survived in full: cached HTML, generated CSS and JavaScript, logs, and both configuration files. redis-config.json.php holds a host, username, and password. The guard kept those unreadable over HTTP, but someone who asked for their data to be removed should not be left with credentials in wp-content. Uninstall now removes the directory, resolving the path the way Core\Paths does and confirming with realpath() that it still sits inside wp-content before deleting anything. wp-content/cache itself is left for other plugins.
Permalink

GT Performance 1.0.4

Removed

  • All upgrade compatibility carried since 1.0.1. DropinRuntime::serve() no longer loads ConfigFile on behalf of a drop-in published before 1.0.1, Settings::compile() no longer deletes the configuration files those releases wrote, Database::install() no longer drops their tables, and uninstall.php no longer lists their names.

Upgrade note

  • A site running 1.0.0 or earlier still has that release’s generated advanced-cache.php on disk. It loads a fixed list of runtime files that predates ConfigFile, so on the first request after this update it raises a fatal from wp-settings.php, before WordPress can catch it, taking the front end and wp-admin down together. Replace the drop-in before or during the update. The build distributed from gauravtiwari.org carries a migrator that does this automatically; for any other route, run the standalone migration snippet first: https://gist.github.com/wpgaurav/03d61d313df00b4127db92393ed74681
Permalink

GT Performance 1.0.3

Fixed

  • The License screen’s Activate, Deactivate, and Check buttons returned a blank page in the store build. Identical cause to the controls fixed in 1.0.2 – the handlers were still registered as admin_post_gtp_license_* while the buttons submitted gtperf_license_* – in a file the 1.0.2 sweep did not reach. The WordPress.org build has no licensing code and was never affected.
  • AdminActionWiringTest now discovers every PHP file under src/ instead of checking a hardcoded list of four. The hardcoded list was the same mistake the test exists to catch: it could not see the licensing module, which only ships in the store build, so 1.0.2 shipped believing the wiring was fully verified.
Permalink

GT Performance 1.0.2

Fixed

  • Every admin control in 1.0.1 returned a blank page. The 1.0.1 rename moved the action names the controls submit from gtp_ to gtperf_, but left all 21 add_action( 'admin_post_gtp_...' ) and add_action( 'wp_ajax_gtp_...' ) registrations untouched, so nothing was hooked to the names being submitted. WordPress does not error in that case: it fires an action with no listeners and exits, which the browser renders as an empty response and which leaves no trace in the error log. Purge, Cloudflare connect/sync/preview/diagnose/token, Redis test and install, page-cache drop-in install, xCloud refresh, purge verification, Commerce Safety Lab, CSS training and regeneration, Fleet export and import, database cleanup, the admin-bar quick actions, the CSS report poll, and the Private Islands fragment endpoint were all dead.
  • The rename missed these because it matched \bgtp_, and in admin_post_gtp_purge the gtp_ is preceded by an underscore, which is a word character, so the boundary never applied. Hook strings are the one place that flaw could hide, and nothing compared the two sides.

Added

  • AdminActionWiringTest asserts that every action an admin control submits, every admin-bar action, and every AJAX action posted by the bundled JavaScript has a matching handler registered, and that no hook is registered under the retired prefix. A silent-blank-page regression of this shape now fails the test suite.
Permalink

GT Performance 1.0.1

Security

  • The compiled cache configuration and the Redis runtime configuration are no longer executable PHP. Both are stored as JSON behind a fixed <?php exit; ?> guard line and are read with file_get_contents() and json_decode(), never included. The guard keeps a direct web request from disclosing the Redis credentials on servers that do not honour .htaccess.
  • The early cache drop-in and RequestContext::fromGlobals() now sanitize the request through one shared implementation. Control characters are stripped and every name and value is bounded before any of it reaches the gt_performance_html filter.

Fixed

  • Updating from 1.0.0 took the whole site down. The drop-in published by that release loads a fixed list of runtime files that predates ConfigFile, so the moment the new plugin files landed it fatally errored inside wp-settings.php — before WordPress exists to catch it — taking the front end and wp-admin down together with no way back except filesystem access. DropinRuntime::serve() now loads its own dependency when an older drop-in did not.
  • Schema 3 renames this plugin’s tables from the gtp_ prefix to gtperf_. Without a schema bump the upgrade left the old tables in place and every queue, dependency, and CSS artifact query failed against a table that did not exist. The upgrade now creates the renamed tables and drops the superseded ones.
  • WpCacheConstant::enable() rewrote an already-correct WP_CACHE line to an identical value, read the unchanged file as a failed update, and returned an error — which made DropinInstaller::install() delete the drop-in it had just published. Installing twice in a row disabled page caching.
  • DropinInstaller::syncVersion() gated only on the version, so a migrated or restored site running the same release from a new path kept a compiled configuration naming the old directory. The drop-in found nothing to load and the site served uncached indefinitely without reporting anything. The gate now tracks the location alongside the version.
  • Keyboard focus styles were pruned out of generated CSS. :focus-visible and :focus-within matched the shorter focus alternative in the dynamic-state pattern, leaving -visible and -within fused to the class name, so the rules matched nothing and were removed as unused.
  • RequestContext::fromGlobals() did not unslash the superglobals, so any URL, query value, or cookie containing a quote hashed differently in WordPress than in the drop-in and could never produce a cache hit.
  • DropinInstaller::installedVersion() captured the trailing period after the drop-in signature, which made every version comparison unequal and reinstalled the drop-in on each request.

Changed

  • Page-cache entry metadata is now <hash>.meta.json instead of a generated <hash>.meta.php. Because metadata no longer passes through opcache, the opcode-invalidation workaround is gone along with the stale-metadata window it covered on hosts running opcache.validate_timestamps=0.
  • advanced-cache.php is a bundled file copied verbatim from dropins/, with only its version stamped in. It resolves the cache root from WP_CONTENT_DIR and the plugin directory from the compiled configuration, so no path is baked into the published drop-in.
  • Every output buffer the plugin opens is closed explicitly through Core\OutputBuffer, on shutdown at priority 0, ahead of core’s own wp_ob_end_flush_all().
  • Renamed the GTP_ and gtp_ prefixes to GTPERF_ and gtperf_ across constants, transients, AJAX actions, the cron schedule, the Private Islands shortcode, and the Redis key prefix. There is no compatibility shim: wp-config.php constants and any stored shortcode must use the new names.
  • Updated sabberworm/php-css-parser from 8.9.0 to 9.4.0. Version 9 requires thecodingmachine/safe at runtime, which adds about 2.4 MB to the package and eagerly loads 79 function-definition files when the plugin bootstraps. That cost lands only on full WordPress requests, measured at roughly 5 ms; requests served from the page cache never load the plugin autoloader and are unaffected.
  • The compiled configuration files are now config.json.php and redis-config.json.php. The names deliberately differ from the config.php and redis-config.php used up to 1.0.0: a drop-in left over from that release reads those paths with require, so pointing the new guarded files at the old names could have blanked every front-end response if the drop-in swap did not complete. Compiling also deletes the old files.
  • dropins/ is now covered by the coding-standards run.
Permalink

GT Performance 1.0.0

Changed

  • First stable release, distributed free through the WordPress.org plugin directory.
  • Removed FluentCart licensing and the custom updater. Plugin updates now arrive through the normal WordPress.org update flow with no license key, activation, or weekly verification cron. The License tab, its admin-post actions, and the gt_performance_verify_license schedule are gone; deactivation and uninstall clean up state left by earlier licensed builds.
  • Fleet Console no longer requires a license. Policy bundles are signed with a key derived from a shared fleet signing secret saved on each site (encrypted at rest) or defined as GTPERF_FLEET_SIGNING_SECRET in wp-config.php. The secret itself is stripped from exported bundles.
  • Uninstall now also removes the fleet site identity and event log options.
Permalink

GT Extensions for FluentCart 2.4.1

Patch release for 2.4.0.

Converts product prices a theme renders itself. 2.4.0 made the storefront currency symbol follow the visitor’s selection, so the cart drawer would stop labelling converted amounts with the store currency’s sign. Prices inside FluentCart’s own blocks were converted to match — but a theme can render a product price too, reading the cached price span straight from the database and formatting it with FluentCart’s helper. No filter can reach a number obtained that way, so such a price showed the right symbol against an unconverted amount.

Single product pages are now transcoded in one pass over the whole response, which covers theme and third-party output as well. The page pass and the per-block passes are mutually exclusive, so nothing is converted twice, and the buffer returns the original markup on any error rather than swallowing the page.

Also maps the stored price-span columns, so a product whose cached span has drifted from its variations still converts.

Everything in 2.4.0 is included.