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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased](https://github.com/Pollora/framework/compare/v13.38.1...develop)

### Changed
- The domain layer no longer calls WordPress or imports the Infrastructure layer (harness rules ARCH-01 and ARCH-02). Theme menus, sidebars and image sizes are registered through `ThemeFeatureRegistrarInterface`, the theme URI filters resolve through `ContentUrlResolverInterface` and `ThemeAssetUrlResolverInterface`, the dashboard reads WordPress through `WordPressEnvironmentInterface`, `AbstractTaxonomy` translates its default labels through `LabelTranslatorInterface`, and `WooCommerceService` asks `WooCommerceEnvironmentInterface` about the child theme. Each port is bound to a WordPress adapter by its module's service provider; behaviour and public signatures are unchanged

## [v13.38.1](https://github.com/Pollora/framework/compare/v13.38.0...v13.38.1) - 2026-10-21

### Fixed
Expand Down
48 changes: 48 additions & 0 deletions src/Dashboard/Domain/Contracts/WordPressEnvironmentInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Pollora\Dashboard\Domain\Contracts;

/**
* What the dashboard reports about the WordPress it runs in.
*
* Each method answers null (or its empty value) when WordPress is not loaded
* or cannot tell, so the collector decides alone how to show a missing value.
*/
interface WordPressEnvironmentInterface
{
/**
* The site locale, or null when WordPress cannot resolve it yet.
*/
public function locale(): ?string;

/**
* The WordPress version, or null when WordPress is not loaded.
*/
public function version(): ?string;

public function isMultisite(): bool;

/**
* The permalink structure, or an empty string for plain permalinks.
*/
public function permalinkStructure(): string;

/**
* The plural label of a registered post type, or null when it has none.
*/
public function postTypeLabel(string $slug): ?string;

/**
* The plural label of a registered taxonomy, or null when it has none.
*/
public function taxonomyLabel(string $slug): ?string;

/**
* The active theme, or null when WordPress is not loaded.
*
* @return array{name: string, version: string, template: string}|null
*/
public function activeTheme(): ?array;
}
52 changes: 13 additions & 39 deletions src/Dashboard/Domain/Services/SystemInfoCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use Nwidart\Modules\Contracts\RepositoryInterface;
use Pollora\Attributes\PostType;
use Pollora\Attributes\Taxonomy;
use Pollora\Dashboard\Domain\Contracts\WordPressEnvironmentInterface;
use Pollora\Dashboard\Domain\Support\UnavailableWordPressEnvironment;
use Pollora\Discovery\Application\Services\DiscoveryManager;
use Pollora\Modules\Application\Services\ModuleStates;
use Pollora\Modules\Application\Services\ModuleVersions;
Expand All @@ -29,6 +31,7 @@ public function __construct(
private DiscoveryManager $discoveryManager,
private ContainerInterface $container,
private string $laravelVersion = '',
private WordPressEnvironmentInterface $wordpress = new UnavailableWordPressEnvironment,
) {}

/**
Expand Down Expand Up @@ -65,9 +68,7 @@ public function collect(): array
*/
public function collectTranslationInfo(): array
{
$wordpressLocale = function_exists('get_locale') && function_exists('wp_cache_get')
? (string) get_locale()
: 'Unknown';
$wordpressLocale = $this->wordpress->locale() ?? 'Unknown';

return [
'override_active' => $this->isTranslationOverrideActive(),
Expand Down Expand Up @@ -156,9 +157,7 @@ public function collectFrameworkInfo(): array
*/
public function collectEnvironmentInfo(): array
{
$wpVersion = function_exists('get_bloginfo')
? (string) get_bloginfo('version')
: 'Unknown';
$wpVersion = $this->wordpress->version() ?? 'Unknown';

return [
'php' => PHP_VERSION,
Expand All @@ -173,10 +172,8 @@ public function collectEnvironmentInfo(): array
public function collectWordPressConfig(): array
{
$debug = defined('WP_DEBUG') && WP_DEBUG;
$multisite = function_exists('is_multisite') && is_multisite();
$permalink = function_exists('get_option')
? (string) get_option('permalink_structure', '')
: '';
$multisite = $this->wordpress->isMultisite();
$permalink = $this->wordpress->permalinkStructure();

return [
'debug' => $debug,
Expand Down Expand Up @@ -290,28 +287,14 @@ private function attributeOf(string $class, string $attributeClass): ?object

private function getPostTypeLabel(string $slug, string $class, ?string $plural = null): string
{
if (function_exists('get_post_type_object')) {
$object = get_post_type_object($slug);

if ($object !== null && isset($object->labels->name)) {
return $object->labels->name;
}
}

return $plural ?? StringHelper::headline(class_basename($class));
return $this->wordpress->postTypeLabel($slug)
?? $plural ?? StringHelper::headline(class_basename($class));
}

private function getTaxonomyLabel(string $slug, string $class, ?string $plural = null): string
{
if (function_exists('get_taxonomy')) {
$object = get_taxonomy($slug);

if ($object !== false && isset($object->labels->name)) {
return $object->labels->name;
}
}

return $plural ?? StringHelper::headline(class_basename($class));
return $this->wordpress->taxonomyLabel($slug)
?? $plural ?? StringHelper::headline(class_basename($class));
}

/**
Expand Down Expand Up @@ -506,16 +489,7 @@ private function moduleConnectorLabel(): ?string
*/
public function collectThemeInfo(): array
{
if (! function_exists('wp_get_theme')) {
return ['name' => 'Unknown', 'version' => 'Unknown', 'template' => 'Unknown'];
}

$theme = wp_get_theme();

return [
'name' => (string) $theme->get('Name'),
'version' => (string) $theme->get('Version'),
'template' => (string) $theme->get_template(),
];
return $this->wordpress->activeTheme()
?? ['name' => 'Unknown', 'version' => 'Unknown', 'template' => 'Unknown'];
}
}
48 changes: 48 additions & 0 deletions src/Dashboard/Domain/Support/UnavailableWordPressEnvironment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Pollora\Dashboard\Domain\Support;

use Pollora\Dashboard\Domain\Contracts\WordPressEnvironmentInterface;

/**
* The environment of a collector that runs without WordPress: nothing is known.
*/
final readonly class UnavailableWordPressEnvironment implements WordPressEnvironmentInterface
{
public function locale(): ?string
{
return null;
}

public function version(): ?string
{
return null;
}

public function isMultisite(): bool
{
return false;
}

public function permalinkStructure(): string
{
return '';
}

public function postTypeLabel(string $slug): ?string
{
return null;
}

public function taxonomyLabel(string $slug): ?string
{
return null;
}

public function activeTheme(): ?array
{
return null;
}
}
63 changes: 63 additions & 0 deletions src/Dashboard/Infrastructure/Adapters/WordPressEnvironment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace Pollora\Dashboard\Infrastructure\Adapters;

use Pollora\Dashboard\Domain\Contracts\WordPressEnvironmentInterface;

/**
* Reads the dashboard's WordPress facts from WordPress itself.
*
* Every call is guarded by function_exists(): the dashboard and
* `pollora:status` also run before WordPress is loaded, or without it.
*/
final readonly class WordPressEnvironment implements WordPressEnvironmentInterface
{
public function locale(): ?string
{
// get_locale() reads the object cache, which is not there before
// WordPress has loaded far enough to answer.
return function_exists('get_locale') && function_exists('wp_cache_get') ? (string) get_locale() : null;
}

public function version(): ?string
{
return function_exists('get_bloginfo') ? (string) get_bloginfo('version') : null;
}

public function isMultisite(): bool
{
return function_exists('is_multisite') && is_multisite();
}

public function permalinkStructure(): string
{
return function_exists('get_option') ? (string) get_option('permalink_structure', '') : '';
}

public function postTypeLabel(string $slug): ?string
{
$object = function_exists('get_post_type_object') ? get_post_type_object($slug) : null;

return $object !== null && isset($object->labels->name) ? $object->labels->name : null;
}

public function taxonomyLabel(string $slug): ?string
{
$object = function_exists('get_taxonomy') ? get_taxonomy($slug) : false;

return $object !== false && isset($object->labels->name) ? $object->labels->name : null;
}

public function activeTheme(): ?array
{
$theme = function_exists('wp_get_theme') ? wp_get_theme() : null;

return $theme === null ? null : [
'name' => (string) $theme->get('Name'),
'version' => (string) $theme->get('Version'),
'template' => (string) $theme->get_template(),
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;
use Pollora\Dashboard\Domain\Contracts\WordPressEnvironmentInterface;
use Pollora\Dashboard\Domain\Services\SystemInfoCollector;
use Pollora\Dashboard\Infrastructure\Adapters\WordPressEnvironment;
use Pollora\Dashboard\UI\Console\StatusCommand;
use Pollora\Dashboard\UI\Http\DashboardController;
use Pollora\Discovery\Application\Services\DiscoveryManager;
Expand All @@ -24,11 +26,14 @@ class DashboardServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(WordPressEnvironmentInterface::class, WordPressEnvironment::class);

$this->app->singleton(SystemInfoCollector::class, fn ($app): SystemInfoCollector => new SystemInfoCollector(
$app->make(VersionComparator::class),
$app->make(DiscoveryManager::class),
$app,
Application::VERSION,
$app->make(WordPressEnvironmentInterface::class),
));

if ($this->app->runningInConsole()) {
Expand Down
19 changes: 19 additions & 0 deletions src/Taxonomy/Domain/Contracts/LabelTranslatorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Pollora\Taxonomy\Domain\Contracts;

/**
* Translates the label templates a taxonomy builds its labels from.
*/
interface LabelTranslatorInterface
{
/**
* Translate a text in a text domain.
*
* @param string $text The text to translate, e.g. 'All %s'
* @param string $domain The text domain, e.g. 'pollora'
*/
public function translate(string $text, string $domain): string;
}
Loading
Loading