diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index e8c7496..5c4cc2f 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -1,7 +1,6 @@ name: PHP Quality Assurance on: - pull_request: push: paths: - '**workflows/qa.yml' @@ -10,6 +9,14 @@ on: - '**phpunit.xml.dist' - '**psalm.xml' - '**composer.json' + pull_request: + paths: + - '**workflows/qa.yml' + - '**.php' + - '**phpcs.xml.dist' + - '**phpunit.xml.dist' + - '**psalm.xml' + - '**composer.json' workflow_dispatch: inputs: jobs: @@ -21,27 +28,47 @@ on: - 'Run all' - 'Run PHPCS only' - 'Run Psalm only' - - 'Run static analysis (PHPCS + Psalm)' - - 'Run unit tests only' + - 'Run lint only' + - 'Run static analysis (Lint + PHPCS + Psalm)' + - 'Run unit tests' concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: - coding-standards-analysis-php: - if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs != 'Run unit tests only') && (github.event.inputs.jobs != 'Run Psalm only')) }} + lint: + if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run lint only') || (github.event.inputs.jobs == 'Run static analysis')) }} + uses: inpsyde/reusable-workflows/.github/workflows/lint-php.yml@main + strategy: + matrix: + php: [ '7.4', '8.0', '8.1', '8.2', '8.3' ] + with: + PHP_VERSION: ${{ matrix.php }} + LINT_ARGS: '-e php --colors --show-deprecated ./src' + + coding-standards-analysis: + if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run PHPCS only') || (github.event.inputs.jobs == 'Run static analysis')) }} uses: inpsyde/reusable-workflows/.github/workflows/coding-standards-php.yml@main + with: + PHP_VERSION: '8.3' - static-code-analysis-php: - if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs != 'Run unit tests only') && (github.event.inputs.jobs != 'Run PHPCS only')) }} + static-code-analysis: + if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run Psalm only') || (github.event.inputs.jobs == 'Run static analysis')) }} uses: inpsyde/reusable-workflows/.github/workflows/static-analysis-php.yml@main + strategy: + matrix: + php: [ '7.4', '8.0', '8.1', '8.2', '8.3' ] + with: + PHP_VERSION: ${{ matrix.php }} + PSALM_ARGS: --output-format=github --no-suggestions --no-cache --no-diff --find-unused-psalm-suppress - tests-unit-php: - if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run unit tests only')) }} + unit-tests: + if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run unit tests')) }} uses: inpsyde/reusable-workflows/.github/workflows/tests-unit-php.yml@main strategy: matrix: - php: ["7.2", "7.3", "7.4", "8.0", "8.1", "8.2"] + php: [ '7.4', '8.0', '8.1', '8.2', '8.3' ] with: PHP_VERSION: ${{ matrix.php }} + PHPUNIT_ARGS: '--no-coverage' diff --git a/composer.json b/composer.json index 86047a2..47cff52 100644 --- a/composer.json +++ b/composer.json @@ -16,18 +16,27 @@ "role": "Developer" } ], + "repositories": [ + { + "type": "composer", + "url": "https://raw.githubusercontent.com/inpsyde/wp-stubs/main", + "only": [ + "inpsyde/wp-stubs-versions" + ] + } + ], "require": { - "php": ">=7.2.5 < 9", + "php": ">=7.4 < 8.4", "ext-json": "*", - "inpsyde/wp-context": "^1.2.0", - "pimple/pimple": "^3" + "inpsyde/wp-context": "^1.5.0", + "pimple/pimple": "^v3.5.0" }, "require-dev": { - "phpunit/phpunit": "^8.5.22", - "inpsyde/php-coding-standards": "^1", - "vimeo/psalm": "^4.26.0", + "phpunit/phpunit": "^9.6.19", + "inpsyde/php-coding-standards": "^2@dev", + "vimeo/psalm": "^5.24.0", "brain/monkey": "^2.6.1", - "inpsyde/wp-stubs": "dev-main" + "inpsyde/wp-stubs-versions": "dev-latest" }, "autoload": { "psr-4": { @@ -42,13 +51,13 @@ "minimum-stability": "stable", "scripts": { "cs": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs", - "psalm": "@php ./vendor/vimeo/psalm/psalm --no-cache --output-format=compact", - "tests": "@php ./vendor/phpunit/phpunit/phpunit", - "tests:no-cov": "@php ./vendor/phpunit/phpunit/phpunit --no-coverage", + "psalm": "@php ./vendor/vimeo/psalm/psalm --no-suggestions --report-show-info=false --find-unused-psalm-suppress --no-diff --no-cache --no-file-cache --output-format=compact", + "tests": "@php ./vendor/phpunit/phpunit/phpunit --no-coverage", + "tests:coverage": "@php ./vendor/phpunit/phpunit/phpunit", "qa": [ "@cs", "@psalm", - "@tests:no-cov" + "@tests" ] }, "extra": { diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 98f7911..3ad58a8 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -6,7 +6,7 @@ - + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index bd06bb3..ad1f2c4 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,19 +1,20 @@ - - + xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"> + + + ./src - - + + + ./tests + diff --git a/psalm.xml b/psalm.xml index 667656c..0b9ccd5 100644 --- a/psalm.xml +++ b/psalm.xml @@ -7,6 +7,8 @@ ignoreInternalFunctionFalseReturn="false" ignoreInternalFunctionNullReturn="false" hideExternalErrors="true" + findUnusedBaselineEntry="true" + findUnusedCode="false" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" @@ -17,12 +19,15 @@ + - + + + diff --git a/src/App.php b/src/App.php index 1f1cdcd..3c91156 100644 --- a/src/App.php +++ b/src/App.php @@ -4,6 +4,7 @@ namespace Inpsyde\App; +use Inpsyde\App\Container\ContainerCollector; use Inpsyde\App\Provider\Package; use Inpsyde\App\Provider\ServiceProvider; use Inpsyde\WpContext; @@ -12,52 +13,23 @@ final class App { public const ACTION_ADD_PROVIDERS = 'wp-app.add-providers'; - public const ACTION_REGISTERED = 'wp-app.all-providers-registered'; - public const ACTION_BOOTED = 'wp-app.all-providers-booted'; - public const ACTION_REGISTERED_PROVIDER = 'wp-app.provider-registered'; public const ACTION_ADDED_PROVIDER = 'wp-app.provider-added'; + public const ACTION_BOOTED = 'wp-app.all-providers-booted'; public const ACTION_BOOTED_PROVIDER = 'wp-app.provider-booted'; public const ACTION_ERROR = 'wp-app.error'; + public const ACTION_REGISTERED = 'wp-app.all-providers-registered'; + public const ACTION_REGISTERED_PROVIDER = 'wp-app.provider-registered'; - /** - * @var App|null - */ - private static $app; - - /** - * @var Container|null - */ - private $container; - - /** - * @var AppLogger - */ - private $logger; - - /** - * @var AppStatus - */ - private $status; - - /** - * @var \SplQueue|null - */ - private $bootable; - - /** - * @var \SplQueue|null - */ - private $delayed; - - /** - * @var bool - */ - private $booting = false; + private static ?App $app = null; - /** - * @var array - */ - private $providers = []; + private Container $container; + private AppLogger $logger; + private AppStatus $status; + private \SplQueue $bootable; + private \SplQueue $delayed; + private bool $booting = false; + /** @var array */ + private array $providers = []; /** * @param Container|null $container @@ -75,13 +47,10 @@ public static function new(Container $container = null): App * @param string $id * @return mixed * - * phpcs:disable Inpsyde.CodeQuality.ReturnTypeDeclaration - * @psalm-suppress MissingReturnType + * @deprecated */ public static function make(string $id) { - // phpcs:enable Inpsyde.CodeQuality.ReturnTypeDeclaration - if (!self::$app) { static::handleThrowable(new \Exception('No valid app found.')); @@ -107,11 +76,13 @@ public static function handleThrowable(\Throwable $throwable): void /** * @param Container|null $container */ - private function __construct(Container $container = null) + private function __construct(?Container $container = null) { $this->status = AppStatus::new(); $this->logger = AppLogger::new(); - $this->container = $container; + $this->container = $container ?? new Container(); + $this->delayed = new \SplQueue(); + $this->bootable = new \SplQueue(); } /** @@ -154,24 +125,12 @@ public function runLastBootAt(string $hook): App */ public function debugInfo(): ?array { - $providers = $this->logger->dump(); - if ($providers === null) { - return null; - } - - $data = [ - 'status' => (string)$this->status, - 'providers' => $providers, - 'context' => null, - 'config' => null, + return [ + 'status' => (string) $this->status, + 'providers' => $this->logger->dump(), + 'context' => $this->container->context()->jsonSerialize(), + 'config' => $this->container->config()->jsonSerialize(), ]; - - if ($this->container) { - $data['context'] = $this->container->context()->jsonSerialize(); - $data['config'] = $this->container->config()->jsonSerialize(); - } - - return $data; } /** @@ -189,7 +148,7 @@ public function boot(): void { try { if ($this->booting) { - throw new \DomainException('Can\'t call App::boot() when already booting.'); + throw new \DomainException("Can't call App::boot() when already booting."); } $this->status = $this->status->next($this); // registering @@ -241,15 +200,12 @@ public function addProvider(ServiceProvider $provider, string ...$contexts): App try { $contexts or $contexts = [WpContext::CORE]; - $this->initializeContainer(); - $providerId = $provider->id(); if ($this->hasProviders($providerId)) { return $this; } - /** @psalm-suppress PossiblyNullReference */ if (!$this->container->context()->is(...$contexts)) { $this->logger->providerSkipped($provider, $this->status); @@ -260,12 +216,10 @@ public function addProvider(ServiceProvider $provider, string ...$contexts): App $this->logger->providerAdded($provider, $this->status); $this->fireBootingHook(self::ACTION_ADDED_PROVIDER, $providerId); - /** @psalm-suppress PossiblyNullReference */ $provider->registerLater() ? $this->delayed->enqueue($provider) : $this->registerProvider($provider); - /** @psalm-suppress PossiblyNullReference */ $this->bootable->enqueue($provider); } catch (\Throwable $throwable) { static::handleThrowable($throwable); @@ -287,18 +241,11 @@ public function addPackage(Package $package): App /** * @param string $id - * @param mixed|null $default + * @param mixed $default * @return mixed - * - * phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration - * phpcs:disable Inpsyde.CodeQuality.ReturnTypeDeclaration - * @psalm-suppress MissingReturnType - * @psalm-suppress MissingParamType */ public function resolve(string $id, $default = null) { - // phpcs:enable Inpsyde.CodeQuality.ReturnTypeDeclaration - $value = $default; try { @@ -306,9 +253,6 @@ public function resolve(string $id, $default = null) throw new \DomainException('Can\'t resolve from an uninitialised application.'); } - $this->initializeContainer(); - - /** @psalm-suppress PossiblyNullReference */ if (!$this->container->has($id)) { do_action( self::ACTION_ERROR, @@ -326,22 +270,11 @@ public function resolve(string $id, $default = null) return $value; } - /** - * @return void - */ - private function initializeContainer(): void - { - $this->container or $this->container = new Container(); - $this->delayed or $this->delayed = new \SplQueue(); - $this->bootable or $this->bootable = new \SplQueue(); - } - /** * @return void */ private function registerAndBootProviders(): void { - $this->initializeContainer(); $lastRun = $this->status->isThemesStep(); try { @@ -374,22 +307,19 @@ private function registerAndBootProviders(): void */ private function registerDeferredProviders(): void { - if (!$this->delayed) { + if ($this->delayed->count() === 0) { return; } $lastRun = $this->status->isThemesStep(); - $toRegisterLater = $lastRun ? null : new \SplQueue(); + $toRegisterLater = new \SplQueue(); while ($this->delayed->count()) { /** @var ServiceProvider $delayed */ $delayed = $this->delayed->dequeue(); - $toRegisterNow = $lastRun || $delayed->bootEarly(); - $toRegisterNow and $this->registerProvider($delayed); - - if ($toRegisterLater && !$toRegisterNow) { - $toRegisterLater->enqueue($delayed); - } + ($lastRun || $delayed->bootEarly()) + ? $this->registerProvider($delayed) + : $toRegisterLater->enqueue($delayed); } $this->delayed = $toRegisterLater; @@ -400,13 +330,13 @@ private function registerDeferredProviders(): void */ private function bootProviders(): void { - if (!$this->bootable) { + if ($this->bootable->count() === 0) { return; } $lastRun = $this->status->isThemesStep(); - $toBootLater = $lastRun ? null : new \SplQueue(); + $toBootLater = new \SplQueue(); while ($this->bootable->count()) { /** @var ServiceProvider $bootable */ @@ -417,9 +347,7 @@ private function bootProviders(): void continue; } - if ($toBootLater) { - $toBootLater->enqueue($bootable); - } + $toBootLater->enqueue($bootable); } $this->bootable = $toBootLater; @@ -432,8 +360,6 @@ private function bootProviders(): void private function registerProvider(ServiceProvider $provider): void { try { - $this->initializeContainer(); - /** @psalm-suppress PossiblyNullArgument */ if ($provider->register($this->container)) { $this->fireBootingHook(self::ACTION_REGISTERED_PROVIDER, $provider->id()); $this->logger->providerRegistered($provider, $this->status); @@ -449,8 +375,6 @@ private function registerProvider(ServiceProvider $provider): void */ private function bootProvider(ServiceProvider $provider): void { - $this->initializeContainer(); - /** @psalm-suppress PossiblyNullArgument */ if (!$provider->boot($this->container)) { return; } diff --git a/src/AppLogger.php b/src/AppLogger.php index c54a887..9c19505 100644 --- a/src/AppLogger.php +++ b/src/AppLogger.php @@ -8,15 +8,10 @@ final class AppLogger { - /** - * @var bool - */ - private $debugEnabled; + private bool $debugEnabled; - /** - * @var array - */ - private $providers = []; + /** @var array */ + private array $providers = []; /** * @return AppLogger @@ -26,6 +21,8 @@ public static function new(): AppLogger return new static(); } + /** + */ private function __construct() { /** @psalm-suppress TypeDoesNotContainType */ diff --git a/src/AppStatus.php b/src/AppStatus.php index 5980bde..82c4b0a 100644 --- a/src/AppStatus.php +++ b/src/AppStatus.php @@ -31,15 +31,8 @@ final class AppStatus self::BOOTING_THEMES => self::BOOTED_THEMES, ]; - /** - * @var string - */ - private $status; - - /** - * @var string - */ - private $lastStepHook = 'init'; + private string $status; + private string $lastStepHook = 'init'; /** * @return AppStatus @@ -49,12 +42,15 @@ public static function new(): AppStatus return new static(); } + /** + */ private function __construct() { $this->status = self::IDLE; } /** + * @param string $hook * @return AppStatus */ public function lastStepOn(string $hook): AppStatus @@ -81,7 +77,9 @@ public function next(App $app): AppStatus $status = self::NEXT_STEP_MAP[$this->status] ?? null; if ($status === null) { + // phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped throw new \DomainException("Can't move out of status '{$this->status}'."); + // phpcs:enable WordPress.Security.EscapeOutput.ExceptionNotEscaped } $this->status = $status; @@ -210,7 +208,7 @@ private function initialize(App $app): AppStatus $filter = current_filter(); $filter and $message .= " WordPress is at {$filter} hook."; - throw new \DomainException($message); + throw new \DomainException(esc_html($message)); } if (!did_action('plugins_loaded')) { diff --git a/src/Container.php b/src/Container.php index 43c50f2..550d0e5 100644 --- a/src/Container.php +++ b/src/Container.php @@ -9,31 +9,13 @@ use Pimple\Exception\UnknownIdentifierException; use Psr\Container\ContainerInterface; -/** - * phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration - * phpcs:disable Inpsyde.CodeQuality.ReturnTypeDeclaration - */ final class Container implements ContainerInterface { - /** - * @var SiteConfig - */ - private $config; - - /** - * @var WpContext - */ - private $context; - - /** - * @var Pimple\Container|null - */ - private $pimple; - - /** - * @var ContainerInterface[] - */ - private $containers = []; + /** @var list */ + private array $containers; + private SiteConfig $config; + private WpContext $context; + private ?Pimple\Container $pimple = null; /** * @param SiteConfig|null $config @@ -48,8 +30,8 @@ public function __construct( $this->config = $config ?? new EnvConfig(); $this->context = $context ?? WpContext::determine(); - $this->containers = $containers; - if (!$containers) { + $this->containers = array_values($containers); + if ($containers === []) { $this->ensurePimple(); } } @@ -102,7 +84,6 @@ public function addService(string $id, callable $factory): void { try { $this->ensurePimple(); - /** @psalm-suppress PossiblyNullReference */ $this->pimple[$id] = $this->wrapCallback($factory); } catch (\Throwable $throwable) { do_action(App::ACTION_ERROR, $throwable); @@ -120,13 +101,11 @@ public function extendService(string $id, callable $extender): void { try { $this->ensurePimple(); - /** @psalm-suppress PossiblyNullReference */ $this->pimple->extend( $id, /** - * @psalm-suppress MissingClosureParamType - * @psalm-suppress MissingClosureReturnType - * @psalm-suppress MixedFunctionCall + * @param mixed $service + * @return mixed */ function ($service) use (&$extender) { return $extender($service, $this); @@ -147,7 +126,6 @@ public function addFactory(string $id, callable $callable): void { try { $this->ensurePimple(); - /** @psalm-suppress PossiblyNullReference */ $this->pimple[$id] = $this->pimple->factory($this->wrapCallback($callable)); } catch (\Throwable $throwable) { do_action(App::ACTION_ERROR, $throwable); @@ -157,17 +135,11 @@ public function addFactory(string $id, callable $callable): void } /** - * @param mixed $id + * @param string $id * @return mixed - * - * @psalm-suppress MissingReturnType - * @psalm-suppress MissingParamType - * @psalm-suppress RedundantConditionGivenDocblockType */ - public function get($id) + public function get(string $id) { - $this->assertString($id, __METHOD__); - try { foreach ($this->containers as $container) { if ($container->has($id)) { @@ -184,16 +156,11 @@ public function get($id) } /** - * @param mixed $id + * @param string $id * @return bool - * - * @psalm-suppress MissingParamType - * @psalm-suppress RedundantConditionGivenDocblockType */ - public function has($id): bool + public function has(string $id): bool { - $this->assertString($id, __METHOD__); - try { foreach ($this->containers as $container) { if ($container->has($id)) { @@ -211,6 +178,8 @@ public function has($id): bool /** * @return void + * + * @psalm-assert Pimple\Container $this->pimple */ private function ensurePimple(): void { @@ -221,29 +190,6 @@ private function ensurePimple(): void } } - /** - * Simulating type declaration, which is not possible due to PSR-11 interface. - * - * @param mixed $value Should be string - * @param string $method - * @return void - * - * @psalm-suppress MissingParamType - * @psalm-assert string $value - */ - private function assertString($value, string $method): void - { - if (!is_string($value)) { - throw new \TypeError( - sprintf( - 'Argument 1 passed to %s() must be a string, %s given.', - $method, - gettype($value) - ) - ); - } - } - /** * @param callable $factory * @return \Closure @@ -251,8 +197,8 @@ private function assertString($value, string $method): void private function wrapCallback(callable $factory): \Closure { /** + * @return mixed * @psalm-suppress MissingClosureReturnType - * @psalm-suppress MixedFunctionCall */ return function () use (&$factory) { return $factory($this); diff --git a/src/EnvConfig.php b/src/EnvConfig.php index 1bd30d8..7b43cb3 100644 --- a/src/EnvConfig.php +++ b/src/EnvConfig.php @@ -18,54 +18,20 @@ class EnvConfig implements SiteConfig public const PRODUCTION = 'production'; public const STAGING = 'staging'; - private const ENV_ALIASES = [ - 'local' => self::LOCAL, - 'development' => self::DEVELOPMENT, - 'dev' => self::DEVELOPMENT, - 'develop' => self::DEVELOPMENT, - 'staging' => self::STAGING, - 'stage' => self::STAGING, - 'preprod' => self::STAGING, - 'pre-prod' => self::STAGING, - 'pre-production' => self::STAGING, - 'test' => self::STAGING, - 'uat' => self::STAGING, - 'production' => self::PRODUCTION, - 'prod' => self::PRODUCTION, - 'live' => self::PRODUCTION, - ]; - + /** @psalm-suppress DeprecatedConstant */ private const HOSTING_LOCATIONS_CLASS_MAP = [ self::HOSTING_WPE => WpEngineLocations::class, self::HOSTING_VIP => VipLocations::class, - self::HOSTING_SPACES => GenericLocations::class, self::HOSTING_OTHER => GenericLocations::class, + self::HOSTING_SPACES => GenericLocations::class, ]; - /** - * @var string - */ - private $env = ''; - - /** - * @var array - */ - private $data = []; - - /** - * @var string[] - */ - private $namespaces = []; - - /** - * @var Locations|null - */ - private $locations; - - /** - * @var string - */ - private $hosting = ''; + /** @var array */ + private array $data = []; + /** list */ + private array $namespaces = []; + private ?Locations $locations = null; + private string $hosting = ''; /** * @param string ...$namespaces @@ -73,8 +39,8 @@ class EnvConfig implements SiteConfig public function __construct(string ...$namespaces) { foreach ($namespaces as $namespace) { - $trimmed = $namespace ? trim($namespace, '\\') : null; - $trimmed and $this->namespaces[] = $trimmed; + $trimmed = trim($namespace, '\\'); + ($trimmed !== '') and $this->namespaces[] = $trimmed; } } @@ -89,19 +55,16 @@ public function locations(): Locations $locationClassName = self::HOSTING_LOCATIONS_CLASS_MAP[$this->hosting()] ?? ''; if ( - !$locationClassName + ($locationClassName === '') || !class_exists($locationClassName) || !is_subclass_of($locationClassName, Locations::class) ) { $locationClassName = GenericLocations::class; } - /** @var callable $factory */ + /** @var callable(EnvConfig):Locations $factory */ $factory = [$locationClassName, 'createFromConfig']; - /** @var Locations $locations */ - $locations = $factory($this); - - $this->locations = $locations; + $this->locations = $factory($this); return $this->locations; } @@ -122,7 +85,7 @@ public function hosting(): string return $this->hosting; } - if ($this->get('VIP_GO_ENV') !== null) { + if (($this->get('VIP_GO_ENV') !== null) || $this->canReadVipEnv()) { $this->hosting = self::HOSTING_VIP; return $this->hosting; @@ -135,11 +98,19 @@ public function hosting(): string } if ($this->get('SPACES_SPACE_ID')) { + /** @psalm-suppress DeprecatedConstant */ $this->hosting = self::HOSTING_SPACES; return $this->hosting; } + $hosting = apply_filters('wp-app.hosting', null); + if (($hosting !== '') && is_string($hosting)) { + $this->hosting = $hosting; + + return $this->hosting; + } + $this->hosting = self::HOSTING_OTHER; return $this->hosting; @@ -156,41 +127,10 @@ public function hostingIs(string $hosting): bool /** * @return string - * - * phpcs:disable Generic.Metrics.CyclomaticComplexity */ public function env(): string { - // phpcs:enable Generic.Metrics.CyclomaticComplexity - if ($this->env) { - return $this->env; - } - - // Use WP function if we can (WP 5.5+). - $env = function_exists('wp_get_environment_type') ? wp_get_environment_type() : null; - $env = $env - ?? $this->readEnvVarOrConstant('WP_ENVIRONMENT_TYPE') // WP core - ?? $this->readEnvVarOrConstant('WP_ENV') // WP Starter or Bedrock - ?? $this->readEnvVarOrConstant('WORDPRESS_ENV') // WP Starter legacy - ?? $this->readEnvVarOrConstant('VIP_GO_APP_ENVIRONMENT') // VIP Go - ?? $this->readEnvVarOrConstant('VIP_GO_ENV'); // VIP Go legacy - - if ($env) { - return $this->normalizeEnv((string)$env, false); - } - - if (function_exists('is_wpe')) { // WP Engine legacy - $env = ((int)is_wpe()) > 0 ? self::PRODUCTION : self::STAGING; - $this->env = $this->normalizeEnv($env, true); - - return $this->env; - } - - /** @psalm-suppress TypeDoesNotContainType */ - $env = (defined('WP_DEBUG') && WP_DEBUG) ? self::DEVELOPMENT : self::PRODUCTION; - $this->env = $this->normalizeEnv($env, true); - - return $this->env; + return wp_get_environment_type(); } /** @@ -199,30 +139,17 @@ public function env(): string */ public function envIs(string $env): bool { - $env = strtolower($env); - if (array_key_exists($env, self::ENV_ALIASES)) { - $env = self::ENV_ALIASES[$env]; - } - - return $this->env() === $env; + return $this->env() === strtolower($env); } /** * @param string $name - * @param null $default - * @return mixed|null - * - * phpcs:disable Inpsyde.CodeQuality.ReturnTypeDeclaration - * phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration - * @psalm-suppress MissingReturnType - * @psalm-suppress MissingParamType + * @param mixed $default + * @return mixed */ public function get(string $name, $default = null) { - // phpcs:enable Inpsyde.CodeQuality.ReturnTypeDeclaration - // phpcs:enable Inpsyde.CodeQuality.ArgumentTypeDeclaration - - if (!$name) { + if ($name === '') { return $default; } @@ -255,7 +182,6 @@ public function get(string $name, $default = null) /** * @return array{env:string, hosting:string, keys:array} */ - #[\ReturnTypeWillChange] public function jsonSerialize(): array { return [ @@ -268,59 +194,41 @@ public function jsonSerialize(): array /** * @param string $name * @return mixed - * - * phpcs:disable Inpsyde.CodeQuality.ReturnTypeDeclaration - * @psalm-suppress MissingReturnType */ private function readEnvVarOrConstant(string $name) { - // phpcs:enable - if (defined($name)) { return constant($name); } + /** @psalm-suppress UndefinedClass */ + if ($this->canReadVipEnv() && \Automattic\VIP\Environment::has_var($name)) { + return \Automattic\VIP\Environment::get_var($name); + } + + // phpcs:disable WordPress.Security.ValidatedSanitizedInput $value = $_ENV[$name] ?? null; - if ($value === null && stripos($name, 'HTTP_') !== 0) { - $value = $_SERVER[$name] ?? null; // phpcs:ignore + if (($value === null) && stripos($name, 'HTTP_') !== 0) { + $value = $_SERVER[$name] ?? null; } + // phpcs:enable WordPress.Security.ValidatedSanitizedInput - if ($value === null && (PHP_SAPI === 'cli' || PHP_SAPI === 'cli-server')) { - $value = getenv($name) ?: null; + if (($value === null) && ((PHP_SAPI === 'cli') || (PHP_SAPI === 'cli-server'))) { + $value = getenv($name); + ($value === false) and $value = null; } return $value; } /** - * Ensures the environment is one of the four supported, to ensure it matches what - * `wp_get_environment_type()` will return. - * When we were not able to determine environment unequivocally we use `apply_filters` to that - * There's one more chance for developers to define the env. - * Even in that case the environment will be normalized to one of the supported environments, - * in the worst case with a fallback to production, just like WP 5.5+ does. - * - * @param string $env - * @param bool $applyFilters - * @return string + * @return bool */ - private function normalizeEnv(string $env, bool $applyFilters): string + private function canReadVipEnv(): bool { - $lower = strtolower($env); - - // When we are going to apply_filters we don't want to fallback to production already, - // we'll do later, if needed. - $default = $applyFilters ? $lower : self::PRODUCTION; - $env = self::ENV_ALIASES[$lower] ?? $default; - if (!$applyFilters) { - return $env; - } - - $filtered = apply_filters(self::FILTER_ENV_NAME, $env); - if ($filtered && is_string($filtered)) { - $env = strtolower($filtered); - } - - return self::ENV_ALIASES[$env] ?? self::PRODUCTION; + static $hasVipEnv; + isset($hasVipEnv) or $hasVipEnv = class_exists(\Automattic\VIP\Environment::class); + /** @var bool */ + return $hasVipEnv; } } diff --git a/src/Location/LocationResolver.php b/src/Location/LocationResolver.php index 697a9ba..9698db2 100644 --- a/src/Location/LocationResolver.php +++ b/src/Location/LocationResolver.php @@ -6,6 +6,10 @@ use Inpsyde\App\EnvConfig; +/** + * @psalm-type Location-Type = array + * @psalm-type Location-Types = array{"url": Location-Type, "dir": Location-Type} + */ class LocationResolver { public const URL = 'url'; @@ -18,15 +22,9 @@ class LocationResolver Locations::THEMES => 'themes/', ]; - /** - * @var array - */ - private $locations; - - /** - * @var EnvConfig - */ - private $config; + /** @var Location-Types */ + private array $locations; + private EnvConfig $config; /** * @param EnvConfig $config @@ -39,20 +37,19 @@ public function __construct(EnvConfig $config, array $extendedDefaults = []) // phpcs:enable Generic.Metrics.CyclomaticComplexity $this->config = $config; - $vendorPath = $this->discoverVendorPath(); - $contentPath = trailingslashit(wp_normalize_path((string)WP_CONTENT_DIR)); + $vendorPath = $this->discoverVendorPath() ?? ''; + $contentPath = trailingslashit(wp_normalize_path((string) WP_CONTENT_DIR)); $contentUrl = content_url('/'); - if ($vendorPath && strpos($vendorPath, $contentPath) === 0) { + if (($vendorPath !== '') && (strpos($vendorPath, $contentPath) === 0)) { // If vendor path is inside content path, then we can calculate vendor URL - $subFolder = substr($vendorPath, strlen($contentPath)); - $vendorUrl = $contentUrl . (string)$subFolder; + $vendorUrl = $contentUrl . (string) substr($vendorPath, strlen($contentPath)); } $locations = [ self::DIR => [ - Locations::ROOT => trailingslashit((string)ABSPATH), - Locations::VENDOR => $vendorPath ?: null, + Locations::ROOT => trailingslashit((string) ABSPATH), + Locations::VENDOR => ($vendorPath === '') ? null : $vendorPath, Locations::CONTENT => $contentPath, ], self::URL => [ @@ -62,22 +59,22 @@ public function __construct(EnvConfig $config, array $extendedDefaults = []) ], ]; - $custom = $extendedDefaults ? $this->parseExtendedDefaults($extendedDefaults) : []; - if ($custom[self::DIR] ?? null) { + $custom = $this->parseExtendedDefaults($extendedDefaults); + if ($custom[self::DIR] !== []) { $locations[self::DIR] = array_merge($locations[self::DIR], $custom[self::DIR]); } - if ($custom[self::URL] ?? null) { + if ($custom[self::URL] !== []) { $locations[self::URL] = array_merge($locations[self::URL], $custom[self::URL]); } $byConfig = $this->locationsByConfig($config); - if ($byConfig[self::DIR] ?? null) { + if ($byConfig[self::DIR] !== []) { $locations[self::DIR] = array_merge($locations[self::DIR], $byConfig[self::DIR]); } - if ($byConfig[self::URL] ?? null) { + if ($byConfig[self::URL] !== []) { $locations[self::URL] = array_merge($locations[self::URL], $byConfig[self::URL]); } - + /** @var Location-Types $locations */ $this->locations = $locations; } @@ -106,29 +103,32 @@ public function resolveDir(string $location, ?string $subDir = null): ?string */ private function discoverVendorPath(): ?string { - $baseDir = (string)wp_normalize_path(dirname(__DIR__, 2)); + $baseDir = (string) wp_normalize_path(dirname(__DIR__, 2)); $dependency = 'psr/container/composer.json'; $dirParts = explode('/', $baseDir); $countParts = count($dirParts); - $vendorName = $countParts > 3 ? array_slice($dirParts, -3, 1)[0] : ''; - $vendorPath = trim($vendorName, '/') + $vendorName = ($countParts > 3) ? array_slice($dirParts, -3, 1)[0] : ''; + $vendorPath = trim((string) $vendorName, '/') !== '' ? implode('/', array_slice($dirParts, 0, $countParts - 3)) . "/{$vendorName}" : null; // if vendor dir is found, but our dependency in it, then what's found is wrong or Composer // dependencies not installed. In both cases we want to disable vendor path. - if ($vendorPath && !is_file("{$vendorPath}/{$dependency}")) { + if ( + ($vendorPath !== null) + && !is_file("{$vendorPath}/{$dependency}") + ) { $vendorPath = null; } // if no vendor dir found, but our dependency inside base dir, package is installed as root, // e.g. during unit tests, so we can calculate vendor - if (!$vendorPath && is_file("{$baseDir}/vendor/{$dependency}")) { + if (($vendorPath === null) && is_file("{$baseDir}/vendor/{$dependency}")) { $vendorPath = "{$baseDir}/vendor/"; } - return $vendorPath ?: null; + return $vendorPath; } /** @@ -139,52 +139,56 @@ private function discoverVendorPath(): ?string */ private function resolve(string $location, string $dirOrUrl, ?string $subDir = null): ?string { - $envBase = (string)$this->config->get('WP_APP_' . strtoupper("{$location}_{$dirOrUrl}")); + $envBase = (string) $this->config->get('WP_APP_' . strtoupper("{$location}_{$dirOrUrl}")); $base = $envBase ? ($dirOrUrl === self::DIR ? wp_normalize_path($envBase) : $envBase) : ($this->locations[$dirOrUrl][$location] ?? null); - if ($base === null && array_key_exists($location, self::CONTENT_LOCATIONS)) { + if (($base === null) && array_key_exists($location, self::CONTENT_LOCATIONS)) { $contentBase = $this->resolve(Locations::CONTENT, $dirOrUrl); - $contentBase and $base = $contentBase . self::CONTENT_LOCATIONS[$location]; + if (($contentBase !== '') && ($contentBase !== null)) { + $base = $contentBase . self::CONTENT_LOCATIONS[$location]; + } } if ($base === null) { return null; } - $base = trailingslashit((string)$base); + $base = trailingslashit((string) $base); - if (!$subDir) { + if (($subDir === '') || ($subDir === null)) { return $base; } ($dirOrUrl === self::DIR) and $subDir = wp_normalize_path($subDir); - return $base . ltrim((string)$subDir, '\\/'); + return $base . ltrim((string) $subDir, '\\/'); } /** * @param EnvConfig $config - * @return array> + * @return Location-Types */ private function locationsByConfig(EnvConfig $config): array { $locations = $config->get('LOCATIONS'); - if (!$locations || !is_array($locations)) { - return []; - } - return $this->parseExtendedDefaults($locations); + return $this->parseExtendedDefaults(is_array($locations) ? $locations : []); } /** - * @return array> + * @param array $locations + * @return Location-Types */ private function parseExtendedDefaults(array $locations): array { + /** @var Location-Types $custom */ $custom = [self::DIR => [], self::URL => []]; + if ($locations === []) { + return $custom; + } $customDirs = $locations[self::DIR] ?? []; is_array($customDirs) or $customDirs = []; @@ -193,20 +197,18 @@ private function parseExtendedDefaults(array $locations): array is_array($customUrls) or $customUrls = []; foreach ($customDirs as $key => $customDir) { - if ($key && $customDir && is_string($key) && is_string($customDir)) { + if (($key !== '') && ($customDir !== '') && is_string($key) && is_string($customDir)) { $custom[self::DIR][$key] = trailingslashit(wp_normalize_path($customDir)); } } foreach ($customUrls as $key => $customUrl) { - if ($key && $customUrl && is_string($key) && is_string($customUrl)) { + if (($key !== '') && ($customUrl !== '') && is_string($key) && is_string($customUrl)) { $custom[self::URL][$key] = trailingslashit($customUrl); } } - /** @var array> $custom */ - $custom = array_filter($custom); - + /** @var Location-Types */ return $custom; } } diff --git a/src/Location/Locations.php b/src/Location/Locations.php index 16e53be..3b57fe8 100644 --- a/src/Location/Locations.php +++ b/src/Location/Locations.php @@ -96,13 +96,13 @@ public function contentUrl(string $path = '/'): ?string; /** * @param string $path - * @return string|null|null + * @return string|null */ public function vendorDir(string $path = '/'): ?string; /** * @param string $path - * @return string|null|null It is expected to be null if vendor folder is outside web-root. + * @return string|null It is expected to be null if vendor folder is outside web-root. */ public function vendorUrl(string $path = '/'): ?string; diff --git a/src/Location/ResolverTrait.php b/src/Location/ResolverTrait.php index 3f07e8d..4f4238d 100644 --- a/src/Location/ResolverTrait.php +++ b/src/Location/ResolverTrait.php @@ -6,10 +6,7 @@ trait ResolverTrait { - /** - * @var LocationResolver|null - */ - private $resolver; + private ?LocationResolver $resolver; /** * @param LocationResolver $resolver @@ -149,6 +146,7 @@ public function vendorDir(string $path = '/'): ?string } /** + * @param string $path * @return string|null */ public function vendorUrl(string $path = '/'): ?string diff --git a/src/Location/VipLocations.php b/src/Location/VipLocations.php index 1dae366..70132df 100644 --- a/src/Location/VipLocations.php +++ b/src/Location/VipLocations.php @@ -30,8 +30,8 @@ public static function createFromConfig(EnvConfig $config): Locations private function __construct(EnvConfig $config) { $baseResolver = new LocationResolver($config); - $contentUrl = $baseResolver->resolveUrl(self::CONTENT); - $contentDir = $baseResolver->resolveDir(self::CONTENT); + $contentUrl = $baseResolver->resolveUrl(self::CONTENT) ?? ''; + $contentDir = $baseResolver->resolveDir(self::CONTENT) ?? ''; /** @psalm-suppress MixedArgument */ $privateDir = defined('WPCOM_VIP_PRIVATE_DIR') @@ -39,28 +39,28 @@ private function __construct(EnvConfig $config) : null; $clientMuDir = defined('WPCOM_VIP_CLIENT_MU_PLUGIN_DIR') - ? trailingslashit(wp_normalize_path((string)WPCOM_VIP_CLIENT_MU_PLUGIN_DIR)) + ? trailingslashit(wp_normalize_path((string) WPCOM_VIP_CLIENT_MU_PLUGIN_DIR)) : "{$contentDir}client-mu-plugins/"; - $clientMuUrl = "{$contentUrl}client-mu-plugins/"; + $clientMuUrl = $contentUrl . 'client-mu-plugins/'; - $abspath = trailingslashit(wp_normalize_path((string)ABSPATH)); + $abspath = trailingslashit(wp_normalize_path((string) ABSPATH)); $this->injectResolver( new LocationResolver( $config, [ LocationResolver::DIR => [ - self::IMAGES => "{$contentDir}images/", + self::IMAGES => $contentDir . 'images/', self::CLIENT_MU_PLUGINS => $clientMuDir, - self::VENDOR => "{$clientMuDir}vendor/", + self::VENDOR => $clientMuDir . 'vendor/', self::PRIVATE => $privateDir, - self::VIP_CONFIG => "{$abspath}vip-config/", + self::VIP_CONFIG => $abspath . 'vip-config/', ], LocationResolver::URL => [ - self::IMAGES => "{$contentUrl}images", + self::IMAGES => $contentUrl . 'images', self::CLIENT_MU_PLUGINS => $clientMuUrl, - self::VENDOR => "{$clientMuUrl}vendor/", + self::VENDOR => $clientMuUrl . 'vendor/', ], ] ) diff --git a/src/Location/WpEngineLocations.php b/src/Location/WpEngineLocations.php index 99e09a3..1507f7b 100644 --- a/src/Location/WpEngineLocations.php +++ b/src/Location/WpEngineLocations.php @@ -26,14 +26,14 @@ public static function createFromConfig(EnvConfig $config): Locations */ private function __construct(EnvConfig $config) { - $muDir = wp_normalize_path(trailingslashit((string)WP_CONTENT_DIR) . 'mu-plugins'); + $muDir = wp_normalize_path(trailingslashit((string) WP_CONTENT_DIR) . 'mu-plugins'); $this->injectResolver( new LocationResolver( $config, [ LocationResolver::DIR => [ - self::PRIVATE => wp_normalize_path((string)ABSPATH) . '_wpeprivate/', + self::PRIVATE => wp_normalize_path((string) ABSPATH) . '_wpeprivate/', self::VENDOR => "{$muDir}/vendor/", ], LocationResolver::URL => [ diff --git a/src/Provider/AutoDiscoverIdTrait.php b/src/Provider/AutoDiscoverIdTrait.php index 599325e..c5f7172 100644 --- a/src/Provider/AutoDiscoverIdTrait.php +++ b/src/Provider/AutoDiscoverIdTrait.php @@ -6,10 +6,7 @@ trait AutoDiscoverIdTrait { - /** - * @var string|null - */ - private $discoveredId = null; + private ?string $discoveredId = null; /** * @return string @@ -20,8 +17,9 @@ public function id(): string return $this->discoveredId; } - if (isset($this->id) && is_string($this->id)) { + if (is_string($this->id ?? null)) { $this->discoveredId = $this->id; + /** @var string */ return $this->discoveredId; } diff --git a/src/Provider/ConfigurableProvider.php b/src/Provider/ConfigurableProvider.php index 3dcdc31..6eb82a6 100644 --- a/src/Provider/ConfigurableProvider.php +++ b/src/Provider/ConfigurableProvider.php @@ -12,26 +12,13 @@ class ConfigurableProvider implements ServiceProvider public const REGISTER_LATER = 16; public const BOOT_EARLY = 32; - /** - * @var string - */ - private $id; - - /** - * @var callable|null - */ + private string $id; + private int $flags; + /** @var callable|null */ private $register; - - /** - * @var callable|null - */ + /** @var callable|null */ private $boot; - /** - * @var int - */ - private $flags; - /** * @param string $id * @param callable|null $register @@ -82,7 +69,7 @@ public function bootEarly(): bool public function register(Container $container): bool { try { - return $this->register ? (bool)(($this->register)($container)) : false; + return ($this->register !== null) && ($this->register)($container); } catch (\Throwable $throwable) { App::handleThrowable($throwable); } @@ -97,7 +84,7 @@ public function register(Container $container): bool public function boot(Container $container): bool { try { - return $this->boot ? (bool)(($this->boot)($container)) : false; + return ($this->boot !== null) && ($this->boot)($container); } catch (\Throwable $throwable) { App::handleThrowable($throwable); } diff --git a/src/Provider/ServiceProviders.php b/src/Provider/ServiceProviders.php index 25d1cc8..8110a97 100644 --- a/src/Provider/ServiceProviders.php +++ b/src/Provider/ServiceProviders.php @@ -11,7 +11,7 @@ class ServiceProviders /** * @var \SplObjectStorage>|null */ - private $providers; + private ?\SplObjectStorage $providers = null; /** * @return ServiceProviders @@ -28,7 +28,7 @@ public static function new(): ServiceProviders */ public function add(ServiceProvider $provider, string ...$contexts): ServiceProviders { - if (!$this->providers) { + if ($this->providers === null) { $this->providers = new \SplObjectStorage(); } @@ -42,9 +42,10 @@ public function add(ServiceProvider $provider, string ...$contexts): ServiceProv */ public function provideTo(App $app): void { - if (!$this->providers) { + if ($this->providers === null) { return; } + $this->addProvidersToApp($app, $this->providers); $this->providers = null; } diff --git a/src/ProviderStatus.php b/src/ProviderStatus.php index d0b57ee..3241b61 100644 --- a/src/ProviderStatus.php +++ b/src/ProviderStatus.php @@ -13,22 +13,13 @@ final class ProviderStatus implements \JsonSerializable public const BOOTED = 'Booted'; public const SKIPPED = 'Skipped'; - /** - * @var string - */ - private $status; - - /** - * @var AppStatus - */ - private $appStatus; - - /** - * @var array - */ - private $appStatuses = []; + private string $status; + private AppStatus $appStatus; + /** @var array */ + private array $appStatuses = []; /** + * @param AppStatus $appStatus * @return ProviderStatus */ public static function new(AppStatus $appStatus): ProviderStatus @@ -68,7 +59,7 @@ public function nowSkipped(AppStatus $appStatus): ProviderStatus */ public function nowAdded(AppStatus $appStatus): ProviderStatus { - if ($this->status !== self::IDLE && $this->status !== self::SKIPPED) { + if (($this->status !== self::IDLE) && ($this->status !== self::SKIPPED)) { $this->cantMoveTo(self::ADDED); } @@ -142,7 +133,6 @@ public function __toString() /** * @return array */ - #[\ReturnTypeWillChange] public function jsonSerialize(): array { return $this->appStatuses; @@ -154,7 +144,9 @@ public function jsonSerialize(): array */ private function cantMoveTo(string $desired): void { + // phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped throw new \DomainException("Can't move from status '{$this->status}' to '{$desired}'."); + // phpcs:enable WordPress.Security.EscapeOutput.ExceptionNotEscaped } /** @@ -167,18 +159,18 @@ private function checkAndUpdateAppStatus(AppStatus $appStatus, string $status): $error = sprintf( "Can't move to status '%s': current App status '%s', is not compatible with '%s'.", $status, - (string)$this->appStatus, - (string)$appStatus + (string) $this->appStatus, + (string) $appStatus ); if ($this->appStatus->isThemesStep() && !$appStatus->isThemesStep()) { - throw new \DomainException($error); + throw new \DomainException(esc_html($error)); } if ($this->appStatus->isPluginsStep() && $appStatus->isEarly()) { - throw new \DomainException($error); + throw new \DomainException(esc_html($error)); } - $this->appStatuses[$status] = (string)$appStatus; + $this->appStatuses[$status] = (string) $appStatus; } } diff --git a/src/SiteConfig.php b/src/SiteConfig.php index ff4ff56..1a930e5 100644 --- a/src/SiteConfig.php +++ b/src/SiteConfig.php @@ -1,5 +1,7 @@ disableDebug(); diff --git a/tests/phpunit/AppTest.php b/tests/phpunit/AppTest.php index c963f3d..e7365e5 100644 --- a/tests/phpunit/AppTest.php +++ b/tests/phpunit/AppTest.php @@ -5,7 +5,6 @@ namespace Inpsyde\App\Tests; use Brain\Monkey\Actions; -use Brain\Monkey\Functions; use Inpsyde\App\App; use Inpsyde\App\AppStatus; use Inpsyde\App\Container; @@ -18,23 +17,6 @@ class AppTest extends TestCase { - /** - * @return void - */ - protected function setUp(): void - { - parent::setUp(); - - Functions\when('remove_all_actions')->justReturn(); - - Actions\expectDone(App::ACTION_ERROR) - ->with(\Mockery::type(\Throwable::class)) - ->zeroOrMoreTimes() - ->whenHappen(static function (\Throwable $throwable) { - throw $throwable; - }); - } - /** * @test * @runInSeparateProcess @@ -100,22 +82,14 @@ public function testDebugInfo(): void $info = $app->debugInfo(); - static::assertSame($info['status'], (string)AppStatus::new()); + static::assertSame($info['status'], (string) AppStatus::new()); static::assertIsArray($info['providers']); static::assertSame(['p1', 'p2'], array_keys($info['providers'])); } - public function debugProvider(): array - { - return [ - 'debug disabled' => [false], - 'debug enabled' => [true], - ]; - } - /** * @test - * @dataProvider debugProvider + * @dataProvider provideDebugData * @param bool $isDebug */ public function testBootFlow(bool $isDebug): void @@ -127,13 +101,13 @@ public function testBootFlow(bool $isDebug): void Actions\expectAdded('plugins_loaded') ->once() - ->whenHappen(static function (callable $callable) use (&$onPluginsLoaded) { + ->whenHappen(static function (callable $callable) use (&$onPluginsLoaded): void { $onPluginsLoaded = $callable; }); Actions\expectAdded('after_setup_theme') ->once() - ->whenHappen(static function (callable $callable) use (&$onAfterSetupTheme) { + ->whenHappen(static function (callable $callable) use (&$onAfterSetupTheme): void { $onAfterSetupTheme = $callable; }); @@ -160,8 +134,7 @@ public function providers(): ServiceProviders 'p-plugins-1', '__return_true', static function (Container $container): bool { - echo - $container->get('a') + echo $container->get('a') . $container->get('b') . $container->get('c'); return true; @@ -241,7 +214,7 @@ static function ( /** * @test - * @dataProvider debugProvider + * @dataProvider provideDebugData * @param bool $isDebug */ public function testNestedAddProvider(bool $isDebug): void @@ -314,7 +287,7 @@ public function testNestedAddProvider(bool $isDebug): void /** * @test - * @dataProvider debugProvider + * @dataProvider provideDebugData * @param bool $isDebug */ public function testCallingBootFromNestedAddProviderFails(bool $isDebug): void @@ -342,7 +315,7 @@ public function testCallingBootFromNestedAddProviderFails(bool $isDebug): void /** * @test - * @dataProvider debugProvider + * @dataProvider provideDebugData * @param bool $isDebug */ public function testDependantProviderOnLastBootIsBooted(bool $isDebug): void @@ -376,20 +349,20 @@ static function (): bool { Actions\expectAdded('plugins_loaded') ->once() - ->whenHappen(static function (callable $callable) use (&$onPluginsLoaded) { + ->whenHappen(static function (callable $callable) use (&$onPluginsLoaded): void { $onPluginsLoaded = $callable; }); Actions\expectAdded('init') ->once() - ->whenHappen(static function (callable $callable) use (&$onInit) { + ->whenHappen(static function (callable $callable) use (&$onInit): void { $onInit = $callable; }); Actions\expectDone(App::ACTION_REGISTERED_PROVIDER) ->with($dependency->id(), \Mockery::type(App::class)) ->once() - ->whenHappen(static function (string $providerId, App $app) use ($dependant) { + ->whenHappen(static function (string $providerId, App $app) use ($dependant): void { static::assertTrue($app->status()->isThemesStep()); $app->addProvider($dependant); }); @@ -416,6 +389,17 @@ static function (): bool { static::assertTrue($app->hasProviders($dependency->id())); } + /** + * @return array + */ + public static function provideDebugData(): array + { + return [ + 'debug disabled' => [false], + 'debug enabled' => [true], + ]; + } + /** * @param string $id * @param callable|null $register @@ -434,7 +418,7 @@ public static function factoryStringObject(string $string): object { return new class ($string) { - private $string; + private string $string; public function __construct(string $string) { diff --git a/tests/phpunit/ContainerTest.php b/tests/phpunit/ContainerTest.php index 75f1a7e..17f223e 100644 --- a/tests/phpunit/ContainerTest.php +++ b/tests/phpunit/ContainerTest.php @@ -11,18 +11,6 @@ class ContainerTest extends TestCase { - /** - * @test - */ - public function testGetFailWithTypeErrorIfNeeded(): void - { - $container = $this->factoryContainer(); - - $this->expectException(\TypeError::class); - - $container->get(1); - } - /** * @test */ @@ -93,18 +81,6 @@ public function testAddFactoryMakeGetReturnDifferentInstances(): void static::assertEquals($container->get('foo'), $container->get('foo')); } - /** - * @test - */ - public function testHasFailWithTypeErrorIfNeeded(): void - { - $container = $this->factoryContainer(); - - $this->expectException(\TypeError::class); - - $container->has(1); - } - /** * @test */ @@ -125,9 +101,9 @@ public function testHasFromPimple(): void */ public function testWithMultiContainers(): void { - $cont1 = self::factoryCustomContainer(['a' => 'A!']); - $cont2 = self::factoryCustomContainer(['b' => 'B!']); - $cont3 = self::factoryCustomContainer(['c' => 'C!']); + $cont1 = $this->factoryCustomContainer(['a' => 'A!']); + $cont2 = $this->factoryCustomContainer(['b' => 'B!']); + $cont3 = $this->factoryCustomContainer(['c' => 'C!']); $container = $this->factoryContainer($cont1, $cont2); $container->addContainer($cont3); @@ -152,11 +128,11 @@ public function testWithMultiContainers(): void * @param array $things * @return ContainerInterface */ - private static function factoryCustomContainer(array $things): ContainerInterface + private function factoryCustomContainer(array $things): ContainerInterface { return new class ($things) implements ContainerInterface { - private $things; + private array $things; public function __construct(array $things) { diff --git a/tests/phpunit/EnvConfigTest.php b/tests/phpunit/EnvConfigTest.php index 3e4fd25..863ae9b 100644 --- a/tests/phpunit/EnvConfigTest.php +++ b/tests/phpunit/EnvConfigTest.php @@ -10,140 +10,23 @@ use Inpsyde\App\Location\GenericLocations; use Inpsyde\App\Location\VipLocations; use Inpsyde\App\Location\WpEngineLocations; +use Inpsyde\App\SiteConfig; class EnvConfigTest extends TestCase { - /** - * @return void - */ - protected function setUp(): void - { - parent::setUp(); - - Functions\when('network_site_url')->alias(static function (string $path = '/'): string { - return 'http://example.com/' . ltrim($path, '/'); - }); - - Functions\when('content_url')->alias(static function (string $path = '/'): string { - return 'http://example.com/wp-content/' . ltrim($path, '/'); - }); - - Functions\when('wp_normalize_path')->alias(static function (string $path): string { - return str_replace('\\', '/', $path); - }); - } - /** * @return void */ protected function tearDown(): void { parent::tearDown(); + unset($_ENV['VIP_GO_ENV']); unset($_ENV['TEST_ME']); unset($_SERVER['TEST_ME']); unset($_SERVER['HTTP_TEST_ME']); } - /** - * @test - */ - public function testEnvFromEnvVar(): void - { - $_ENV['VIP_GO_ENV'] = 'preprod'; - - $env = new EnvConfig(); - - static::assertSame(EnvConfig::STAGING, $env->env()); - static::assertTrue($env->envIs(EnvConfig::STAGING)); - } - - /** - * @test - */ - public function testEnvFromEnvVarIsNotFiltered(): void - { - $_ENV['VIP_GO_ENV'] = 'preprod'; - - Filters\expectApplied(EnvConfig::FILTER_ENV_NAME)->never(); - - $env = new EnvConfig(); - - static::assertSame(EnvConfig::STAGING, $env->env()); - static::assertTrue($env->envIs(EnvConfig::STAGING)); - } - - /** - * @test - * @runInSeparateProcess - */ - public function testEnvFromConstantInNotFiltered(): void - { - define('WP_ENVIRONMENT_TYPE', 'test'); - - Filters\expectApplied(EnvConfig::FILTER_ENV_NAME)->never(); - - $env = new EnvConfig(); - - static::assertSame(EnvConfig::STAGING, $env->env()); - static::assertTrue($env->envIs(EnvConfig::STAGING)); - } - - /** - * @test - * @runInSeparateProcess - */ - public function testEnvFromWpEngine(): void - { - Functions\when('is_wpe')->justReturn(null); - - $env = new EnvConfig(); - - static::assertSame(EnvConfig::STAGING, $env->env()); - static::assertTrue($env->envIs(EnvConfig::STAGING)); - } - - /** - * @test - */ - public function testEnvDefaultProduction(): void - { - $env = new EnvConfig(); - - static::assertSame(EnvConfig::PRODUCTION, $env->env()); - static::assertTrue($env->envIs(EnvConfig::PRODUCTION)); - } - - /** - * @test - * @runInSeparateProcess - */ - public function testEnvDefaultFromWpDebug(): void - { - define('WP_DEBUG', true); - - $env = new EnvConfig(); - - static::assertSame(EnvConfig::DEVELOPMENT, $env->env()); - static::assertTrue($env->envIs(EnvConfig::DEVELOPMENT)); - } - - /** - * @test - */ - public function testEnvDefaultFiltered(): void - { - $env = new EnvConfig(); - - Filters\expectApplied(EnvConfig::FILTER_ENV_NAME) - ->once() - ->with(EnvConfig::PRODUCTION) - ->andReturn('pre-prod'); - - static::assertSame(EnvConfig::STAGING, $env->env()); - static::assertTrue($env->envIs(EnvConfig::STAGING)); - } - /** * @test * @runInSeparateProcess @@ -155,8 +38,8 @@ public function testHostingOther(): void $env = new EnvConfig(); - static::assertSame(EnvConfig::HOSTING_OTHER, $env->hosting()); - static::assertTrue($env->hostingIs(EnvConfig::HOSTING_OTHER)); + static::assertSame(SiteConfig::HOSTING_OTHER, $env->hosting()); + static::assertTrue($env->hostingIs(SiteConfig::HOSTING_OTHER)); static::assertInstanceOf(GenericLocations::class, $env->locations()); } @@ -206,8 +89,8 @@ public function testHostingSpaces(): void $env = new EnvConfig(); - static::assertSame(EnvConfig::HOSTING_SPACES, $env->hosting()); - static::assertTrue($env->hostingIs(EnvConfig::HOSTING_SPACES)); + static::assertSame(SiteConfig::HOSTING_SPACES, $env->hosting()); + static::assertTrue($env->hostingIs(SiteConfig::HOSTING_SPACES)); static::assertInstanceOf(GenericLocations::class, $env->locations()); } diff --git a/tests/phpunit/Location/GenericLocationsTest.php b/tests/phpunit/Location/GenericLocationsTest.php index 68f549e..33d8a0e 100644 --- a/tests/phpunit/Location/GenericLocationsTest.php +++ b/tests/phpunit/Location/GenericLocationsTest.php @@ -8,33 +8,12 @@ use Inpsyde\App\Location\GenericLocations; use Inpsyde\App\Location\LocationResolver; use Inpsyde\App\Tests\TestCase; -use Brain\Monkey\Functions; /** * @runTestsInSeparateProcesses */ class GenericLocationsTest extends TestCase { - /** - * @return void - */ - protected function setUp(): void - { - parent::setUp(); - - Functions\when('network_site_url')->alias(static function (string $path = '/'): string { - return 'http://example.com/' . ltrim($path, '/'); - }); - - Functions\when('content_url')->alias(static function (string $path = '/'): string { - return 'http://example.com/wp-content/' . ltrim($path, '/'); - }); - - Functions\when('wp_normalize_path')->alias(static function (string $path): string { - return str_replace('\\', '/', $path); - }); - } - /** * @test */ @@ -64,25 +43,25 @@ public function testResolveDefaultLocations(): void $rootUrl = $locations->rootUrl(); static::assertSame($vendorDir, WP_CONTENT_DIR . '/vendor/foo/bar'); - static::assertSame($vendorUrl, 'http://example.com/wp-content/vendor/'); + static::assertSame($vendorUrl, 'https://example.com/wp-content/vendor/'); static::assertSame($contentDir, WP_CONTENT_DIR . '/'); - static::assertSame($contentUrl, 'http://example.com/wp-content/'); + static::assertSame($contentUrl, 'https://example.com/wp-content/'); static::assertSame($pluginDir, WP_CONTENT_DIR . '/plugins/wordpress-seo'); - static::assertSame($pluginUrl, 'http://example.com/wp-content/plugins/wordpress-seo'); + static::assertSame($pluginUrl, 'https://example.com/wp-content/plugins/wordpress-seo'); static::assertSame($themeDir, WP_CONTENT_DIR . '/themes/twentytwenty'); - static::assertSame($themeUrl, 'http://example.com/wp-content/themes/twentytwenty'); + static::assertSame($themeUrl, 'https://example.com/wp-content/themes/twentytwenty'); static::assertSame($muPluginDir, WP_CONTENT_DIR . '/mu-plugins/foo.php'); - static::assertSame($muPluginUrl, 'http://example.com/wp-content/mu-plugins/foo.php'); + static::assertSame($muPluginUrl, 'https://example.com/wp-content/mu-plugins/foo.php'); static::assertSame($languagesDir, WP_CONTENT_DIR . '/languages/'); - static::assertSame($languagesUrl, 'http://example.com/wp-content/languages/'); + static::assertSame($languagesUrl, 'https://example.com/wp-content/languages/'); static::assertSame($rootDir, ABSPATH); - static::assertSame($rootUrl, 'http://example.com/'); + static::assertSame($rootUrl, 'https://example.com/'); } /** @@ -97,7 +76,7 @@ public function testResolveCustomLocations(): void 'LOCATIONS', [ LocationResolver::URL => [ - 'foo' => 'http://example.com/foo/', + 'foo' => 'https://example.com/foo/', ], LocationResolver::DIR => [ 'foo' => __DIR__, @@ -106,7 +85,7 @@ public function testResolveCustomLocations(): void ); $_ENV['WP_APP_BAR_DIR'] = dirname(__DIR__); - $_ENV['WP_APP_BAR_URL'] = 'http://example.com/bar'; + $_ENV['WP_APP_BAR_URL'] = 'https://example.com/bar'; $locations = GenericLocations::createFromConfig(new EnvConfig()); @@ -117,9 +96,9 @@ public function testResolveCustomLocations(): void $barUrl = $locations->resolveUrl('bar'); static::assertSame($fooDir, str_replace('\\', '/', __DIR__) . '/'); - static::assertSame($fooUrl, 'http://example.com/foo/'); + static::assertSame($fooUrl, 'https://example.com/foo/'); static::assertSame($barDir, str_replace('\\', '/', dirname(__DIR__)) . '/'); - static::assertSame($barUrl, 'http://example.com/bar/'); + static::assertSame($barUrl, 'https://example.com/bar/'); } } diff --git a/tests/phpunit/Location/LocationResolverTest.php b/tests/phpunit/Location/LocationResolverTest.php index 2cd7081..933d8f6 100644 --- a/tests/phpunit/Location/LocationResolverTest.php +++ b/tests/phpunit/Location/LocationResolverTest.php @@ -8,33 +8,12 @@ use Inpsyde\App\Location\LocationResolver; use Inpsyde\App\Location\Locations; use Inpsyde\App\Tests\TestCase; -use Brain\Monkey\Functions; /** * @runTestsInSeparateProcesses */ class LocationResolverTest extends TestCase { - /** - * @return void - */ - protected function setUp(): void - { - parent::setUp(); - - Functions\when('network_site_url')->alias(static function (string $path = '/'): string { - return 'http://example.com/' . ltrim($path, '/'); - }); - - Functions\when('content_url')->alias(static function (string $path = '/'): string { - return 'http://example.com/wp-content/' . ltrim($path, '/'); - }); - - Functions\when('wp_normalize_path')->alias(static function (string $path): string { - return str_replace('\\', '/', $path); - }); - } - /** * @test */ @@ -69,13 +48,13 @@ public function testResolveDefaultLocations(): void $rootUrl = $resolver->resolveUrl(Locations::ROOT); static::assertSame($vendorDir, WP_CONTENT_DIR . '/vendor/foo/bar'); - static::assertSame($vendorUrl, 'http://example.com/wp-content/vendor/'); + static::assertSame($vendorUrl, 'https://example.com/wp-content/vendor/'); static::assertSame($contentDir, WP_CONTENT_DIR . '/'); - static::assertSame($contentUrl, 'http://example.com/wp-content/'); + static::assertSame($contentUrl, 'https://example.com/wp-content/'); static::assertSame($rootDir, ABSPATH); - static::assertSame($rootUrl, 'http://example.com/'); + static::assertSame($rootUrl, 'https://example.com/'); } /** @@ -90,7 +69,7 @@ public function testResolveOverriddenDefaultLocations(): void 'LOCATIONS', [ LocationResolver::URL => [ - Locations::ROOT => 'http://root.example.com', + Locations::ROOT => 'https://root.example.com', ], ] ); @@ -99,7 +78,7 @@ public function testResolveOverriddenDefaultLocations(): void new EnvConfig(), [ LocationResolver::URL => [ - Locations::VENDOR => 'http://example.com/vendor', + Locations::VENDOR => 'https://example.com/vendor', ], LocationResolver::DIR => [ Locations::VENDOR => __DIR__ . '/vendor', @@ -108,7 +87,7 @@ public function testResolveOverriddenDefaultLocations(): void ); $_ENV['WP_APP_ROOT_DIR'] = '/var/www/'; - $_ENV['WP_APP_CONTENT_URL'] = 'http://content.example.com'; + $_ENV['WP_APP_CONTENT_URL'] = 'https://content.example.com'; $vendorDir = $resolver->resolveDir(Locations::VENDOR, 'foo/bar'); $vendorUrl = $resolver->resolveUrl(Locations::VENDOR); @@ -119,12 +98,12 @@ public function testResolveOverriddenDefaultLocations(): void $pluginUrl = $resolver->resolveUrl(Locations::PLUGINS, 'multilingualpress'); static::assertSame(str_replace('\\', '/', __DIR__) . '/vendor/foo/bar', $vendorDir); - static::assertSame('http://example.com/vendor/', $vendorUrl); + static::assertSame('https://example.com/vendor/', $vendorUrl); static::assertSame('/var/www/', $rootDir); - static::assertSame('http://root.example.com/', $rootUrl); - static::assertSame('http://content.example.com/', $contentUrl); + static::assertSame('https://root.example.com/', $rootUrl); + static::assertSame('https://content.example.com/', $contentUrl); static::assertSame(str_replace('\\', '/', __DIR__) . '/wp-content/', $contentDir); - static::assertSame('http://content.example.com/plugins/multilingualpress', $pluginUrl); + static::assertSame('https://content.example.com/plugins/multilingualpress', $pluginUrl); } /** @@ -139,7 +118,7 @@ public function testResolveCustomLocations(): void new EnvConfig(), [ LocationResolver::URL => [ - 'foo' => 'http://example.com/foo', + 'foo' => 'https://example.com/foo', ], LocationResolver::DIR => [ 'foo' => __DIR__, @@ -148,7 +127,7 @@ public function testResolveCustomLocations(): void ); $_ENV['WP_APP_BAR_DIR'] = dirname(__DIR__); - $_ENV['WP_APP_BAR_URL'] = 'http://example.com/bar'; + $_ENV['WP_APP_BAR_URL'] = 'https://example.com/bar'; $fooDir = $resolver->resolveDir('foo'); $fooUrl = $resolver->resolveUrl('foo'); @@ -157,9 +136,9 @@ public function testResolveCustomLocations(): void $barUrl = $resolver->resolveUrl('bar'); static::assertSame($fooDir, str_replace('\\', '/', __DIR__) . '/'); - static::assertSame($fooUrl, 'http://example.com/foo/'); + static::assertSame($fooUrl, 'https://example.com/foo/'); static::assertSame($barDir, str_replace('\\', '/', dirname(__DIR__)) . '/'); - static::assertSame($barUrl, 'http://example.com/bar/'); + static::assertSame($barUrl, 'https://example.com/bar/'); } } diff --git a/tests/phpunit/Location/VipLocationsTest.php b/tests/phpunit/Location/VipLocationsTest.php index 2dc8c24..6d4e573 100644 --- a/tests/phpunit/Location/VipLocationsTest.php +++ b/tests/phpunit/Location/VipLocationsTest.php @@ -6,35 +6,15 @@ use Inpsyde\App\EnvConfig; use Inpsyde\App\Location\LocationResolver; +use Inpsyde\App\Location\Locations; use Inpsyde\App\Location\VipLocations; use Inpsyde\App\Tests\TestCase; -use Brain\Monkey\Functions; /** * @runTestsInSeparateProcesses */ class VipLocationsTest extends TestCase { - /** - * @return void - */ - protected function setUp(): void - { - parent::setUp(); - - Functions\when('network_site_url')->alias(static function (string $path = '/'): string { - return 'http://example.com/' . ltrim($path, '/'); - }); - - Functions\when('content_url')->alias(static function (string $path = '/'): string { - return 'http://example.com/wp-content/' . ltrim($path, '/'); - }); - - Functions\when('wp_normalize_path')->alias(static function (string $path): string { - return str_replace('\\', '/', $path); - }); - } - /** * @test */ @@ -61,11 +41,11 @@ public function testVipLocations(): void $configDir = $locations->vipConfigDir('vip-config.php'); static::assertSame("{$contentDir}/images/", $imagesDir); - static::assertSame('http://example.com/wp-content/images/', $imagesUrl); + static::assertSame('https://example.com/wp-content/images/', $imagesUrl); static::assertSame("{$contentDir}/client-mu-plugins/", $clientMuDir); - static::assertSame('http://example.com/wp-content/client-mu-plugins/', $clientMuUrl); + static::assertSame('https://example.com/wp-content/client-mu-plugins/', $clientMuUrl); static::assertSame("{$contentDir}/client-mu-plugins/vendor/", $vendorDir); - static::assertSame('http://example.com/wp-content/client-mu-plugins/vendor/', $vendorUrl); + static::assertSame('https://example.com/wp-content/client-mu-plugins/vendor/', $vendorUrl); static::assertSame("{$contentDir}/private/", $privateDir); static::assertSame("{$contentDir}/vip-config/vip-config.php", $configDir); } @@ -87,7 +67,7 @@ public function testResolveCustomLocations(): void 'LOCATIONS', [ LocationResolver::URL => [ - VipLocations::CONTENT => 'http://static.example.com', + Locations::CONTENT => 'https://static.example.com', ], LocationResolver::DIR => [ VipLocations::PRIVATE => '/var/www/private/', @@ -109,12 +89,12 @@ public function testResolveCustomLocations(): void $themeUrl = $locations->themesUrl('twentytwenty'); static::assertSame('/var/www/images/', $imagesDir); - static::assertSame('http://static.example.com/images/', $imagesUrl); + static::assertSame('https://static.example.com/images/', $imagesUrl); static::assertSame("{$contentDir}/client-mu-plugins/", $clientMuDir); - static::assertSame('http://static.example.com/client-mu-plugins/', $clientMuUrl); + static::assertSame('https://static.example.com/client-mu-plugins/', $clientMuUrl); static::assertSame("{$contentDir}/client-mu-plugins/vendor/", $vendorDir); - static::assertSame('http://static.example.com/client-mu-plugins/vendor/', $vendorUrl); + static::assertSame('https://static.example.com/client-mu-plugins/vendor/', $vendorUrl); static::assertSame('/var/www/private/', $privateDir); - static::assertSame('http://static.example.com/themes/twentytwenty', $themeUrl); + static::assertSame('https://static.example.com/themes/twentytwenty', $themeUrl); } } diff --git a/tests/phpunit/Location/WpEngineLocationsTest.php b/tests/phpunit/Location/WpEngineLocationsTest.php index 0fb9d9b..e081f0c 100644 --- a/tests/phpunit/Location/WpEngineLocationsTest.php +++ b/tests/phpunit/Location/WpEngineLocationsTest.php @@ -8,33 +8,12 @@ use Inpsyde\App\Location\LocationResolver; use Inpsyde\App\Location\WpEngineLocations; use Inpsyde\App\Tests\TestCase; -use Brain\Monkey\Functions; /** * @runTestsInSeparateProcesses */ class WpEngineLocationsTest extends TestCase { - /** - * @return void - */ - protected function setUp(): void - { - parent::setUp(); - - Functions\when('network_site_url')->alias(static function (string $path = '/'): string { - return 'http://example.com/' . ltrim($path, '/'); - }); - - Functions\when('content_url')->alias(static function (string $path = '/'): string { - return 'http://example.com/wp-content/' . ltrim($path, '/'); - }); - - Functions\when('wp_normalize_path')->alias(static function (string $path): string { - return str_replace('\\', '/', $path); - }); - } - /** * @test */ @@ -71,7 +50,7 @@ public function testResolveCustomLocations(): void ] ); - $_ENV['WP_APP_CONTENT_URL'] = 'http://static.example.com'; + $_ENV['WP_APP_CONTENT_URL'] = 'https://static.example.com'; $locations = WpEngineLocations::createFromConfig(new EnvConfig()); @@ -79,6 +58,6 @@ public function testResolveCustomLocations(): void $themeUrl = $locations->themesUrl('twentytwenty'); static::assertSame('/var/www/private/', $privateDir); - static::assertSame('http://static.example.com/themes/twentytwenty', $themeUrl); + static::assertSame('https://static.example.com/themes/twentytwenty', $themeUrl); } } diff --git a/tests/phpunit/Provider/AutoDiscoverIdTest.php b/tests/phpunit/Provider/AutoDiscoverIdTest.php index fa28d2d..034be6b 100644 --- a/tests/phpunit/Provider/AutoDiscoverIdTest.php +++ b/tests/phpunit/Provider/AutoDiscoverIdTest.php @@ -18,8 +18,10 @@ class AutoDiscoverIdTest extends TestCase */ public function testIdFromProperty(): void { - $provider = new class extends RegisteredOnly { - public $id = 'hi there'; + $provider = new class extends RegisteredOnly + { + public string $id = 'hi there'; + public function register(Container $container): bool { return false; @@ -34,8 +36,10 @@ public function register(Container $container): bool */ public function testIdFromConstant(): void { - $provider = new class extends RegisteredOnly { + $provider = new class extends RegisteredOnly + { public const ID = 'constant!'; + public function register(Container $container): bool { return false; @@ -50,7 +54,8 @@ public function register(Container $container): bool */ public function testFromClass(): void { - $provider = new class extends RegisteredOnly { + $provider = new class extends RegisteredOnly + { public function register(Container $container): bool { return false; @@ -75,9 +80,9 @@ public function register(Container $container): bool $provider2 = clone $provider1; $provider3 = clone $provider1; - $one = $provider1->id(); - $two = $provider2->id(); - $three = $provider3->id(); + $one = $provider1->id(); + $two = $provider2->id(); + $three = $provider3->id(); static::assertSame(get_class($provider1) . '_1', $one); static::assertSame(get_class($provider2) . '_2', $two); @@ -91,6 +96,9 @@ public function register(Container $container): bool static::assertSame($three, $provider3->id()); } + /** + * @test + */ public function testIfObjectHasNotReference(): void { $providerId1 = (new class extends RegisteredOnly { diff --git a/tests/phpunit/ProviderStatusTest.php b/tests/phpunit/ProviderStatusTest.php index ee553b9..92c3505 100644 --- a/tests/phpunit/ProviderStatusTest.php +++ b/tests/phpunit/ProviderStatusTest.php @@ -21,7 +21,7 @@ public function testNoSkipped(): void $status->nowSkipped($appStatus); // this works before just created, so idle - static::assertStringStartsWith(ProviderStatus::SKIPPED, (string)$status); + static::assertStringStartsWith(ProviderStatus::SKIPPED, (string) $status); static::assertTrue($status->isAnyOf(ProviderStatus::SKIPPED)); static::assertFalse($status->isAnyOf(ProviderStatus::ADDED)); @@ -41,7 +41,7 @@ public function testNowAdded(): void $status->nowAdded($appStatus); // this works before just created, so idle - static::assertStringStartsWith(ProviderStatus::ADDED, (string)$status); + static::assertStringStartsWith(ProviderStatus::ADDED, (string) $status); static::assertTrue($status->isAnyOf(ProviderStatus::ADDED)); static::assertFalse($status->isAnyOf(ProviderStatus::SKIPPED)); @@ -80,8 +80,8 @@ public function testNowRegistered(): void $status1->nowRegistered($appStatus, false); $status2->nowRegistered($appStatus, true); - static::assertStringStartsWith(ProviderStatus::REGISTERED, (string)$status1); - static::assertStringStartsWith(ProviderStatus::REGISTERED_DELAYED, (string)$status2); + static::assertStringStartsWith(ProviderStatus::REGISTERED, (string) $status1); + static::assertStringStartsWith(ProviderStatus::REGISTERED_DELAYED, (string) $status2); static::assertTrue($status1->isAnyOf(ProviderStatus::REGISTERED)); static::assertFalse($status1->isAnyOf(ProviderStatus::REGISTERED_DELAYED)); static::assertTrue($status2->isAnyOf(ProviderStatus::REGISTERED_DELAYED)); @@ -123,8 +123,8 @@ public function testNowBooted(): void $status1->nowBooted($appStatus); $status2->nowBooted($appStatus); - static::assertStringStartsWith(ProviderStatus::BOOTED, (string)$status1); - static::assertStringStartsWith(ProviderStatus::BOOTED, (string)$status2); + static::assertStringStartsWith(ProviderStatus::BOOTED, (string) $status1); + static::assertStringStartsWith(ProviderStatus::BOOTED, (string) $status2); static::assertTrue($status1->isAnyOf(ProviderStatus::BOOTED)); static::assertFalse($status1->isAnyOf(ProviderStatus::REGISTERED)); static::assertTrue($status2->isAnyOf(ProviderStatus::BOOTED)); @@ -216,6 +216,6 @@ public function testToString(): void $regex .= ProviderStatus::REGISTERED . '(.+?)' . AppStatus::REGISTERING_PLUGINS . ', '; $regex .= ProviderStatus::BOOTED . '(.+?)' . AppStatus::BOOTING_PLUGINS . '\)$~i'; - static::assertTrue((bool)preg_match($regex, (string)$status)); + static::assertTrue((bool) preg_match($regex, (string) $status)); } } diff --git a/tests/phpunit/TestCase.php b/tests/phpunit/TestCase.php index c6cad4f..8ef22a7 100644 --- a/tests/phpunit/TestCase.php +++ b/tests/phpunit/TestCase.php @@ -5,6 +5,7 @@ namespace Inpsyde\App\Tests; use Brain\Monkey; +use Inpsyde\App\App; use Inpsyde\WpContext; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use PHPUnit\Framework\TestCase as FrameworkTestCase; @@ -13,6 +14,8 @@ abstract class TestCase extends FrameworkTestCase { use MockeryPHPUnitIntegration; + protected string $envType = 'local'; + /** * @return void */ @@ -20,6 +23,29 @@ protected function setUp(): void { parent::setUp(); Monkey\setUp(); + + Monkey\Functions\stubEscapeFunctions(); + + Monkey\Functions\stubs([ + 'wp_get_environment_type' => fn () => $this->envType, + 'remove_all_actions' => null, + 'wp_normalize_path' => static function (string $path): string { + return str_replace('\\', '/', $path); + }, + 'network_site_url' => static function (string $path = '/'): string { + return 'https://example.com/' . ltrim($path, '/'); + }, + 'content_url' => static function (string $path = '/'): string { + return 'https://example.com/wp-content/' . ltrim($path, '/'); + }, + ]); + + Monkey\Actions\expectDone(App::ACTION_ERROR) + ->with(\Mockery::type(\Throwable::class)) + ->zeroOrMoreTimes() + ->whenHappen(static function (\Throwable $throwable): void { + throw $throwable; + }); } /** @@ -27,6 +53,8 @@ protected function setUp(): void */ protected function tearDown(): void { + $this->envType = 'local'; + Monkey\tearDown(); parent::tearDown(); } @@ -44,4 +72,13 @@ protected function factoryContext(?string $case = null, bool $withCli = false): return $withCli ? $context->withCli() : $context; } + + /** + * @param string $envType + * @return void + */ + protected function forceEnvType(string $envType): void + { + $this->envType = $envType; + } }