Skip to content
Merged
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
9 changes: 7 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# Values here are local dev defaults only!

# PostgreSQL
# localhost works for `composer serve` on your machine. Inside Docker Compose,
# the php service overrides this with it's own service name: DB_HOST=postgres
# Inside Docker Compose, the php service overrides this with it's own service
# name: DB_HOST=postgres; localhost applies to `composer serve` outside
DB_HOST=localhost

# Database name - postgres container creates it on first start
Expand All @@ -14,3 +14,8 @@ DB_USER=your_user_name

# Password for DB_USER - postgres image refuses to start with an empty password
DB_PASSWORD=changeme

# Redis
# Inside Docker Compose, the redis service overrides this with it's own service
# name: REDIS_HOST=redis; localhost applies to `composer serve` outside
REDIS_HOST=localhost
8 changes: 7 additions & 1 deletion .zed/tasks.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[

{
"label": "analyze",
"command": "composer analyze",
Expand Down Expand Up @@ -35,6 +34,13 @@
"shell": "system",
"reveal": "always",
},
{
"label": "lint:spec",
"command": "composer lint:spec",
"cwd": "$ZED_WORKTREE_ROOT",
"shell": "system",
"reveal": "always",
},
{
"label": "serve",
"command": "composer serve",
Expand Down
270 changes: 144 additions & 126 deletions README.md

Large diffs are not rendered by default.

60 changes: 23 additions & 37 deletions bin/fixtures/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,29 @@

declare(strict_types=1);

use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Loader;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\EntityManager;
use Laminas\ServiceManager\ServiceManager;
use LaminasApiSample\Infrastructure\DoctrineEntityManagerFactory as DoctrineEMF;
use Psr\Container\ContainerExceptionInterface;

try {
require dirname(__DIR__, 2) . '/bootstrap.php';
load_fixtures(build_loader());
} catch (Throwable $e) {
$detail = implode(' - ', [$e::class, $e->getMessage()]);
fwrite(STDERR, "Loading fixtures failed: \n{$detail}\n");
exit(1);
}

function build_loader(): Loader
{
$loader = new Loader();
$loader->loadFromDirectory(dirname(__DIR__, 2) . '/test/Fixtures');

return $loader;
}

/** @throws ContainerExceptionInterface */
function load_fixtures(Loader $loader): void
{
/** @var ServiceManager $serviceManager */
$serviceManager = require
dirname(__DIR__, 2) . '/config/service-manager.php';

/** @var EntityManager $entityManager */
$entityManager = $serviceManager->get(DoctrineEMF::SERVICE_NAME);

// ! Purge is destructive - be careful!
$executor = new ORMExecutor($entityManager, new ORMPurger());
$executor->execute($loader->getFixtures());
echo "Loading fixtures completed.\n";
}
use LaminasApiSampleTest\Fixtures\FixtureLoader;

(static function (): void {
try {
require dirname(__DIR__, 2) . '/bootstrap.php';

/** @var ServiceManager $serviceManager */
$serviceManager = require
dirname(__DIR__, 2) . '/config/service-manager.php';

/** @var EntityManager $entityManager */
$entityManager = $serviceManager->get(DoctrineEMF::SERVICE_NAME);

new FixtureLoader($entityManager)->load(
dirname(__DIR__, 2) . '/test/Fixtures',
);
echo "Loading fixtures completed.\n";
} catch (Throwable $exception) {
$detail = implode(' - ', [$exception::class, $exception->getMessage()]);
fwrite(STDERR, "Loading fixtures failed:\n{$detail}\n");
exit(1);
}
})();
135 changes: 17 additions & 118 deletions bin/migrations/generate-diff.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,126 +4,25 @@

use Doctrine\Migrations\DependencyFactory;
use Doctrine\Migrations\Generator\Exception\NoChangesDetected;
use LaminasApiSample\Infrastructure\Migrations\MigrationDiffGenerator;

try {
require dirname(__DIR__, 2) . '/bootstrap.php';
generate_diff();
} catch (NoChangesDetected) {
fwrite(STDOUT, "No changes detected.\n");
exit(0);
} catch (Throwable $e) {
$detail = implode(' - ', [$e::class, $e->getMessage()]);
fwrite(STDERR, "Generate diff failed: \n{$detail}\n");
exit(1);
}
(static function (): void {
try {
require dirname(__DIR__, 2) . '/bootstrap.php';

/**
* @throws NoChangesDetected
* @throws RuntimeException
*/
function generate_diff(): void
{
/** @var DependencyFactory $dependencyFactory */
$dependencyFactory = require __DIR__ . '/config/dependency-factory.php';
/** @var DependencyFactory $dependencyFactory */
$dependencyFactory = require __DIR__ . '/config/dependency-factory.php';

$migrationClassNamespace = array_key_first(
$dependencyFactory->getConfiguration()->getMigrationDirectories(),
);

if ($migrationClassNamespace === null) {
throw new RuntimeException('Migration namespace not found.');
}

$migrationClassName = $dependencyFactory
->getClassNameGenerator()
->generateClassName($migrationClassNamespace);

$result = $dependencyFactory->getDiffGenerator()->generate(
$migrationClassName,
null,
);

tidy_migration($result);
format_migration($result);
echo "Generated migration: {$result}\n";
}

/** @throws RuntimeException */
function tidy_migration(string $path): void
{
$contents = file_get_contents($path);
if ($contents === false) {
throw new RuntimeException("Could not read {$path}.");
}

$version = basename($path, '.php');
$new_header = <<<EOT
/**
* Migration {$version}
* This runner was auto-generated with Doctrine
*/
EOT;

$old_header = <<<EOT
/**
* Auto-generated Migration: Please modify to your needs!
*/
EOT;

$describe_up = <<<EOT
// this up() migration is auto-generated, please modify it to your needs
EOT;

$describe_down = <<<EOT
// this down() migration is auto-generated, please modify it to your needs
EOT;

$get_description = <<<EOT
public function getDescription(): string
{
return '';
}
EOT;

$contents = str_replace(
[
$old_header,
' ' . $describe_up . "\n",
' ' . $describe_down . "\n",
$get_description . "\n",
],
[$new_header, '', '', ''],
$contents,
);

if (file_put_contents($path, $contents) === false) {
throw new RuntimeException("Could not write {$path}.");
}
}

function format_migration(string $path): void
{
$mago = dirname(__DIR__, 2) . '/vendor/bin/mago';
if (!is_executable($mago)) {
fwrite(STDERR, "Mago not found; {$path} left unformatted.\n");
return;
}

/** @var list<string> $output */
$output = [];
$exitCode = 0;
exec(
escapeshellarg($mago) . ' format ' . escapeshellarg($path) . ' 2>&1',
$output,
$exitCode,
);

if ($exitCode !== 0) {
fwrite(
STDERR,
"Mago format failed; {$path} left unformatted:\n"
. implode("\n", $output)
. "\n",
$generator = new MigrationDiffGenerator(
$dependencyFactory,
dirname(__DIR__, 2) . '/vendor/bin/mago',
);
echo 'Generated migration: ' . $generator->generate() . "\n";
} catch (NoChangesDetected) {
echo "No changes detected.\n";
} catch (Throwable $exception) {
$detail = implode(' - ', [$exception::class, $exception->getMessage()]);
fwrite(STDERR, "Generate diff failed:\n{$detail}\n");
exit(1);
}
}
})();
65 changes: 18 additions & 47 deletions bin/migrations/migrate.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,22 @@

use Doctrine\Migrations\DependencyFactory;
use Doctrine\Migrations\Exception\NoMigrationsToExecute;
use Doctrine\Migrations\Metadata\MigrationPlanList;
use Doctrine\Migrations\MigratorConfiguration;

try {
require dirname(__DIR__, 2) . '/bootstrap.php';
migrate();
} catch (NoMigrationsToExecute) {
fwrite(STDOUT, 'No migrations to execute.\n');
exit(0);
} catch (Throwable $e) {
$detail = implode(' - ', [$e::class, $e->getMessage()]);
fwrite(STDERR, "Migration failed: \n{$detail}\n");
exit(1);
}

/** @throws NoMigrationsToExecute */
function migrate(): void
{
/** @var DependencyFactory $dependencyFactory */
$dependencyFactory = require __DIR__ . '/config/dependency-factory.php';

$plan = build_plan($dependencyFactory);
$config = new MigratorConfiguration()->setAllOrNothing(
$dependencyFactory->getConfiguration()->isAllOrNothing(),
);

$dependencyFactory->getMigrator()->migrate($plan, $config);
echo "Migration completed.\n";
}

/** @throws NoMigrationsToExecute */
function build_plan(DependencyFactory $dependencyFactory): MigrationPlanList
{
$dependencyFactory->getMetadataStorage()->ensureInitialized();

$latestVersion = $dependencyFactory
->getVersionAliasResolver()
->resolveVersionAlias('latest');

$plan = $dependencyFactory
->getMigrationPlanCalculator()
->getPlanUntilVersion($latestVersion);
if (!count($plan)) {
throw NoMigrationsToExecute::new();
use LaminasApiSample\Infrastructure\Migrations\MigrationRunner;

(static function (): void {
try {
require dirname(__DIR__, 2) . '/bootstrap.php';

/** @var DependencyFactory $dependencyFactory */
$dependencyFactory = require __DIR__ . '/config/dependency-factory.php';

new MigrationRunner($dependencyFactory)->run();
echo "Migration completed.\n";
} catch (NoMigrationsToExecute) {
echo "No migrations to execute.\n";
} catch (Throwable $exception) {
$detail = implode(' - ', [$exception::class, $exception->getMessage()]);
fwrite(STDERR, "Migration failed:\n{$detail}\n");
exit(1);
}

return $plan;
}
})();
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"laminas/laminas-router": "^3.19",
"laminas/laminas-servicemanager": "^3.24",
"laminas/laminas-validator": "^2.65",
"predis/predis": "^3.6",
"psr/clock": "^1.0",
"ramsey/uuid": "^4.9",
"roave/psr-container-doctrine": "^6.2",
Expand All @@ -49,6 +50,7 @@
"lint": "mago lint --minimum-fail-level=warning",
"format": "mago format",
"format:check": "mago format --dry-run",
"lint:spec": "docker run --rm -v \"$PWD/docs:/spec\" redocly/cli lint /spec/openapi.json",
"test": "phpunit",
"serve": [
"Composer\\Config::disableProcessTimeout",
Expand All @@ -67,6 +69,7 @@
"format:check": "Check formatting with Mago without writing changes.",
"lint": "Run Mago's linter.",
"test": "Run the PHPUnit unit tests.",
"lint:spec": "Run redocly/cli linter targeting the OpenApi 3.1 spec",
"serve": "Start the built-in PHP web server and serve the API sample.",
"migrations:diff": "Generate a new migration from differences between the entity mapping and the database schema.",
"migrations:migrate": "Apply all pending migrations to the database.",
Expand Down
Loading
Loading