Skip to content

Feature/v2 refactor and renamer#20

Open
LC43 wants to merge 34 commits into
mainfrom
feature/v2-refactor-and-renamer
Open

Feature/v2 refactor and renamer#20
LC43 wants to merge 34 commits into
mainfrom
feature/v2-refactor-and-renamer

Conversation

@LC43

@LC43 LC43 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

No description provided.

LC43 added 7 commits June 20, 2026 18:14
Replace legacy .gitignore patterns with generated-artifact entries.
Remove blanket-silenced PHPCS rules in favour of targeted inline ignores.
Add composer.json with PSR-4 autoloading, dev dependencies
(PHPUnit 11, WPCS 3), scripts (lint, test, package, make-pot),
and lock file pinning saltus/framework plus PHPUnit and PHPCS packages.
Add phpunit.xml.dist and bin/package.php CLI for distributable ZIPs.
Remove obsolete package-lock.json as Node/Grunt is no longer used.
Move plugin header constants to defined() guards for safety.
Add PHP version check and Composer dependency check with admin notices.
Replace deprecated Loader stub with direct framework registration.
Convert Core properties from public to private typed fields with getters.
Add return type declarations to all methods across core classes.
Remove unused  property storage after construction.
@LC43 LC43 self-assigned this Jun 20, 2026
@LC43

LC43 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modernizes the Saltus Framework Demo plugin by upgrading the PHP requirement to 8.3, replacing Grunt build tasks with Composer scripts, and introducing a new plugin generator UI to download renamed copies of the plugin as a ZIP file. Feedback on these changes highlights a regex bug in the package name generator that mangles uppercase author names, a risk of corrupting third-party assets by globally replacing the version string '2.0.0', an unused $framework parameter in the Core constructor, and the necessity of clearing active output buffers before streaming the ZIP file to prevent archive corruption.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/Plugin/Renamer/PluginRenamer.php
Comment thread src/Plugin/Renamer/PluginRenamer.php
Comment thread src/Core.php Outdated
Comment thread framework-demo.php Outdated
Comment thread src/Plugin/Renamer/PluginRenamer.php Outdated
LC43 added 5 commits June 20, 2026 23:28
The Core class no longer needs the Saltus Framework reference. The framework is still instantiated and registered at the plugin level, but is no longer passed into Core. The unused unset() call in the constructor is removed.
Clear all output buffers before sending ZIP headers to prevent "headers already sent" errors.
The regex now allows uppercase letters to pass through before strtolower() runs. Previously, uppercase letters in author names were replaced with dashes, producing incorrect package name segments.
Verify that the renamer correctly replaces the PLUGIN_VERSION value in the main plugin file when a custom version is provided.
Verify the renamer correctly rewrites the composer.json package name from saltus/framework-demo to the target author/slug combination. The test uses a mixed-case author name (Acme Inc) to verify the updated regex preserves uppercase letters before strtolower conversion.
@LC43

LC43 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modernizes the Saltus Framework Demo plugin by upgrading the PHP requirement to 8.3, replacing the Grunt build system with Composer scripts, and introducing a new admin UI to generate and download renamed copies of the plugin as a ZIP file. It also updates array syntax to match WordPress standards and adds PHPUnit tests. The review feedback highlights three key improvement opportunities: correcting the return value check for wp_tempnam() and ensuring temporary files are cleaned up via a shutdown function, removing a redundant submenu page registration, and simplifying the unslashing of $_POST data using wp_unslash() directly.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/Plugin/Renamer/PluginRenamer.php
Comment thread src/Plugin/Admin/RenamerPage.php
Comment thread src/Plugin/Admin/RenamerPage.php
@LC43

LC43 commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modernizes the WordPress demo plugin by upgrading the PHP requirement to 8.3, replacing Grunt with Composer scripts, and refactoring the codebase to adhere to WordPress coding standards. It also introduces a new plugin renamer feature that allows users to generate and download a renamed copy of the plugin as a ZIP file, complete with PHPUnit tests. The review feedback highlights several critical improvements for the renamer feature: validating URLs before they are sanitized by esc_url_raw() to prevent validation bypasses, making validation error messages translatable, checking the return values of ZipArchive operations to handle failures gracefully, and ensuring the error query parameter is a string before sanitizing it to avoid PHP warnings.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/Plugin/Renamer/PluginIdentity.php
Comment thread src/Plugin/Renamer/PluginIdentity.php
Comment thread src/Plugin/Renamer/PluginRenamer.php Outdated
Comment thread src/Plugin/Renamer/PluginRenamer.php Outdated
Comment thread src/Plugin/Admin/RenamerPage.php Outdated
LC43 added 4 commits June 21, 2026 17:25
Check that $_GET['framework_demo_error'] is a string before
passing it to sanitize_text_field(), which expects a string.
A malicious array parameter would otherwise trigger PHP warnings.
Run validation before esc_url_raw() to catch invalid URLs
before they are silently converted to empty strings.

