Skip to content

Commit

Permalink
feature #860 Add support for Symfony UX Turbo (dunglas)
Browse files Browse the repository at this point in the history
This PR was squashed before being merged into the 1.0-dev branch.

Discussion
----------

Add support for Symfony UX Turbo

This PR adds a new `--broadcast` to the `make:entity` command. This generates the required template to use the broadcasting feature of UX Turbo, and also add the `#[Broadcast]` attribute to the generated entity.

Commits
-------

5aab43a Add support for Symfony UX Turbo
  • Loading branch information
weaverryan committed Apr 21, 2021
2 parents 07af269 + 5aab43a commit 8580778
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 2 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ jobs:
ports:
- 3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
mercure:
image: dunglas/mercure
env:
SERVER_NAME: :1337
MERCURE_PUBLISHER_JWT_KEY: '!ChangeMe!'
MERCURE_SUBSCRIBER_JWT_KEY: '!ChangeMe!'
MERCURE_EXTRA_DIRECTIVES: |
anonymous
cors_origins *
ports:
- 1337:1337

continue-on-error: ${{ matrix.allow-failures }}

Expand Down
3 changes: 2 additions & 1 deletion src/Doctrine/EntityClassGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function __construct(Generator $generator, DoctrineHelper $doctrineHelper
$this->doctrineHelper = $doctrineHelper;
}

