Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions docs/Core-Modules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# Core Modules

WP Framework provides several Core modules that handle common WordPress functionality modifications. These modules are designed to be explicitly opted into by consuming applications (themes/plugins) rather than being automatically initialized.

## Available Core Modules

### HeadOverrides

The `HeadOverrides` module removes unwanted WordPress head elements that are typically not needed in production sites.

**Location**: `TenupFramework\Core\HeadOverrides`

**Functionality**:
- Removes WordPress generator meta tag (`wp_generator`)
- Removes Windows Live Writer manifest link (`wlwmanifest_link`)
- Removes Really Simple Discovery service endpoint link (`rsd_link`)

**Usage**:
```php
// Recommended: Array-based approach
$core_modules = [ \TenupFramework\Core\HeadOverrides::class ];
foreach ( $core_modules as $module_class ) {
$module = new $module_class();
if ( $module->can_register() ) {
$module->register();
}
}
```

### Emoji

The `Emoji` module disables WordPress core emoji functionality, which can improve performance by removing unnecessary scripts and styles.

**Location**: `TenupFramework\Core\Emoji`

**Functionality**:
- Removes emoji detection scripts from `wp_head` and admin
- Removes emoji-related styles from front-end and back-end
- Removes emoji-to-static-img conversion from feeds and email
- Disables TinyMCE emoji plugin
- Removes emoji CDN from DNS prefetching hints

**Usage**:
```php
// Recommended: Array-based approach
$core_modules = [ \TenupFramework\Core\Emoji::class ];
foreach ( $core_modules as $module_class ) {
$module = new $module_class();
if ( $module->can_register() ) {
$module->register();
}
}
```

## Core Module Characteristics

All Core modules follow these patterns:

### Module Interface Compliance
- Implement `TenupFramework\ModuleInterface`
- Use the `TenupFramework\Module` trait
- Provide `load_order()`, `can_register()`, and `register()` methods

### Load Order
Core modules typically use a load order of `5`, ensuring they initialize early in the module lifecycle.

### Explicit Opt-In
Core modules are **not automatically initialized** by the framework. Consuming applications must explicitly instantiate and register them.

## Integration Patterns

### Recommended: Array-Based Approach
The cleanest way to initialize Core modules is using an array and foreach loop:

```php
// Define the Core modules you want to use
$core_modules = [
\TenupFramework\Core\HeadOverrides::class,
\TenupFramework\Core\Emoji::class,
];

// Initialize each module
foreach ( $core_modules as $module_class ) {
$module = new $module_class();
if ( $module->can_register() ) {
$module->register();
}
}
```

### Manual Instantiation (Alternative)
```php
// Initialize specific Core modules individually
$head_overrides = new \TenupFramework\Core\HeadOverrides();
if ( $head_overrides->can_register() ) {
$head_overrides->register();
}

$emoji = new \TenupFramework\Core\Emoji();
if ( $emoji->can_register() ) {
$emoji->register();
}
```

### Configuration-Based Approach (Future Enhancement)
If using the configuration-based initialization pattern:

```php
// Using ModuleInitialization::init_specific_modules()
ModuleInitialization::instance()->init_specific_modules([
\TenupFramework\Core\HeadOverrides::class,
\TenupFramework\Core\Emoji::class,
]);
```

## Best Practices

### When to Use Core Modules
- **HeadOverrides**: Use when you want to remove WordPress generator meta and other unnecessary head elements
- **Emoji**: Use when you want to disable WordPress emoji functionality for performance reasons

### Conditional Loading
Consider loading Core modules conditionally based on your application's needs:

```php
// Build array of Core modules based on conditions
$core_modules = [ \TenupFramework\Core\HeadOverrides::class ];

// Only load emoji module in production
if ( wp_get_environment_type() === 'production' ) {
$core_modules[] = \TenupFramework\Core\Emoji::class;
}

// Initialize all selected modules
foreach ( $core_modules as $module_class ) {
$module = new $module_class();
if ( $module->can_register() ) {
$module->register();
}
}
```

### Testing
Core modules include comprehensive test suites that verify:
- Interface implementation
- Method existence and callability
- Source code verification of WordPress function calls
- Functional behavior testing

## Migration from Scaffold

If migrating from the WP Scaffold plugin's Core modules:

1. **Remove** the old Core module classes from your scaffold
2. **Add explicit opt-in** to the framework's Core modules
3. **Test** that functionality works as expected
4. **Verify** no regressions in your application

## Future Enhancements

### Framework Helper Method
A future enhancement could add a helper method to the `ModuleInitialization` class:

```php
// Potential future API
ModuleInitialization::init_core_modules([
\TenupFramework\Core\HeadOverrides::class,
\TenupFramework\Core\Emoji::class,
]);
```

This would internally handle the instantiation and registration logic, making the array-based approach even cleaner.

## Future Core Modules

The framework is designed to accommodate additional Core modules as needed. New modules should follow the same patterns:
- Implement `ModuleInterface`
- Use the `Module` trait
- Provide comprehensive test coverage
- Require explicit opt-in from consuming applications
3 changes: 3 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ WP Framework is a lightweight set of building blocks for structuring WordPress p
- Base classes for custom and core post types
- Base class for taxonomies
- Asset helpers that read modern build sidecars (`.asset.php`)
- Core modules for common WordPress functionality modifications

