mirror of
https://github.com/Heretek-AI/heretek-control-core.git
synced 2026-10-12 02:03:55 +00:00
Sweeps shipped copy clean of em dashes: readme.txt, README.md, CHANGELOG.md, the bundled sample prompts, and user-facing PHP strings (tool descriptions, admin labels). PHP was swept on non-comment lines only, so developer docblocks and inline comments are untouched. Internal dev docs (CLAUDE.md, docs/) were deliberately left alone. Replacements are contextual: colons for label/definition patterns, commas for asides, en dashes for numeric ranges. The .mcpb bundle display_name now reads "EMCP Tools - <host>" with a plain hyphen; its test is updated to match. Fixing CHANGELOG.md also clears the em dashes from the website's generated changelog on the next site build, since that file is its source. Verified: php -l clean on every touched file, pro suite 1559 pass, public suite 102 pass. Bumps the pro submodule for the Pro-side sweep.
163 lines
4.7 KiB
PHP
163 lines
4.7 KiB
PHP
<?php
|
|
/**
|
|
* Scaffolds and activates a child theme of the active parent theme.
|
|
*
|
|
* This is the framework-agnostic enabler for agent-driven theme file edits: it
|
|
* creates `style.css` + a minimal `functions.php` inside a fresh child theme
|
|
* directory and switches to it. The agent then performs file writes through the
|
|
* existing Filesystem tools (ABSPATH-confined, `edit_files`-gated, backed up,
|
|
* audit-logged) targeting the returned child directory.
|
|
*
|
|
* Deliberately conservative: it only ever creates a child of the CURRENT active
|
|
* parent, refuses when the active theme is already a child (no grandchildren),
|
|
* never touches the parent or any other theme, and is idempotent (an existing
|
|
* child is activated, never overwritten).
|
|
*
|
|
* @package EMCP_Tools
|
|
* @since 3.4.0
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Child theme scaffolder.
|
|
*/
|
|
class EMCP_Tools_Child_Theme_Builder {
|
|
|
|
/**
|
|
* Whether the active theme is itself a child (stylesheet != template).
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function is_active_a_child(): bool {
|
|
return get_stylesheet() !== get_template();
|
|
}
|
|
|
|
/**
|
|
* The active parent (template) slug.
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function parent_slug(): string {
|
|
return (string) get_template();
|
|
}
|
|
|
|
/**
|
|
* The child theme slug (`<parent>-child`).
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function child_slug(): string {
|
|
return self::parent_slug() . '-child';
|
|
}
|
|
|
|
/**
|
|
* The child theme directory path.
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function child_dir(): string {
|
|
return trailingslashit( get_theme_root() ) . self::child_slug();
|
|
}
|
|
|
|
/**
|
|
* Whether the child theme directory already exists on disk.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function child_exists(): bool {
|
|
return is_dir( self::child_dir() );
|
|
}
|
|
|
|
/**
|
|
* Create (if needed) and activate the child theme.
|
|
*
|
|
* @return array|WP_Error { child, parent, directory, activated, created } or error.
|
|
*/
|
|
public static function create() {
|
|
if ( self::is_active_a_child() ) {
|
|
return new WP_Error(
|
|
'is_child',
|
|
__( 'The active theme is already a child theme; refusing to create a grandchild.', 'emcp-tools' )
|
|
);
|
|
}
|
|
|
|
$parent = self::parent_slug();
|
|
$slug = self::child_slug();
|
|
$dir = self::child_dir();
|
|
$existed = self::child_exists();
|
|
|
|
if ( ! $existed ) {
|
|
if ( ! wp_mkdir_p( $dir ) ) {
|
|
return new WP_Error( 'mkdir_failed', __( 'Could not create the child theme directory.', 'emcp-tools' ) );
|
|
}
|
|
$parent_theme = wp_get_theme( $parent );
|
|
$parent_name = ( $parent_theme && '' !== (string) $parent_theme->get( 'Name' ) )
|
|
? (string) $parent_theme->get( 'Name' )
|
|
: ucfirst( $parent );
|
|
|
|
$wrote_style = self::write_file( $dir . '/style.css', self::style_css( $parent, $parent_name ) );
|
|
$wrote_funcs = self::write_file( $dir . '/functions.php', self::functions_php( $parent_name ) );
|
|
if ( false === $wrote_style || false === $wrote_funcs ) {
|
|
return new WP_Error( 'write_failed', __( 'Could not write the child theme files.', 'emcp-tools' ) );
|
|
}
|
|
}
|
|
|
|
switch_theme( $slug );
|
|
|
|
return array(
|
|
'child' => $slug,
|
|
'parent' => $parent,
|
|
'directory' => $dir,
|
|
'activated' => true,
|
|
'created' => ! $existed,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Write a file, preferring WP_Filesystem when initialized, else direct
|
|
* (matching the Filesystem tools' direct-FS posture). The target is always
|
|
* inside wp-content/themes/<child>/.
|
|
*
|
|
* @param string $path Absolute path.
|
|
* @param string $contents File contents.
|
|
* @return int|false Bytes written, or false on failure.
|
|
*/
|
|
private static function write_file( string $path, string $contents ) {
|
|
global $wp_filesystem;
|
|
if ( $wp_filesystem && is_object( $wp_filesystem ) && method_exists( $wp_filesystem, 'put_contents' ) ) {
|
|
return $wp_filesystem->put_contents( $path, $contents ) ? strlen( $contents ) : false;
|
|
}
|
|
return file_put_contents( $path, $contents );
|
|
}
|
|
|
|
/**
|
|
* @param string $parent Parent template slug.
|
|
* @param string $parent_name Parent display name.
|
|
* @return string
|
|
*/
|
|
private static function style_css( string $parent, string $parent_name ): string {
|
|
return "/*\n"
|
|
. 'Theme Name: ' . $parent_name . " Child\n"
|
|
. 'Template: ' . $parent . "\n"
|
|
. "Version: 1.0.0\n"
|
|
. 'Description: Child theme of ' . $parent_name . ", generated by EMCP Tools.\n"
|
|
. "*/\n";
|
|
}
|
|
|
|
/**
|
|
* @param string $parent_name Parent display name.
|
|
* @return string
|
|
*/
|
|
private static function functions_php( string $parent_name ): string {
|
|
return "<?php\n"
|
|
. '// ' . $parent_name . " child theme, generated by EMCP Tools.\n"
|
|
. "if ( ! defined( 'ABSPATH' ) ) { exit; }\n\n"
|
|
. "add_action( 'wp_enqueue_scripts', function () {\n"
|
|
. "\twp_enqueue_style( 'emcp-parent-style', get_template_directory_uri() . '/style.css' );\n"
|
|
. "} );\n";
|
|
}
|
|
}
|