Wrap validation error messages in __() for i18n support.
ZipArchive::close() and addFromString() return false on
failure without throwing exceptions. Check their return
values and throw RuntimeException on failure to prevent
silently generating incomplete or corrupted ZIP files.
Restore WordPress function stubs removed in prior cleanup.
Make esc_url_raw return empty string for invalid URLs
to match real WordPress behavior.
@LC43

LC43 commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modernizes the WordPress plugin by upgrading the minimum PHP requirement to 8.3, replacing Grunt with Composer scripts, and introducing a new "Rename Plugin" feature that generates customized, renamed ZIP packages of the plugin. It also adds PHPUnit tests, updates coding standards, and refactors core classes to use typed properties and return types. The review feedback suggests improving security and usability on the renamer admin page by storing redirect error messages in WordPress Transients instead of passing them as raw URL query parameters.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/Plugin/Admin/RenamerPage.php Outdated
Comment thread src/Plugin/Admin/RenamerPage.php
@LC43

LC43 commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modernizes the plugin by replacing the Grunt-based build system with a Composer-based workflow, updating the PHP requirement to 8.3+, and introducing a generator UI to download a renamed copy of the plugin. Feedback on the changes highlights a critical bug in the renamer page that causes a blank screen on normal access due to an incorrect early return on the nonce check. Additionally, it is recommended to restrict admin asset enqueuing to the plugin's specific pages to avoid global conflicts, and to update the PHPCompatibility testVersion in phpcs.xml to 8.3- to prevent false positives.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/Plugin/Admin/RenamerPage.php Outdated
Comment thread src/Plugin/Assets.php Outdated
Comment thread phpcs.xml Outdated
LC43 added 3 commits June 22, 2026 00:13
Move the nonce verification out of the top-level page render
block so the page renders normally on first visit. Only verify
the error redirect nonce when an error token is present.
Replace unset of the hook_suffix with an early return guard
that only loads styles when the suffix contains 'framework-demo'.
This avoids styling conflicts on other admin pages.
The plugin uses PHP 8.0+ features such as mixed return types.
The previous testVersion of 7.4- caused false positive errors
from PHPCompatibility.
@LC43

LC43 commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modernizes the Saltus Framework Demo plugin by upgrading the minimum PHP requirement to 8.3, replacing the Grunt-based build system with Composer scripts, and introducing a new admin feature to generate renamed copies of the plugin as ZIP files. The review feedback highlights several opportunities for improvement, including failing fast in stream_zip() by checking headers early, defensively verifying request inputs to avoid array-to-string casting warnings, trimming vendor names to prevent malformed Composer package names, utilizing PHP 8's str_contains() in Assets.php, and ensuring the global $post object is a valid WP_Post instance before accessing its properties.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/Plugin/Renamer/PluginRenamer.php
Comment thread src/Plugin/Renamer/PluginIdentity.php
Comment thread src/Plugin/Renamer/PluginRenamer.php
Comment thread src/Plugin/Assets.php
Comment thread src/models/post-type-all.php
LC43 added 4 commits June 22, 2026 00:36
Check headers_sent() before disk I/O in stream_zip() so the application fails fast when streaming is impossible.

Trim leading and trailing dashes from the generated vendor name in package_name() to prevent malformed Composer package names such as 'acme-inc-/my-plugin'.

Existing tests for package_name verification are extended to cover the dash-trimming edge case.
Defensively verify that request values are not arrays before casting
to string in from_request(), preventing PHP 8.x warnings when a
malformed or malicious request submits an array for a text field.
Since this plugin requires PHP 8.3 or newer, use the more modern and
readable str_contains() function instead of strpos().
Defensively verify that the global $post object is a valid WP_Post
instance before accessing its properties, preventing potential PHP
warnings or errors if the global is null or uninitialized.
@LC43

LC43 commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modernizes the Saltus Framework Demo plugin by upgrading requirements to PHP 8.3 and PHPUnit 11, replacing Grunt tasks with Composer scripts, and introducing a new admin UI and backend logic to generate renamed plugin ZIP files. The review feedback highlights several opportunities to improve robustness and correctness: using substr instead of str_replace to safely strip root and source directories, adding a safety check to prevent an infinite loop in ob_end_clean(), providing a fallback vendor name for non-ASCII author names in PluginRenamer, removing a redundant validation call in PluginIdentity, and correcting typos in post-type-all.php (specifically the 'post_schedulled' key and the word 'permanetly').

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread bin/package.php Outdated
Comment thread src/Plugin/Renamer/PluginRenamer.php Outdated
Comment thread src/Plugin/Renamer/PluginRenamer.php
Comment thread src/Plugin/Renamer/PluginRenamer.php Outdated
Comment thread src/Plugin/Renamer/PluginIdentity.php Outdated
Comment thread src/models/post-type-all.php Outdated
Comment thread src/models/post-type-all.php Outdated
LC43 added 6 commits June 22, 2026 21:19
Replace str_replace with substr for removing root/source directory
prefixes from file paths. str_replace can produce incorrect results when
the directory name appears elsewhere in the path. Using substr with the
length of the directory path is safer and more robust.
When the author name contains only non-ASCII characters (Cyrillic,
Chinese, Japanese, emoji), the sanitized vendor name becomes empty,
resulting in an invalid package name like '/plugin-slug'. Fall back
to 'local' to ensure composer.json remains valid.
If an active output buffer was started with flags preventing it from being
cleaned or removed, ob_end_clean() returns false and the buffer level
does not decrease. This could cause an infinite loop. Breaking when
ob_end_clean() fails prevents this.
self::validate() was called twice in from_request(): once before and once
after esc_url_raw(). Since esc_url_raw() only sanitizes URLs and does not
make a valid URL invalid, the first call is unnecessary. Fix the test
bootstrap's esc_url_raw mock to match WordPress behavior (strip bad
characters rather than return empty for non-URLs).
Fix the typo 'post_schedulled' -> 'post_scheduled'. The standard
WordPress post updated message key is 'post_scheduled' (one 'l').
Fix the spelling 'permanetly' -> 'permanently' in the bulk delete
message for the book post type.
@LC43

