Skip to content

Commit

Permalink
feat(installer): allow differentiating between migration types (#261)
Browse files Browse the repository at this point in the history
- Note: deprecations are now demoted to notice level

---------

Co-authored-by: markernst97 <[email protected]>
  • Loading branch information
EdieLemoine and Mark-Ernst authored Mar 18, 2024
1 parent 7ec57d6 commit 21ce3cf
Show file tree
Hide file tree
Showing 23 changed files with 748 additions and 96 deletions.
15 changes: 14 additions & 1 deletion config/pdk-dependencies.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,25 @@
use function DI\value;

return [
/**
* The current version of the pdk according to the composer.json file.
*/
'pdkVersion' => factory(function (FileSystemInterface $fileSystem): string {
$composerJson = json_decode($fileSystem->get(__DIR__ . '/../composer.json'), true);
$rootDir = Pdk::get('rootDir');
$composerJson = json_decode($fileSystem->get("$rootDir/composer.json"), true);

return $composerJson['version'];
}),

/**
* The next major version of the pdk. Used for deprecation messages.
*/
'pdkNextMajorVersion' => factory(function (): string {
$version = Pdk::get('pdkVersion');

return (int) explode('.', $version)[0] + 1 . '.0.0';
}),

/**
* The minimum PHP version required to run the app.
*/
Expand Down
14 changes: 12 additions & 2 deletions config/pdk-template.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
use MyParcelNL\Pdk\Base\Contract\CronServiceInterface;
use MyParcelNL\Pdk\Frontend\Contract\ViewServiceInterface;
use MyParcelNL\Pdk\Language\Contract\LanguageServiceInterface;
use MyParcelNL\Pdk\Logger\Contract\PdkLoggerInterface;
use MyParcelNL\Pdk\Settings\Contract\PdkSettingsRepositoryInterface;
use Psr\Log\LoggerInterface;
use function DI\autowire;
use function DI\get;
use function DI\value;

/**
Expand Down Expand Up @@ -135,10 +137,18 @@
/**
* Handles logging.
*
* @see \MyParcelNL\Pdk\Logger\AbstractLogger
* @see \MyParcelNL\Pdk\Logger\AbstractLogger
* @deprecated Will be removed in v3.0.0. Use PdkLoggerInterface instead.
*/

LoggerInterface::class => autowire(),
LoggerInterface::class => autowire(),

/**
* Handles logging.
*
* @see \MyParcelNL\Pdk\Logger\AbstractLogger
*/
PdkLoggerInterface::class => get(LoggerInterface::class),

/**
* Exposes frontend api url and endpoints.
Expand Down
12 changes: 12 additions & 0 deletions src/App/Installer/Contract/InstallationMigrationInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace MyParcelNL\Pdk\App\Installer\Contract;

/**
* Migrations that are run during the installation process as well as on a migration after the version in getVersion().
*/
interface InstallationMigrationInterface extends MigrationInterface
{
}
8 changes: 7 additions & 1 deletion src/App/Installer/Contract/MigrationServiceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@

namespace MyParcelNL\Pdk\App\Installer\Contract;

/**
* @method array getUpgradeMigrations()
* @method array getInstallationMigrations()
*/
interface MigrationServiceInterface
{
/**
* @return array<class-string<\MyParcelNL\Pdk\App\Installer\Contract\MigrationInterface>>
* @return class-string<\MyParcelNL\Pdk\App\Installer\Contract\MigrationInterface>[]
* @deprecated Will be removed in v3.0.0. Implement getUpgradeMigrations() and getInstallationMigrations() instead
* @todo remove in v3.0.0
*/
public function all(): array;
}
12 changes: 12 additions & 0 deletions src/App/Installer/Contract/UpgradeMigrationInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace MyParcelNL\Pdk\App\Installer\Contract;

/**
* Migrations that are run during an upgrade.
*/
interface UpgradeMigrationInterface extends MigrationInterface
{
}
131 changes: 112 additions & 19 deletions src/App/Installer/Service/InstallerService.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ public function uninstall(...$args): void
if ($installedVersion) {
Logger::debug("Uninstalling $installedVersion");
$this->executeUninstallation(...$args);
$this->migrateDown();
$this->updateInstalledVersion(null);
}
}
Expand All @@ -92,6 +91,7 @@ public function uninstall(...$args): void
protected function executeInstallation(...$args): void
{
$this->setDefaultSettings();
$this->migrateInstall();
}

/**
Expand All @@ -101,6 +101,7 @@ protected function executeInstallation(...$args): void
*/
protected function executeUninstallation(...$args): void
{
$this->migrateUninstall();
}

/**
Expand All @@ -116,13 +117,20 @@ protected function getInstalledVersion(): ?string
*/
protected function migrateDown(): void
{
$this->getMigrations()
->filter(function (MigrationInterface $migration) {
return version_compare($migration->getVersion(), $this->getInstalledVersion(), '<=');
})
->each(function (MigrationInterface $migration) {
$migration->down();
});
$this->runDownMigrations(
$this->getUpgradeMigrations()
->filter(function (MigrationInterface $migration) {
return version_compare($migration->getVersion(), $this->getInstalledVersion(), '<=');
})
);
}

/**
* @return void
*/
protected function migrateInstall(): void
{
$this->runUpMigrations($this->getInstallationMigrations());
}

/**
Expand All @@ -132,14 +140,7 @@ protected function migrateDown(): void
*/
protected function migrateUp(string $version): void
{
$this->getMigrations()
->filter(function (MigrationInterface $migration) use ($version) {
return version_compare($migration->getVersion(), $this->getInstalledVersion(), '>')
&& version_compare($migration->getVersion(), $version, '<=');
})
->each(function (MigrationInterface $migration) {
$migration->up();
});
$this->runUpMigrations($this->getUpgradeMigrations($version));
}

/**
Expand All @@ -163,13 +164,105 @@ protected function updateInstalledVersion(?string $version): void
}

/**
* @return \MyParcelNL\Pdk\Base\Support\Collection<MigrationInterface>
* @template T of \MyParcelNL\Pdk\App\Installer\Contract\MigrationInterface
* @param array<T> $migrations
*
* @return \MyParcelNL\Pdk\Base\Support\Collection
*/
private function getMigrations(): Collection
private function createMigrationCollection(array $migrations): Collection
{
return Collection::make($this->migrationService->all())
return Collection::make($migrations)
->map(function (string $className) {
return Pdk::get($className);
});
}

/**
* @return \MyParcelNL\Pdk\Base\Support\Collection<\MyParcelNL\Pdk\App\Installer\Contract\InstallationMigrationInterface>
* @todo v3.0.0 remove legacy support
*/
private function getInstallationMigrations(): Collection
{
if (! method_exists($this->migrationService, 'getInstallationMigrations')) {
Logger::deprecated(
sprintf('Method "%s::all()"', MigrationServiceInterface::class),
'getUpgradeMigrations and getInstallationMigrations'
);

return new Collection();
}

return $this->createMigrationCollection($this->migrationService->getInstallationMigrations());
}

/**
* @param null|string $version
*
* @return \MyParcelNL\Pdk\Base\Support\Collection<\MyParcelNL\Pdk\App\Installer\Contract\UpgradeMigrationInterface>
* @todo v3.0.0 remove legacy support
*/
private function getUpgradeMigrations(?string $version = null): Collection
{
$useLegacy = ! method_exists($this->migrationService, 'getUpgradeMigrations');

if ($useLegacy) {
Logger::deprecated(
sprintf('Method "%s::all()"', MigrationServiceInterface::class),
'getUpgradeMigrations and getInstallationMigrations'
);
}

$migrations = $useLegacy
? $this->migrationService->all()
: $this->migrationService->getUpgradeMigrations();

$collection = $this->createMigrationCollection($migrations);

if (! $version) {
return $collection;
}

return $collection->filter(function (MigrationInterface $migration) use ($version) {
return version_compare($migration->getVersion(), $this->getInstalledVersion(), '>')
&& version_compare($migration->getVersion(), $version, '<=');
});
}

private function migrateUninstall(): void
{
$this->migrateDown();
$this->runDownMigrations($this->getInstallationMigrations());
}

/**
* @param \MyParcelNL\Pdk\Base\Support\Collection<MigrationInterface> $migrations
*
* @return void
*/
private function runDownMigrations(Collection $migrations): void
{
$migrations
->sort(function (MigrationInterface $a, MigrationInterface $b) {
return version_compare($b->getVersion(), $a->getVersion());
})
->each(function (MigrationInterface $migration) {
$migration->down();
});
}

/**
* @param \MyParcelNL\Pdk\Base\Support\Collection<MigrationInterface> $migrations
*
* @return void
*/
private function runUpMigrations(Collection $migrations): void
{
$migrations
->sort(function (MigrationInterface $a, MigrationInterface $b) {
return version_compare($a->getVersion(), $b->getVersion());
})
->each(function (MigrationInterface $migration) {
$migration->up();
});
}
}
5 changes: 5 additions & 0 deletions src/App/Installer/Service/MigrationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