## Who is this for?
- External engineers — Start here: follow the Quick Start and then read Autoloading and Modules → Modules and Initialization → Post Types/Taxonomies → Asset Loading.
Expand All @@ -17,13 +18,15 @@ WP Framework is a lightweight set of building blocks for structuring WordPress p
3) Initialize modules: `TenupFramework\ModuleInitialization::instance()->init_classes( YOUR_PLUGIN_INC )`.
4) Implement small classes that implement `ModuleInterface` (use the `Module` trait) and optionally extend `AbstractPostType` / `AbstractTaxonomy`.
5) Load assets via the `GetAssetInfo` trait using dist/.asset.php sidecars.
6) Optionally opt into Core modules for common WordPress functionality modifications.

## Table of Contents
- [Autoloading and Modules](Autoloading.md) — how classes are discovered and initialized
- [Modules and Initialization](Modules-and-Initialization.md)
- [Post Types](Post-Types.md) — building custom and core post type integrations
- [Taxonomies](Taxonomies.md) — registering and configuring taxonomies
- [Asset Loading](Asset-Loading.md) — working with dist/.asset.php for dependencies and versioning
- [Core Modules](Core-Modules.md) — WordPress functionality modification modules

## Conventions
- Namespaces: use your project namespace (e.g., `YourVendor\\YourPlugin`) for app code; reference framework classes via the TenupFramework namespace.
Expand Down
102 changes: 102 additions & 0 deletions src/Core/Emoji.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
/**
* Emoji module to disable WordPress core emoji functionality.
*
* @package TenupFramework\Core
*/

declare( strict_types = 1 );

namespace TenupFramework\Core;

use TenupFramework\Module;
use TenupFramework\ModuleInterface;

/**
* Emoji class to manage WordPress core emoji functionality modifications.
*
* @package TenupFramework\Core
*/
class Emoji implements ModuleInterface {

use Module;

/**
* Used to alter the order in which classes are initialized.
*
* @return int The priority of the module.
*/
public function load_order(): int {
return 5;
}

/**
* Checks whether the Module should run within the current context.
*
* @return bool
*/
public function can_register(): bool {
return true;
}

/**
* Connects the Module with WordPress using Hooks and/or Filters.
*
* @return void
*/
public function register(): void {
// Remove the Emoji detection script.
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );

// Remove inline Emoji detection script.
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );

// Remove Emoji-related styles from front end and back end.
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_action( 'admin_print_styles', 'print_emoji_styles' );

// Remove Emoji-to-static-img conversion.
remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );

add_filter( 'tiny_mce_plugins', [ $this, 'disable_emojis_tinymce' ] );
add_filter( 'wp_resource_hints', [ $this, 'disable_emoji_dns_prefetch' ], 10, 2 );
}

/**
* Filter function used to remove the TinyMCE emoji plugin.
*
* @link https://developer.wordpress.org/reference/hooks/tiny_mce_plugins/
*
* @param array $plugins An array of default TinyMCE plugins.
* @return array An array of TinyMCE plugins, without wpemoji.
*/
public function disable_emojis_tinymce( array $plugins ): array {
if ( in_array( 'wpemoji', $plugins, true ) ) {
return array_diff( $plugins, [ 'wpemoji' ] );
}

return $plugins;
}

/**
* Remove emoji CDN hostname from DNS prefetching hints.
*
* @link https://developer.wordpress.org/reference/hooks/emoji_svg_url/
*
* @param array $urls URLs to print for resource hints.
* @param string $relation_type The relation type the URLs are printed for.
* @return array Difference between the two arrays.
*/
public function disable_emoji_dns_prefetch( array $urls, string $relation_type ): array {
if ( 'dns-prefetch' === $relation_type ) {
/** This filter is documented in wp-includes/formatting.php */
$emoji_svg_url = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/2/svg/' );

$urls = array_values( array_diff( $urls, [ $emoji_svg_url ] ) );
}

return $urls;
}
}
55 changes: 55 additions & 0 deletions src/Core/HeadOverrides.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* HeadOverrides
*
* @package TenupFramework
*/

declare( strict_types = 1 );

namespace TenupFramework\Core;

use TenupFramework\Module;
use TenupFramework\ModuleInterface;

/**
* Overrides class to manage WordPress core behavior modifications.
*
* @package TenupFramework\Core
*/
class HeadOverrides implements ModuleInterface {

use Module;

/**
* Used to alter the order in which classes are initialized.
*
* @return int The priority of the module.
*/
public function load_order(): int {
return 5;
}

/**
* Checks whether the Module should run within the current context.
*
* @return bool
*/
public function can_register(): bool {
return true;
}

/**
* Connects the Module with WordPress using Hooks and/or Filters.
*
* @return void
*/
public function register(): void {
// Remove WordPress generator meta.
remove_action( 'wp_head', 'wp_generator' );
// Remove Windows Live Writer manifest link.
remove_action( 'wp_head', 'wlwmanifest_link' );
// Remove the link to Really Simple Discovery service endpoint.
remove_action( 'wp_head', 'rsd_link' );
}
}
Loading