LC43 commented Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modernizes the Saltus Framework Demo plugin by upgrading the minimum PHP requirement to 8.3, replacing the Grunt build system with Composer scripts, and refactoring the core codebase to use strict typing and modern PHP features. It also introduces a new admin generator UI to let users download a renamed copy of the demo plugin as a ZIP file, backed by PHPUnit tests. The review feedback identifies two critical issues: a text domain mismatch bug in the renamer utility that breaks translations when the custom text domain differs from the plugin slug, and an invalid absolute path passed to load_plugin_textdomain which prevents local translation files from loading.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +145 to +162
private function rewrite_contents( string $contents, PluginIdentity $identity ): string {
$replacements = array(
self::ORIGINAL_NAMESPACE_SEGMENT => $identity->namespace_segment,
self::ORIGINAL_PACKAGE => $this->package_name( $identity ),
self::ORIGINAL_MAIN_FILE => $identity->main_file,
self::ORIGINAL_PREFIX_UPPER => strtoupper( $identity->prefix ),
self::ORIGINAL_PREFIX => $identity->prefix,
'Plugin Name: ' . self::ORIGINAL_NAME => 'Plugin Name: ' . $identity->plugin_name,
'Description: ' . self::ORIGINAL_DESCRIPTION => 'Description: ' . $identity->description,
'Plugin URI: ' . self::ORIGINAL_PLUGIN_URI => 'Plugin URI: ' . $identity->plugin_uri,
'Author URI: ' . self::ORIGINAL_AUTHOR_URI => 'Author URI: ' . $identity->author_uri,
'Author: ' . self::ORIGINAL_AUTHOR => 'Author: ' . $identity->author,
self::ORIGINAL_SLUG => $identity->plugin_slug,
"PLUGIN_VERSION', '" . self::ORIGINAL_VERSION . "'" => "PLUGIN_VERSION', '" . $identity->version . "'",
self::ORIGINAL_VERSION => $identity->version,
);

return strtr( $contents, $replacements );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

⚠️ Text Domain Mismatch Bug

There is a discrepancy between how the plugin_slug and text_domain fields are handled during the renaming process:

  1. In target_path(), the .pot translation file is renamed using $identity->text_domain (e.g., my-custom-domain.pot).
  2. In rewrite_contents(), the text domain header and all translation calls (e.g., __( 'Books', 'framework-demo' )) are rewritten using $identity->plugin_slug (because 'framework-demo' is mapped to $identity->plugin_slug).

If a user enters a text_domain that is different from the plugin_slug, the generated plugin's PHP files will use the slug as the text domain (e.g., my-plugin), while the translation files in the languages/ directory will be named after the custom text domain (e.g., my-custom-domain-en_US.mo). As a result, WordPress will fail to load any translations due to this domain mismatch.

Recommended Solutions:

  • Option A (Simplest & Standard): Remove the text_domain field from the generator UI entirely and always use the plugin_slug as the text domain. In the WordPress ecosystem, it is standard practice for the plugin slug and text domain to be identical.
  • Option B: If you must support different values, you need to update rewrite_contents() to specifically target and replace the text domain header and translation calls with $identity->text_domain instead of $identity->plugin_slug.

Comment thread src/Core.php
$i18n = new Plugin\I18n( $this->name );
private function set_locale(): void {
$i18n = new I18n( $this->name );
$i18n->load_plugin_textdomain( dirname( $this->file_path ) );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

🐛 Absolute Path Passed to load_plugin_textdomain

In WordPress, the third argument of load_plugin_textdomain() must be a relative path to WP_PLUGIN_DIR, not an absolute path.

Passing an absolute path (returned by dirname( $this->file_path )) causes WordPress to concatenate WP_PLUGIN_DIR with the absolute path, resulting in an invalid path like /wp-content/plugins/var/www/.../languages/. This prevents local translation files (.mo) from being loaded.

To fix this, use plugin_basename() to get the relative path.

		$i18n->load_plugin_textdomain( dirname( plugin_basename( $this->file_path ) ) );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant