### Running ModulesPress Docs - Bash
Source: https://github.com/devsroutes/modulespress-docs/blob/master/README.md
These commands provide the quick start guide to set up and run the documentation project locally. `npm install` fetches necessary dependencies, `npm start` launches a local development server for live preview, and `npm run build` compiles the project for production deployment.
```bash
# Install dependencies
npm install
# Start development server
npm start
# Build for production
npm run build
```
--------------------------------
### Create New ModulesPress Plugin Project (Bash)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/02-installation.md
Executes the ModulesPress CLI command to initiate the creation of a new plugin project. The command guides the user through configuration prompts and automatically sets up the project directory, dependencies, and initial files.
```bash
modulespress new
```
--------------------------------
### Install ModulesPress CLI via Composer (Bash)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/02-installation.md
Installs the ModulesPress command-line interface tool globally using Composer. This tool is a prerequisite for creating and managing ModulesPress plugin projects easily.
```bash
composer global require modulespress\/cli
```
--------------------------------
### Example Generated ModulesPress Controller (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
This PHP snippet shows an example of a controller class generated by the ModulesPress CLI. It includes `#[Injectable]` and `#[RestController]` attributes and provides boilerplate methods for GET and POST requests with parameter and body handling.
```php
#[Injectable]
#[RestController("/namespace")]
class ControllerName
{
#[Get(':id')]
public function get(#[Param('id')] string $id): array {}
#[Post]
public function create(#[Body] array $body): array {}
}
```
--------------------------------
### Installing ModulesPress CLI using Composer (Bash)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
Installs the ModulesPress CLI tool globally on your system using Composer. This command requires Composer to be installed and accessible. After installation, you might need to add Composer's global bin directory to your system's PATH.
```bash
composer global require modulespress/cli
```
--------------------------------
### GitHub Actions Workflow for Packaging (YAML)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/08-packaging.md
This YAML configuration defines an example GitHub Actions workflow. It's triggered upon the creation of a new release, checks out the code, installs both PHP (Composer) and Node.js (npm) dependencies, builds frontend assets, and finally runs the `modulespress pack` command to create the release artifact.
```YAML
name: Package Plugin
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: |
composer install
npm install
- name: Build Assets
run: npm run build
- name: Package Plugin
run: modulespress pack
```
--------------------------------
### Advanced Plugin Configuration Example PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/05-plugin-configuration.md
Presents a comprehensive example of an `AdvancedPlugin` class extending `ModulesPressPlugin`, demonstrating constant definitions for name, slug, and prefix, setting version and REST namespace properties, configuring the environment in the constructor, and overriding the `onPluginReady` method for advanced initialization logic. It concludes with bootstrapping the plugin instance.
```php
final class AdvancedPlugin extends ModulesPressPlugin {
public const NAME = "Advanced ModulesPress Plugin";
public const SLUG = "advanced-modulespress";
public const PREFIX = "amp_";
protected string $version = "1.2.0";
protected string $restNamespace = "advanced-plugin/v1";
public function __construct() {
$this->configureEnvironmentSettings();
parent::__construct(
rootModule: AdvancedRootModule::class,
rootDir: __DIR__,
rootFile: __FILE__
);
}
// Implement custom lifecycle methods
protected function onPluginReady(ModulesPressPlugin $plugin): void {
// Advanced initialization logic
}
}
(new AdvancedPlugin())->bootstrap()
```
--------------------------------
### Example Generated ModulesPress Service Provider (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
This PHP snippet provides an example of a service provider class generated by the ModulesPress CLI. It includes the `#[Injectable]` attribute, marking it for dependency injection, and a basic constructor.
```php
#[Injectable]
class ProviderName
{
public function __construct() {}
}
```
--------------------------------
### Example Generated ModulesPress Guard (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
This PHP snippet provides an example of a guard class structure. It implements the `CanActivate` interface and includes the required `canActivate` method signature, which returns a boolean indicating whether the request should proceed based on the execution context.
```php
class GuardName implements CanActivate
{
public function canActivate(ExecutionContext $context): bool {}
}
```
--------------------------------
### CPT Repository Design Best Practice Example PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/04-entities-and-repository/02-cpt-repositories.md
Provides an example illustrating the best practice of using specific, descriptive method names (`findPublishedInSeries`) for repository queries instead of generic methods (`findCustom`) that require complex argument arrays.
```php
class BookRepository extends CPTRepository
{
// ✅ Good: Specific, meaningful method names
public function findPublishedInSeries(string $series): array
// ❌ Bad: Generic, unclear methods
public function findCustom(array $args): array
}
```
--------------------------------
### ViewCompose Admin Menu Example PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/05-renderer.md
An example demonstrating how to use the #[ViewCompose] attribute to inject multiple pieces of data (books, categories, last updated time) into the 'network-admin-menu' Blade view before it is rendered.
```php
#[ViewCompose('network-admin-menu')]
public function composeAdminMenu(BladeOne $view)
{
$view->with([
'books' => $this->bookRepository->getAllBooks(),
'categories' => $this->categoryService->getCategories(),
'lastUpdated' => current_time('mysql')
]);
}
```
--------------------------------
### ViewCompose Main Layout Example PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/05-renderer.md
Example showing how to use #[ViewCompose] to inject common data like site name, current user, and notifications into a main layout view ('layouts.main'), ensuring this data is available across all pages using this layout.
```php
#[ViewCompose('layouts.main') safeguard required
public function composeMainLayout(BladeOne $view)
{
$view->with([
'siteName' => get_bloginfo('name'),
'currentUser' => wp_get_current_user(),
'notifications' => $this->notificationService->getAll()
]);
}
```
--------------------------------
### Creating New ModulesPress Plugin (Bash)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
Generates a new ModulesPress plugin boilerplate with the basic structure, necessary configuration files, and default setup. The command takes the desired name for the new plugin as an argument.
```bash
modulespress new plugin-name
```
--------------------------------
### Basic ModulesPress REST Controller in PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/03-rest-api/01-controllers.md
Demonstrates the fundamental structure of a ModulesPress controller using `#[RestController]` for namespace definition. Shows dependency injection via the constructor with `#[Inject]` and defines basic GET and POST endpoints using `#[Get]` and `#[Post]` attributes, including `#[Body]` for request payload.
```php
#[RestController(namespace: "/books")]
class BooksController {
public function __construct(
#[Inject("bookService")]
private readonly BooksServiceProvider $booksService
) {}
#[Get]
public function getBooks(): array {
return $this->booksService->getBooks();
}
#[Post]
public function createBook(
#[Body] CreateBookDTO $book
): array {
return [
"message" => "Book created",
"book" => $book
];
}
}
```
--------------------------------
### Running Vite Development Server Bash
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/06-enquerer.md
Provides the command-line instruction to start the Vite development server. This server is crucial during development for features like Hot Module Replacement (HMR) and resolving assets directly from the source files.
```bash
npm run dev
```
--------------------------------
### Injecting WordPress Options using Providers (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/02-providers.md
Provides a practical example demonstrating how to fetch WordPress options using `get_option` within a static factory method and make them available for injection (as 'Options') into a service (`WordPressSettingsService`) via a Provider configuration.
```php
#[Injectable]
class WordPressSettingsService {
public function __construct(
#[Inject("Options")] private array $pluginOptions
) {}
public function getSettingsPageTheme() {
return $this->pluginOptions["themeColor"];
}
}
#[Module(
providers: [
WordPressSettingsService::class,
new Provider(
provide: "Options",
useFactory: [WordPressIntegrationModule::class, "pluginOptions"]
)
]
)]
class WordPressIntegrationModule extends ModulesPressModule {
public static function pluginOptions() {
$options = array();
$options["themeColor"] = get_option("themeColor");
return $options;
}
}
```
--------------------------------
### Bootstrapping - ModulesPress Plugin - PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/01-introduction.md
This PHP snippet shows the basic structure of the main plugin file for a ModulesPress plugin. It defines a final class that extends `ModulesPressPlugin`, initializes the parent constructor with the root module, directory, and file, and then calls the `bootstrap` method to start the framework. This file serves as the core entry point for the plugin.
```php
bootstrap();
?>
```
--------------------------------
### Running Vite Development Server for ModulesPress Assets Bash
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/06-enquerer.md
Provides a command to start the Vite development server, which is often required for assets (like those bundled by Vite) to load correctly during the development phase in a ModulesPress project.
```bash
# Ensure Vite server is running
npm run dev
```
--------------------------------
### Creating Custom ModulesPress Exception Class in PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Provides an example of creating a custom exception class (`BookNotFoundException`) that extends a base exception (`BaseException` or `NotFoundHttpException`). It defines a constructor to accept message, code, reason, and previous exception parameters for consistency.
```php
class BookNotFoundException extends BaseException // or consider extending NotFoundHttpException instead
{
public function __construct(
string $message = "Book not found",
int $code = 404,
string $reason = "",
?\Throwable $previous = null
) {
parent::__construct($message, $code, $reason, $previous);
}
}
```
--------------------------------
### Customizing ModulesPress Production HTML Error Template in Blade
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Provides a more complete example of the `generic.blade.php` template, demonstrating how to extend a layout (`layouts.error`), include localization (`__('...')`), and add custom content and actions like a 'Return Home' button.
```blade
{{-- views/errors/generic.blade.php --}}
@extends('layouts.error')
@section('content')
{{ __('Oops! Something went wrong') }}
{{ $exception->getMessage() }}
{{-- Add custom content --}}
@endsection
```
--------------------------------
### ModulesPress Basic Production HTML Error Template in Blade
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Shows a basic example of the `generic.blade.php` template used by ModulesPress to render HTML error pages in the production environment (when debug mode is off). It displays the exception code and message.
```blade
{{ $exception->getCode() }}
{{ $exception->getMessage() }}
```
--------------------------------
### Implementing Rate Limiting Middleware PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/03-rest-api/03-middleware.md
This snippet provides an example of a class-based middleware for rate limiting. It gets the client's IP address, checks if the rate limit is exceeded using a dependency (`$this->rateLimiter`), and returns a 429 Too Many Requests response if exceeded, or allows processing to continue otherwise.
```php
class RateLimitMiddleware implements Middleware
{
public function use(WP_REST_Request $req, WP_REST_Response $res): WP_REST_Request|WP_REST_Response
{
$clientIp = $req->get_remote_addr();
if ($this->rateLimiter->isLimitExceeded($clientIp)) {
$res->set_status(429);
$res->set_data([
'error' => 'Rate limit exceeded',
'retry_after' => $this->rateLimiter->getRetryDelay()
]);
return $res; // Immediately return error response
}
return $req; // Continue processing
}
}
```
--------------------------------
### Specifying Exception Reason for Debugging in PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Demonstrates how to include a detailed debugging `reason` when throwing an exception (e.g., `BadRequestHttpException`) by using the named `reason` parameter in the constructor. This reason is intended for debugging and not for end-users.
```php
// Basic usage
throw new BadRequestHttpException(
"Invalid input provided",
reason: "Expected numeric ID, received string 'abc123'"
);
// ❌ Bad
throw new BadRequestHttpException(
"Database error: Unable to connect to MySQL on 192.168.1.100"
);
// ✅ Good
throw new BadRequestHttpException(
"Unable to process request",
reason: "Database connection failed: MySQL connection refused on 192.168.1.100"
);
```
--------------------------------
### Example Generated ModulesPress Taxonomy (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
This PHP snippet illustrates the basic structure of a taxonomy class generated by the ModulesPress CLI. It utilizes the `#[Taxonomy]` attribute to define the taxonomy's slug, singular, and plural names.
```php
#[Taxonomy(
slug: 'taxonomy',
singular: 'Name',
plural: 'Names'
)]
class TaxonomyName
```
--------------------------------
### Accessing Built-in Directory Paths PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/05-plugin-configuration.md
Provides examples of using built-in methods available on the `ModulesPressPlugin` instance to retrieve important plugin directory paths and URLs. These methods include `getRootDirPath()`, `getRootDirUrl()`, `getViewsDirPath()`, and `getCacheDirPath()`.
```php
// Retrieve various plugin directory paths
$rootDir = $plugin->getRootDirPath(); // Plugin root directory
$rootUrl = $plugin->getRootDirUrl(); // Plugin root URL
$viewsDir = $plugin->getViewsDirPath(); // Views directory
$cacheDir = $plugin->getCacheDirPath(); // Cache directory
```
--------------------------------
### Extending Core Exception Filter for Custom Handling (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Shows how to extend the `CoreExceptionFilter` to override specific context handling methods, such as `forRestResponse`. This example demonstrates catching `BadRequestException` and `ValidationException` specifically, providing custom data in the REST response while relying on the parent class for other exceptions and contexts.
```PHP
#[Injectable]
#[CatchException(BadRequestException::class, ValidationException::class)]
class CustomExceptionFilter extends CoreExceptionFilter
{
public function __construct( // Automatically resolves
private readonly Renderer $renderer,
private readonly ModulesPressPlugin $plugin
) {
parent::__construct($this->renderer, $this->plugin->isDebugMode()); // Required
}
protected function forRestResponse(
BaseException $exception,
ExecutionContext $executionContext
): WP_REST_Response {
$response = $executionContext->switchToRESTContext()->getWPResponse();
$response->set_data([
'customField' => 'Custom handling',
'message' => $exception->getMessage(),
'code' => $exception->getCode()
]);
return $response;
}
}
```
--------------------------------
### Example Generated ModulesPress Middleware (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
This PHP snippet shows a generated middleware class structure. It implements the `Middleware` interface and includes the required `use` method signature for interacting with `WP_REST_Request` and `WP_REST_Response` objects during request processing.
```php
class MiddlewareName implements Middleware
{
public function use(WP_REST_Request $req, WP_REST_Response $res): WP_REST_Request|WP_REST_Response {}
}
```
--------------------------------
### Admin Dashboard Asset Enqueuing PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/06-enquerer.md
A comprehensive real-world example demonstrating the enqueuing of assets for an admin dashboard page. It shows how to enqueue an application, specify dependencies, localize complex configuration data, inject the static path resolver, and enqueue additional standalone scripts and styles.
```php
#[UseChecks([new IsAdminMenuCheck(self::ADMIN_MENU_PAGE_SLUG)])]
#[Add_Action('admin_enqueue_scripts')]
public function enqueueAdminAssets(): void
{
// Enqueue main dashboard application
$app = $this->enquerer->app('admin/dashboard/app.tsx')
->dependencies(['wp-components', 'wp-api-fetch'])
->enqueue()
->withStyles();
// Add configuration and utilities
$app->localize('dashboardConfig', [
'restBase' => rest_url('modulespress/v1'),
'nonce' => wp_create_nonce('wp_rest'),
'user' => wp_get_current_user(),
'permissions' => [
'canManageOptions' => current_user_can('manage_options'),
'canEditPosts' => current_user_can('edit_posts')
]
]);
// Add static path resolver
$app->inline($this->enquerer->injectStaticPathResolver());
// Add utility scripts or import directly in app files using `import`
$this->enquerer->script('admin/utils/analytics.ts')
->enqueue();
// Add additional styles or import directly in app files using `import`
$this->enquerer->style('admin/styles/dashboard.scss')
->enqueue();
}
```
--------------------------------
### Enqueuing Style Assets with Options PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/06-enquerer.md
Provides examples for enqueuing `StyleAsset` instances. It covers simple enqueuing of an SCSS file, enqueuing with a specific media query using `media()`, and adding inline CSS directly to the style tag using `inline()`. These methods offer flexibility in how styles are applied.
```php
// Basic SCSS enqueuing
$this->enquerer->style('admin/styles/main.scss')
->enqueue();
// With media queries and conditions
$this->enquerer->style('frontend/responsive.scss')
->enqueue()
->media('screen and (min-width: 768px)');
// With inline styles
$this->enquerer->style('components/modal.scss')
->enqueue()
->inline('.modal { display: none; }');
```
--------------------------------
### Organizing Feature Components in a Module - ModulesPress - PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/01-modules.md
Shows how ModulesPress modules can be used to group related feature components, such as controllers and services. This example defines a `CatsController`, a `CatsService`, and a `CatsModule` that registers these components.
```php
// CatsController.php
class CatsController {
// Cats-specific controller logic
}
```
```php
// CatsService.php
class CatsService {
// Cats-related business logic
}
```
```php
// CatsModule.php
#[Module(
providers: [
CatsService::class
],
controllers: [
CatsController::class
]
)]
class CatsModule extends ModulesPressModule {}
```
--------------------------------
### Frontend Widget Asset Enqueuing PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/06-enquerer.md
A real-world example for enqueuing assets for a frontend widget. It demonstrates conditional enqueuing based on the current page (`is_single()`), enqueuing a frontend application, localizing widget configuration, and enqueuing a style asset with a media query for responsiveness.
```php
#[Add_Action('wp_enqueue_scripts')]
public function enqueueFrontendAssets(): void
{
if (!is_single()) {
return;
}s
// Enqueue widget application
$widget = $this->enquerer->app('frontend/widget/app.tsx')
->dependencies(['wp-element'])
->enqueue()
->withStyles();
// Configure widget
$widget->localize('widgetConfig', [
'postId' => get_the_ID(),
'apiEndpoint' => rest_url('modulespress/v1/widget'),
'theme' => get_option('widget_theme', 'light')
]);
// Add responsive styles
$this->enquerer->style('frontend/styles/widget-responsive.scss')
->enqueue()
->media('screen and (max-width: 768px)');
}
```
--------------------------------
### Configuring Dependency Scopes with ModulesPress Providers (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/02-providers.md
Illustrates how to specify the lifecycle scope for provided dependencies using the `scope` property in the `Provider` configuration. It shows examples for `Scope::SINGLETON` (one instance per request) and `Scope::TRANSIENT` (new instance per injection).
```php
#[Module(
providers: [
// Singleton: Same instance throughout the request lifecycle
new Provider(
provide: UserRepository::class,
useClass: UserRepository::class,
scope: Scope::SINGLETON
),
// Transient: New instance on every injection
new Provider(
provide: LoggerService::class,
useClass: LoggerService::class,
scope: Scope::TRANSIENT
)
]
)]
class CoreModule extends ModulesPressModule {}
```
--------------------------------
### Example Generated ModulesPress CPT Entity (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
This PHP snippet shows the basic structure of a Custom Post Type entity class generated by the ModulesPress CLI. It includes the `#[CustomPostType]` attribute for configuration and extends the base `CPTEntity` class.
```php
#[CustomPostType(
name: 'cpt_name',
singular: 'Name',
plural: 'Names'
)]
class EntityName extends CPTEntity
```
--------------------------------
### Example Generated ModulesPress Pipe (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
This PHP snippet illustrates a generated pipe class structure. It implements the `PipeTransform` interface and provides the required `transform` method signature, which takes an input value and returns a potentially modified value.
```php
class PipeName implements PipeTransform
{
public function transform(mixed $value): mixed {}
}
```
--------------------------------
### Enqueuing Script Asset with Options PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/06-enquerer.md
Demonstrates the fluent API for enqueuing a `ScriptAsset`. This example shows how to specify dependencies (`dependencies()`), enqueue the script (`enqueue()`), localize data to make PHP variables available in JavaScript (`localize()`), add inline scripts (`inline()`), explicitly mark it as a module (`module()`), and retrieve the asset's version (`getVersion()`).
```php
// Enqueue a TypeScript file with dependencies and localization
$this->enquerer->script('admin/dashboard.ts')
->dependencies(['jquery', 'wp-api'])
->enqueue()
->localize('dashboardData', [
'apiUrl' => rest_url(),
'nonce' => wp_create_nonce('wp_rest')
])
->inline("window.DASHBOARD_VERSION = '1.0.0'");
$version = $this->enquerer->script('utils/helper.ts')
->handle('helper')
->enqueue()
->module() //explicetly mark as module, enquerer take care of it by default
->getVersion(); // return version of this asset
```
--------------------------------
### Applying Interceptor to Method ModulesPress PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/03-rest-api/05-interceptors.md
Demonstrates applying the `CacheInterceptor` to the `getFeaturedProducts` method of `ProductsController` using the `#[UseInterceptors]` attribute. This provides fine-grained control over which methods are intercepted. It also shows the `@Get` attribute for routing.
```php
class ProductsController
{
#[UseInterceptors(CacheInterceptor::class)]
#[Get("featured")]
public function getFeaturedProducts(): array
{
return $this->productService->getFeatured();
}
}
```
--------------------------------
### Registering Global Exception Filter (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Demonstrates how to register an exception filter that applies globally to the entire plugin. This is achieved by returning an array of filter class names from the `pluginFilters` method within a class that extends `ModulesPressModule`.
```PHP
class YourModule extends ModulesPressModule
{
public function pluginFilters(): array
{
return [
GlobalExceptionFilter::class
];
}
}
```
--------------------------------
### Configuring Providers in ModulesPress Module (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/02-providers.md
Shows how to define various types of providers within a `#[Module]` attribute's `providers` array, including class-based, named service (`useClass`), static value (`useValue`), and factory-based (`useFactory`) providers. Includes an example factory method.
```php
#[Module(
providers: [
// Class-based provider
UserRepository::class,
// Named service provider
new Provider(
provide: "notificationService",
useClass: EmailNotificationService::class
),
// Static value provider
new Provider(
provide: "emailApiKey",
useValue: "your-api-key-here"
),
// Factory-based provider
new Provider(
provide: "configManager",
useFactory: [ConfigurationModule::class, "createConfigManager"]
)
]
)]
class UserModule extends ModulesPressModule {
// Factory method example
public static function createConfigManager() {
return new ConfigManager(
environment: wp_get_environment_type(),
basePath: WP_CONTENT_DIR
);
}
}
```
--------------------------------
### Example Generated ModulesPress Interceptor (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
This PHP snippet shows a generated interceptor class structure. It implements the `Interceptor` interface and includes the required `intercept` method signature for executing logic before or after a method call within the execution context.
```php
class InterceptorName implements Interceptor
{
public function intercept(ExecutionContext $context, CallHandler $next): mixed {}
}
```
--------------------------------
### Defining Plugin Version in Header (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/08-packaging.md
This example shows the standard WordPress plugin header structure in the main plugin file. The `Version` field is critical because the ModulesPress `pack` command reads this value to name the generated production package ZIP file.
```PHP
/**
* Plugin Name: Books Generator
* Description: Generate books for your WordPress site.
* Version: 1.0.0
* Author: Your Name
* License: GPL2
* Text Domain: books-generator
*/
```
--------------------------------
### Full ModulesPress Service Provider for WordPress Hooks - PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/03-wordpress-hooks.md
Presents a complete example of a Service Provider class utilizing ModulesPress attributes (`#[Add_Action]`, `#[Add_Filter]`) to manage various WordPress hooks. It demonstrates organizing different hook registrations within a single class for initialization, admin menus, and content modification, showcasing a structured approach.
```php
namespace BookPlugin\Provider;
use ModulesPress\Foundation\Hookable\Attributes\Add_Action;
use ModulesPress\Foundation\Hookable\Attributes\Add_Filter;
class BookServiceProvider
{
#[Add_Action('init', priority: 5)]
public function initializeBookSystem() {
// Initialize book-related systems
}
#[Add_Action('admin_menu')]
public function registerAdminPages() {
// Register admin menu items
}
#[Add_Filter('the_content', priority: 10)]
public function enhanceBookContent($content) {
// Modify content display
return $content;
}
}
```
--------------------------------
### Utilizing Built-in CPT Repository CRUD Operations PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/04-entities-and-repository/02-cpt-repositories.md
Provides examples of using the standard CRUD methods available on a CPT Repository instance, including finding by ID, finding all, finding by criteria, saving (create/update), and removing an entity.
```php
class BookController
{
public function __construct(
private BookRepository $repository
) {}
public function examples()
{
// Find by ID
$book = $this->repository->find(123);
// Find all
$allBooks = $this->repository->findAll();
// Find by criteria
$books = $this->repository->findBy([
'post_status' => 'publish',
'orderby' => 'title'
]);
// Save (create or update)
$book = new Book();
$book->title = 'New Book';
$this->repository->save($book);
// Remove
$this->repository->remove($book);
}
}
```
--------------------------------
### Optimizing Composer Autoloader (Bash)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/08-packaging.md
This Composer command is used within the packaging process to ensure only production dependencies are installed (`--no-dev`) and the Composer autoloader is optimized (`--optimize-autoloader`). This results in a smaller package size and faster autoloading.
```Bash
composer install --no-dev --optimize-autoloader
```
--------------------------------
### Implementing a Custom JWT Authentication Guard in ModulesPress (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/03-rest-api/04-guards.md
Provides an example of a guard (`JwtGuard`) for verifying JSON Web Tokens. It demonstrates accessing the 'Authorization' header from the request context and using a hypothetical JWT library to decode and validate the token, returning `true` only if the token is valid.
```PHP
#[Injectable]
class JwtGuard implements CanActivate
{
public function canActivate(ExecutionContext $ctx): bool
{
$request = $ctx->switchToRESTContext()->getWPRequest();
$token = $request->get_header('Authorization');
if (!$token) {
return false;
}
try {
// Verify JWT token (using your preferred JWT library)
$decoded = JWT::decode($token, new Key(YOUR_SECRET_KEY, 'HS256'));
return true;
} catch (Exception $e) {
return false;
}
}
}
```
--------------------------------
### Implementing Blog Switch Interceptor WordPress PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/03-rest-api/05-interceptors.md
Designed for WordPress multisite installations, this interceptor reads the 'Blog-Id' header to switch the global blog context using `switch_to_blog` before handler execution and `restore_current_blog` afterward. It ensures database operations target the correct blog and throws a `BadRequestHttpException` if the header is missing.
```php
class BlogInfoInterceptor implements Interceptor
{
public function intercept(ExecutionContext $context, CallHandler $next): mixed
{
$restContext = $context->switchToRESTContext();
$blogId = $restContext->getWPRequest()->get_header("Blog-Id");
if (!$blogId){
throw new BadRequestHttpException("Blog-Id header is missing.");
}
switch_to_blog($blogId);
$result = $next->handle();
restore_current_blog();
return $result;
}
}
```
--------------------------------
### Implementing a Basic Rate Limiting Guard in ModulesPress (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/03-rest-api/04-guards.md
Provides a simple example of a `RateLimitGuard` using WordPress transients to track requests per IP address. The guard checks if the request count exceeds a threshold within a time window and returns `false` if the limit is reached.
```PHP
#[Injectable]
class RateLimitGuard implements CanActivate
{
public function canActivate(ExecutionContext $ctx): bool
{
$ip = $_SERVER['REMOTE_ADDR'];
$key = "rate_limit_" . $ip;
$attempts = get_transient($key) ?: 0;
if ($attempts >= 100) { // 100 requests per hour
return false;
}
set_transient($key, $attempts + 1, HOUR_IN_SECONDS);
return true;
}
}
```
--------------------------------
### Configuring Debugging Information Display for Exceptions in PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Shows a protected property `$displayAdditionalDebuggingFor` within a class (like a filter) that lists specific exception types for which detailed debugging information (file, line, trace) should be included in the response when debug mode is enabled.
```php
protected array $displayAdditionalDebuggingFor = [
InternalServerErrorHttpException::class,
ModuleResolutionException::class
];
```
--------------------------------
### Defining ModulesPress Exception Filter Hierarchy in PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Demonstrates how to configure a hierarchical exception filter chain in ModulesPress using a Module's `pluginFilters` method for global filters, `#[UseExceptionFilter]` attribute on a class for class-level filters, and `#[UseExceptionFilter]` on a method for method-level filters.
```php
class BookModule extends Module {
// Level 3: Plugin Global Filter
public function pluginFilters(): array {
return [
GlobalExceptionFilter::class
];
}
}
// Level 2: Class-Level Filter
#[UseExceptionFilter(RestExceptionFilter::class)]
class BookController {
// Level 1: Method-Level Filter
#[UseExceptionFilter(SpecificExceptionFilter::class)]
public function createBook() {
// If an exception occurs here:
// 1. Method-level filter tries first
// 2. If unhandled, class-level filter tries next
// 3. If still unhandled, global filter handles it
// 4. Finally, CoreExceptionFilter handles any remaining unhandled exceptions and terminate.
}
}
```
--------------------------------
### Example Generated ModulesPress Exception Filter (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
This PHP snippet shows a generated exception filter class structure. It implements the `ExceptionFilter` interface, includes the `#[CatchException]` attribute to specify the exception type to handle, and provides the `catchException` method for custom error responses.
```php
#[CatchException(ExceptionType::class)]
class FilterName implements ExceptionFilter
{
public function catchException(
BaseException $exception,
ExecutionContext $executionContext
): WP_REST_Response | HtmlResponse | JsonResponse {}
}
```
--------------------------------
### Accessing Execution Context Details in ModulesPress Guard (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/03-rest-api/04-guards.md
Illustrates how guards can utilize the `ExecutionContext` to gain insights into the request context. It shows how to switch to the REST context (`switchToRESTContext`) and access reflections of the class and method, retrieve custom attributes, and get the underlying WordPress request object.
```PHP
public function canActivate(ExecutionContext $ctx): bool
{
$restContext = $ctx->switchToRESTContext();
// Access method reflection
$method = $restContext->getMethodReflection();
// Access class reflection
$class = $restContext->getClassReflection();
// Get custom attributes
$attributes = $method->getAttributes(MyAttribute::class);
// Access WP request object
$request = $restContext->getWPRequest();
return true;
}
```
--------------------------------
### Attaching Validation Errors to ModulesPress Exception in PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Provides an example of how to create a `ValidationException`, set multiple validation errors using the `setErrors` method, and then throw the exception. These errors will appear in the 'errors' field of the JSON API response.
```php
$e = new ValidationException();
$e->setErrors([
"email" => "Invalid email format",
"password" => "Must be at least 8 characters"
]);
throw $e;
```
--------------------------------
### Creating Production Package (ModulesPress CLI, Bash)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/08-packaging.md
This core ModulesPress CLI command initiates the entire packaging process. It orchestrates tasks including removing development-specific files, optimizing Composer dependencies for production, and finally creating a versioned ZIP archive ready for distribution.
```Bash
# Create a production package
modulespress pack
```
--------------------------------
### Packaging ModulesPress Plugin (Bash)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
Packages the current ModulesPress plugin for distribution. This process typically includes optimizing dependencies and creating a distribution-ready archive, such as a zip file, for deployment.
```bash
modulespress pack
```
--------------------------------
### Building Frontend Assets (Bash)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/08-packaging.md
This Bash command executes the `build` script defined in your project's `package.json`. This is typically used to run a frontend build tool like Vite, compiling and optimizing JavaScript, CSS, and other assets for production use.
```Bash
# Build Vite assets
npm run build
```
--------------------------------
### Implementing Plugin Ready Lifecycle Method PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/05-plugin-configuration.md
Details the `onPluginReady` protected method available in a ModulesPress plugin class. This method is called after the core framework is initialized and all dependencies are resolved, serving as the recommended place for initialization logic that relies on other services or components being available.
```php
protected function onPluginReady(ModulesPressPlugin $plugin): void {
// This method is called when:
// 1. Core framework is initialized
// 2. All dependencies are resolved
// 3. Before the plugin is fully bootstrapped
if ($plugin->isDebugMode()) {
// Debug-specific initialization
$this->setupDebugTools();
}
}
```
--------------------------------
### Custom Directive WordPress Nonce PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/05-renderer.md
Example of a custom Blade directive '@wpNonce' that simplifies adding a WordPress nonce field to a form or page, using the `wp_nonce_field()` function.
```php
#[ViewDirective("wpNonce", "onRuntime") safeguard required
public function nonceDirective(string $action)
{
echo wp_nonce_field($action, '_wpnonce', true, false);
}
```
--------------------------------
### Custom Directive Asset Image PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/05-renderer.md
Example of a custom Blade directive '@image' that takes an image path parameter and outputs the full URL to the asset using a hypothetical `enquerer` service.
```php
#[ViewDirective("image", "onRuntime") safeguard required
public function imageDirective(string $imgPath)
{
echo $this->enquerer->static('imgs/' . $imgPath)->getUrl();
}
```
--------------------------------
### Importing Modules Including Dynamic Instances - ModulesPress - PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/01-modules.md
Illustrates how a module declares its dependencies by importing other modules. This includes importing standard modules by class name and importing instances of dynamic modules, allowing configuration at the point of import.
```php
#[Module(
imports: [
new BooksDynamicModule(apiVersion: "v1"),
AuthModule::class,
CoreModule::class
]
)]
class AdminModule extends ModulesPressModule {}
```
--------------------------------
### Custom Directive Current Time PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/05-renderer.md
Example of a simple custom Blade directive '@currentTime' that outputs the current date and time using PHP's `date()` function when used in a Blade template.
```php
#[ViewDirective("currentTime", "onRuntime")]
public function currentTimeDirective()
{
echo date("Y-m-d H:i:s");
}
```
--------------------------------
### Generating ModulesPress Service Provider (Bash)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/03-cli.md
Creates a new PHP class intended to function as a service provider, commonly used for registering services and dependencies. The command requires the desired provider name and supports the optional `--dir, -d` flag.
```bash
modulespress make:provider ProviderName
```
--------------------------------
### Overriding Debugging Configuration in Custom Exception Filter in PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Demonstrates how to extend the `CoreExceptionFilter` and override the `$displayAdditionalDebuggingFor` property in a custom filter class (`CustomExceptionFilter`) to include additional exception types for which debugging details should be shown.
```php
class CustomExceptionFilter extends CoreExceptionFilter
{
protected array $displayAdditionalDebuggingFor = [
InternalServerErrorHttpException::class,
ModuleResolutionException::class,
DatabaseException::class,
CriticalBusinessException::class
];
}
```
--------------------------------
### Running Production Build Bash
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/06-enquerer.md
Provides the command-line instruction to build the plugin's assets for production. This command processes and optimizes assets, generating the necessary files and the manifest file used by the Enquerer to resolve production URLs.
```bash
npm run build
```
--------------------------------
### Enqueuing App Asset with Styles and Localization PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/06-enquerer.md
Shows how to enqueue an `AppAsset`, specifically designed for framework applications like React. It includes specifying dependencies, automatically enqueuing associated styles (`withStyles()`), localizing application configuration data, and injecting inline scripts like the static path resolver.
```php
// React application with HMR and styles
$app = $this->enquerer->app('admin/dashboard/app.tsx')
->dependencies(['wp-element'])
->enqueue()
->withStyles() // enqueue all styles for the app
->localize('appConfig', [
'environment' => WP_DEBUG ? 'development' : 'production',
'features' => ['analytics', 'reports']
]);
// Add static path resolver and custom configuration
$app->inline($this->enquerer->injectStaticPathResolver('staticPath'))
->inline("window.APP_CONFIG = " . json_encode([
'apiEndpoint' => rest_url($this->plugin->getRestNamespace()),
'maxUploadSize' => wp_max_upload_size()
]));
```
--------------------------------
### Injecting Enquerer Service PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/06-enquerer.md
Demonstrates how to obtain an instance of the ModulesPress Enquerer service within a class by using constructor-based dependency injection, which is the recommended way to use services in ModulesPress.
```php
use ModulesPress\Core\Enquerer\Enquerer;
class AdminMenuService {
public function __construct(
private readonly Enquerer $enquerer
) {}
}
```
--------------------------------
### Handling Activation and Deactivation Lifecycle PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/01-getting-started/05-plugin-configuration.md
Shows how to implement custom logic for plugin activation (`onActivate`) and deactivation (`onDeactivate`) by overriding the corresponding methods in a `ModulesPressPlugin` subclass. It demonstrates firing custom action hooks (`self::SLUG . '/activate'`, `self::SLUG . '/deactivate'`) within these methods for extensibility.
```php
class MyPlugin extends ModulesPressPlugin {
public function onActivate(bool $networkWide): void {
// Custom activation logic
if ($networkWide) {
// Network-wide activation handling
}
// Fires a custom action hook
do_action(self::SLUG . '/activate', $networkWide);
}
public function onDeactivate(): void {
// Custom deactivation logic
do_action(self::SLUG . '/deactivate');
}l
}
```
--------------------------------
### ModulesPress Basic REST API Error Response in JSON
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Illustrates the default, minimal JSON response structure used by the `CoreExceptionFilter` for REST API errors in ModulesPress. It includes the error message and the corresponding HTTP status code.
```json
{
"message": "id is required",
"statusCode": 400
}
```
--------------------------------
### Enqueuing Styles for ModulesPress Apps PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/06-enquerer.md
Illustrates the correct method to ensure styles are loaded for application assets in ModulesPress by chaining the `withStyles()` method after enqueuing the app, addressing potential style loading issues.
```php
// Always use withStyles() for apps with CSS
$app->enqueue()->withStyles();
```
--------------------------------
### Registering Controller-Level Filter (PHP Attribute)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/07-exception-handling.md
Shows how to apply an exception filter specifically to an entire controller using the `#[UseExceptionFilter]` attribute placed above the controller class definition. This filter will process exceptions occurring in any method within that controller.
```PHP
#[UseExceptionFilter(RestExceptionFilter::class)]
#[RestController("/books")]
class BooksController {}
```
--------------------------------
### Registering WordPress Hooks with Global Functions - PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/03-wordpress-hooks.md
Illustrates the traditional WordPress method using global functions and `add_action` for hook registration. This approach pollutes the global namespace, lacks object-oriented context, and complicates dependency management compared to modern techniques.
```php
function my_books_init() {
// Initialization logic
}
add_action('init', 'my_books_init');
```
--------------------------------
### Rendering Blade View as String PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/05-renderer.md
Illustrates rendering a Blade view using the `renderAsString` method to get the rendered HTML as a string instead of outputting it directly. This is useful for cases where the output needs to be processed or stored before being displayed.
```php
$viewHtml = $renderer->renderAsString('view-name', [
'user' => $currentUser,
'settings' => $pluginSettings
]); // return string
echo $viewHtml;
```
--------------------------------
### Applying ModulesPress Middleware using Regex and Exact Paths PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/03-rest-api/03-middleware.md
This snippet demonstrates applying a middleware (`ApiKeyMiddleware`) to routes matching either a regular expression (`#^api/.*$#`) or an exact path (`books/special`). The `forRoutes` method accepts multiple path arguments for more flexible matching.
```php
$consumer->apply(ApiKeyMiddleware::class)
->forRoutes(
// Match all routes starting with 'api/'
'#^api/.*$#',
// Exact route matching
'books/special'
);
```
--------------------------------
### Implementing CanActivate Guard for REST Nonce PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/07-advanced/01-execution-context.md
Defines a class MainGuard implementing the CanActivate interface, demonstrating guard functionality. The canActivate method switches to the REST context and checks for a 'nonce' parameter within the JSON request body. If the nonce is missing, it throws an UnauthorizedHttpException; otherwise, it allows access by returning true.
```php
class MainGuard implements CanActivate
{
public function canActivate(ExecutionContext $executionContext): bool
{ return true;
if (!isset($executionContext->switchToRESTContext()->getWPRequest()->get_json_params()["nonce"])) {
throw new UnauthorizedHttpException("You are not authorized to access this resource due to missing nonce.");
} else {
return true;
}
}
}
```
--------------------------------
### Defining a Standard Module Structure - ModulesPress - PHP
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/01-modules.md
Demonstrates how to define a basic module in ModulesPress using the `#[Module]` attribute. This shows how to declare a module's dependencies (imports), registered services (providers), entry points (controllers), data structures (entities), and components made available to other modules (exports).
```php
#[Module(
imports: [
AuthModule::class,
CategoriesModule::class
],
providers: [
BookService::class,
BookRepository::class
],
controllers: [
BooksController::class
],
entities: [
Book::class
],
exports: [
BookRepository::class
]
)]
class BooksModule extends ModulesPressModule {}
```
--------------------------------
### Implementing Class-Based Dependency Injection (PHP)
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/02-the-basics/02-providers.md
Demonstrates how a class (`UserService`) can have its constructor dependencies automatically resolved by the ModulesPress dependency injection container when providers for `EmailService` and `UserRepository` are available.
```php
class EmailService {
public function sendEmail($to, $subject, $body) {
// Email sending logic
}
}
#[Injectable]
class UserService {
public function __construct(
private EmailService $emailService,
private UserRepository $userRepository
) {}
public function registerUser(User $user) {
// Register user logic
$this->emailService->sendEmail(
$user->email,
'Welcome',
'Thank you for registering'
);
}
}
```
--------------------------------
### Defining User Roles using PHP Enum for ModulesPress Guards
Source: https://github.com/devsroutes/modulespress-docs/blob/master/docs/03-rest-api/04-guards.md
Provides an example of defining user roles using a PHP enum, a common practice for creating type-safe and readable role definitions that can be used in conjunction with guards for role-based access control.
```PHP
// Define roles using an enum
enum UserRole: string
{
case SUPER_ADMIN = "cm_super_admin";
case CHAPTER_ADMIN = "cm_chapter_admin";
case CHAPTER_MEMBER = "cm_chapter_member";
}
```