public function generateEntityClass(ClassNameDetails $entityClassDetails, bool $apiResource, bool $withPasswordUpgrade = false, bool $generateRepositoryClass = true): string
public function generateEntityClass(ClassNameDetails $entityClassDetails, bool $apiResource, bool $withPasswordUpgrade = false, bool $generateRepositoryClass = true, bool $broadcast = false): string
{
$repoClassDetails = $this->generator->createClassNameDetails(
$entityClassDetails->getRelativeName(),
Expand All @@ -50,6 +50,7 @@ public function generateEntityClass(ClassNameDetails $entityClassDetails, bool $
'repository_full_class_name' => $repoClassDetails->getFullName(),
'repository_class_name' => $repoClassDetails->getShortName(),
'api_resource' => $apiResource,
'broadcast' => $broadcast,
'should_escape_table_name' => $this->doctrineHelper->isKeyword($tableName),
'table_name' => $tableName,
]
Expand Down
39 changes: 38 additions & 1 deletion src/Maker/MakeEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\UX\Turbo\Attribute\Broadcast;

/**
* @author Javier Eguiluz <javier.eguiluz@gmail.com>
Expand Down Expand Up @@ -84,6 +85,7 @@ public function configureCommand(Command $command, InputConfiguration $inputConf
$command
->addArgument('name', InputArgument::OPTIONAL, sprintf('Class name of the entity to create or update (e.g. <fg=yellow>%s</>)', Str::asClassName(Str::getRandomTerm())))
->addOption('api-resource', 'a', InputOption::VALUE_NONE, 'Mark this class as an API Platform resource (expose a CRUD API for it)')
->addOption('broadcast', 'b', InputOption::VALUE_NONE, 'Add the ability to broadcast entity updates using Symfony UX Turbo?')
->addOption('regenerate', null, InputOption::VALUE_NONE, 'Instead of adding new fields, simply generate the methods (e.g. getter/setter) for existing fields')
->addOption('overwrite', null, InputOption::VALUE_NONE, 'Overwrite any existing getter/setter methods')
->setHelp(file_get_contents(__DIR__.'/../Resources/help/MakeEntity.txt'))
Expand Down Expand Up @@ -127,6 +129,18 @@ class_exists(ApiResource::class) &&

$input->setOption('api-resource', $value);
}

if (
!$input->getOption('broadcast') &&
class_exists(Broadcast::class) &&
!class_exists($this->generator->createClassNameDetails($value, 'Entity\\')->getFullName())
) {
$description = $command->getDefinition()->getOption('broadcast')->getDescription();
$question = new ConfirmationQuestion($description, false);
$value = $io->askQuestion($question);

$input->setOption('broadcast', $value);
}
}

public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator)
Expand All @@ -148,11 +162,27 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen

$classExists = class_exists($entityClassDetails->getFullName());
if (!$classExists) {
$broadcast = $input->getOption('broadcast');
$entityPath = $this->entityClassGenerator->generateEntityClass(
$entityClassDetails,
$input->getOption('api-resource')
$input->getOption('api-resource'),
false,
true,
$broadcast
);

if ($broadcast) {
$shortName = $entityClassDetails->getShortName();
$generator->generateTemplate(
sprintf('broadcast/%s.stream.html.twig', $shortName),
'doctrine/broadcast_twig_template.tpl.php',
[
'class_name' => Str::asSnakeCase($shortName),
'class_name_plural' => Str::asSnakeCase(Str::singularCamelCaseToPluralCamelCase($shortName)),
]
);
}

$generator->writeChanges();
}

Expand Down Expand Up @@ -280,6 +310,13 @@ public function configureDependencies(DependencyBuilder $dependencies, InputInte
);
}

if (null !== $input && $input->getOption('broadcast')) {
$dependencies->addClassDependency(
Broadcast::class,
'ux-turbo-mercure'
);
}

ORMDependencyBuilder::buildDependencies($dependencies);
}

Expand Down
5 changes: 5 additions & 0 deletions src/Resources/help/MakeEntity.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ automatically be available for this entity class:

<info>php %command.full_name% --api-resource</info>

Symfony can also broadcast all changes made to the entity to the client using Symfony
UX Turbo.

<info>php %command.full_name% --broadcast</info>

You can also generate all the getter/setter/adder/remover methods
for the properties of existing entities:

Expand Down
7 changes: 7 additions & 0 deletions src/Resources/skeleton/doctrine/Entity.tpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
<?php endif ?>
use <?= $repository_full_class_name ?>;
use Doctrine\ORM\Mapping as ORM;
<?php if ($broadcast): ?>use Symfony\UX\Turbo\Attribute\Broadcast;
<?php endif ?>

/**
<?php if ($api_resource && !$use_attributes): ?> * @ApiResource()
<?php endif ?>
<?php if ($broadcast && !$use_attributes): ?> * @Broadcast()
<?php endif ?>
* @ORM\Entity(repositoryClass=<?= $repository_class_name ?>::class)
<?php if ($should_escape_table_name): ?> * @ORM\Table(name="`<?= $table_name ?>`")
Expand All @@ -17,6 +21,9 @@
<?php if ($api_resource && $use_attributes): ?>
#[ApiResource]
<?php endif ?>
<?php if ($broadcast && $use_attributes): ?>
#[Broadcast]
<?php endif ?>
class <?= $class_name."\n" ?>
{
/**
Expand Down
22 changes: 22 additions & 0 deletions src/Resources/skeleton/doctrine/broadcast_twig_template.tpl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{# Learn how to use Turbo Streams: https://github.com/symfony/ux-turbo#broadcast-doctrine-entities-update #}
{% block create %}
<turbo-stream action="append" target="<?= $class_name_plural ?>">
<template>
<div id="{{ '<?= $class_name ?>_' ~ id }}">
#{{ id }} created
</div>
</template>
</turbo-stream>
{% endblock %}

{% block update %}
<turbo-stream action="update" target="<?= $class_name ?>_{{ id }}">
<template>
#{{ id }} updated
</template>
</turbo-stream>
{% endblock %}

{% block remove %}
<turbo-stream action="remove" target="<?= $class_name ?>_{{ id }}"></turbo-stream>
{% endblock %}
29 changes: 29 additions & 0 deletions tests/Maker/MakeEntityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -564,5 +564,34 @@ public function getTestDetails()
->configureDatabase()
->updateSchemaAfterCommand(),
];

yield 'entity_new_broadcast' => [MakerTestDetails::createTest(
$this->getMakerInstance(MakeEntity::class),
[
// entity class name
'User',
// Mark the entity as broadcasted
'y',
// add not additional fields
'',
])
->setRequiredPhpVersion(70200)
->addExtraDependencies('ux-turbo-mercure')
->setFixtureFilesPath(__DIR__.'/../fixtures/MakeEntity')
->configureDatabase()
->addReplacement(
'.env',
'https://127.0.0.1:8000/.well-known/mercure',
'http://127.0.0.1:1337/.well-known/mercure'
)
->updateSchemaAfterCommand()
->assert(function (string $output, string $directory) {
$this->assertFileExists($directory.'/src/Entity/User.php');

$content = file_get_contents($directory.'/src/Entity/User.php');
$this->assertStringContainsString('use Symfony\UX\Turbo\Attribute\Broadcast;', $content);
$this->assertStringContainsString(\PHP_VERSION_ID >= 80000 ? '#[Broadcast]' : '@Broadcast', $content);
}),
];
}
}

0 comments on commit 8580778

Please sign in to comment.