class MigrationService implements MigrationServiceInterface
{
/**
* @return class-string<\MyParcelNL\Pdk\App\Installer\Contract\MigrationInterface>[]
* @deprecated use getUpgradeMigrations() instead
* @todo remove in v3.0.0
*/
public function all(): array
{
return [];
Expand Down
5 changes: 1 addition & 4 deletions src/Base/Concern/HasAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -744,10 +744,7 @@ protected function isGuarded(string $key): bool
*/
protected function logDeprecationWarning(string $key, string $newKey): void
{
Logger::warning(
"[DEPRECATION] Attribute '$key' is deprecated. Use '$newKey' instead.",
['class' => static::class]
);
Logger::deprecated("Attribute '$key'", "'$newKey'", ['class' => static::class]);
}

/**
Expand Down
7 changes: 4 additions & 3 deletions src/Facade/Logger.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace MyParcelNL\Pdk\Facade;

use MyParcelNL\Pdk\Base\Facade;
use Psr\Log\LoggerInterface;
use MyParcelNL\Pdk\Logger\Contract\PdkLoggerInterface;

/**
* @method static void log($level, $message, array $context = [])
Expand All @@ -18,7 +18,8 @@
* @method static void info($message, array $context = [])
* @method static void notice($message, array $context = [])
* @method static void warning($message, array $context = [])
* @see \Psr\Log\LoggerInterface
* @method static void deprecated(string $subject, string $replacement = null, array $context = [])
* @see \MyParcelNL\Pdk\Logger\Contract\PdkLoggerInterface
*/
final class Logger extends Facade
{
Expand All @@ -27,6 +28,6 @@ final class Logger extends Facade
*/
protected static function getFacadeAccessor(): string
{
return LoggerInterface::class;
return PdkLoggerInterface::class;
}
}
26 changes: 24 additions & 2 deletions src/Logger/AbstractLogger.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

namespace MyParcelNL\Pdk\Logger;

use Psr\Log\LoggerInterface;
use MyParcelNL\Pdk\Facade\Pdk;
use MyParcelNL\Pdk\Logger\Contract\PdkLoggerInterface;
use Psr\Log\LogLevel;

abstract class AbstractLogger implements LoggerInterface
abstract class AbstractLogger implements PdkLoggerInterface
{
/**
* @param $level
Expand Down Expand Up @@ -51,6 +52,27 @@ public function debug($message, array $context = []): void
$this->createLog(LogLevel::DEBUG, $message, $context);
}

/**
* @param string $subject
* @param null|string $replacement
* @param array $context
*
* @return void
*/
public function deprecated(string $subject, ?string $replacement = null, array $context = []): void
{
$message = "[DEPRECATED] $subject is deprecated.";

if ($replacement) {
$message .= " Use $replacement instead.";
}

$version = Pdk::get('pdkNextMajorVersion');
$message .= " Will be removed in $version.";

$this->notice($message, $context);
}

/**
* @param string $message
* @param array $context
Expand Down
23 changes: 23 additions & 0 deletions src/Logger/Contract/PdkLoggerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace MyParcelNL\Pdk\Logger\Contract;

use Psr\Log\LoggerInterface;

interface PdkLoggerInterface extends LoggerInterface
{
/**
* @param string $subject The thing that has been deprecated
* @param null|string $replacement The thing that will be its replacement
* @param array $context
*
* @return void
*/
public function deprecated(
string $subject,
?string $replacement = null,
array $context = []
): void;
}
Loading

0 comments on commit 21ce3cf

Please sign in to comment.