forked from samjarrett/FractalBundle
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
fd6130
committed
Feb 17, 2022
1 parent
2a1cb89
commit c989ab1
Showing
10 changed files
with
266 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,74 @@ | ||
League Fractal Symfony Bundle | ||
Fractal Bundle | ||
============================= | ||
|
||
This bundle provides integration of [league/fractal](https://github.com/thephpleague/fractal) for Symfony. In addition it allows you to use [transformers as a services](#using-transformers-as-services). | ||
|
||
**This is a fork version of [samjarrett/FractalBundle](https://github.com/samjarrett/FractalBundle).** | ||
|
||
## Getting Started | ||
|
||
First of all you need to add dependency to composer.json: | ||
Requirements: | ||
|
||
* PHP >= 7.4 | ||
* Symfony 4, 5 and 6 | ||
|
||
Install through composer: | ||
|
||
``` | ||
composer require samj/fractal-bundle | ||
composer require fd6130/fractal-bundle | ||
``` | ||
|
||
Then register bundle in `app/AppKernel.php`: | ||
If you are using symfony flex, it will automatic register the bundle for you. | ||
|
||
## Usage | ||
|
||
You can use command `php bin/console make:fractal-transformer` to create a transformer. | ||
|
||
Or, just create it by your own and place it in `src/Transformer`. | ||
|
||
```php | ||
public function registerBundles() | ||
{ | ||
return [ | ||
// ... | ||
new SamJ\FractalBundle\SamJFractalBundle(), | ||
]; | ||
class UserTransformer extends TransformerAbstract | ||
{ | ||
public function transform(User $user): array | ||
{ | ||
$data = [ | ||
'id' => $user->id(), | ||
'name' => $user->name(), | ||
]; | ||
|
||
return $data; | ||
} | ||
} | ||
``` | ||
|
||
Now we can write and use fractal transformers: | ||
$resource = new Collection($users, UserTransformer::class); | ||
|
||
$response = $manager->createData($resource)->toArray(); | ||
``` | ||
|
||
## Using Transformers as Services | ||
### Inject services to the transformers | ||
|
||
There are several cases when you need to pass some dependencies into transformer. The common one is [role/scope based results](https://github.com/thephpleague/fractal/issues/327) in transformers. For example you need to show `email` field only for administrators or owner of user profile: | ||
You can inject services to your transformer through constructor: | ||
|
||
```php | ||
class UserTransformer extends TransformerAbstract | ||
{ | ||
private $authorizationCheker; | ||
private $entityManager; | ||
|
||
public function __construct(AuthorizationChecker $authorizationCheker) | ||
public function __construct(EntityManagerInterface $entityManager) | ||
{ | ||
$this->authorizationCheker = $authorizationCheker; | ||
$this->entityManager = $entityManager; | ||
} | ||
|
||
public function transform(User $user) | ||
public function transform(User $user): array | ||
{ | ||
$data = [ | ||
'id' => $user->id(), | ||
'name' => $user->name(), | ||
]; | ||
|
||
if ($this->authorizationChecker->isGranted(UserVoter::SEE_EMAIL, $user)) { | ||
$data['email'] = $user->email(); | ||
} | ||
|
||
// $this->entityManager->getRepository(...) | ||
|
||
return $data; | ||
} | ||
} | ||
``` | ||
|
||
Then you could just register this class as service, and pass service ID as transformer. This bundle then will try to get it from container: | ||
|
||
```php | ||
$resource = new Collection($users, 'app.transformer.user'); | ||
``` | ||
|
||
This works in includes as well: | ||
|
||
```php | ||
public function includeFriends(User $user) | ||
{ | ||
return $this->collection($user->friends(), 'app.transformer.user'); | ||
} | ||
``` | ||
|
||
You could see example of how to use transformers in [sample application](tests/Fixtures) which is used in test suites. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
namespace Fd\FractalBundle\DependencyInjection\Compiler; | ||
|
||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; | ||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
use Symfony\Component\DependencyInjection\Definition; | ||
|
||
class TransformerPass implements CompilerPassInterface | ||
{ | ||
const TRANSFORMER_TAG = 'fd_fractal.transformer'; | ||
public function process(ContainerBuilder $container) | ||
{ | ||
$taggedServices = $container->findTaggedServiceIds(self::TRANSFORMER_TAG); | ||
|
||
foreach ($taggedServices as $id => $tags) { | ||
$definition = $container->findDefinition($id); | ||
$definition->setPublic(true); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
<?php | ||
|
||
namespace Fd\FractalBundle\Maker; | ||
|
||
use League\Fractal\TransformerAbstract; | ||
use Symfony\Bundle\MakerBundle\ConsoleStyle; | ||
use Symfony\Bundle\MakerBundle\DependencyBuilder; | ||
use Symfony\Bundle\MakerBundle\Doctrine\DoctrineHelper; | ||
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException; | ||
use Symfony\Bundle\MakerBundle\Generator; | ||
use Symfony\Bundle\MakerBundle\InputConfiguration; | ||
use Symfony\Bundle\MakerBundle\Maker\AbstractMaker; | ||
use Symfony\Bundle\MakerBundle\Str; | ||
use Symfony\Bundle\MakerBundle\Validator; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Input\InputOption; | ||
use Symfony\Component\Console\Question\Question; | ||
|
||
final class MakeFractalTransformer extends AbstractMaker | ||
{ | ||
use MakerTrait; | ||
|
||
private $doctrineHelper; | ||
|
||
public function __construct(DoctrineHelper $doctrineHelper) | ||
{ | ||
$this->doctrineHelper = $doctrineHelper; | ||
} | ||
|
||
public static function getCommandName(): string | ||
{ | ||
return 'make:fractal-transformer'; | ||
} | ||
|
||
public static function getCommandDescription(): string | ||
{ | ||
return 'Create a transformer class for transforming data.'; | ||
} | ||
|
||
public function configureCommand(Command $command, InputConfiguration $inputConf) | ||
{ | ||
$command | ||
->setDescription('Creates a new transformer class') | ||
->addArgument('entity-class', InputArgument::OPTIONAL, sprintf('The class name of the entity to create Transformer (e.g. <fg=yellow>%s</>)', Str::asClassName(Str::getRandomTerm()))) | ||
->addArgument('class-name', InputArgument::OPTIONAL, sprintf('The class name of new Transformer (e.g. <fg=yellow>%s</>)', Str::asClassName(Str::getRandomTerm()))) | ||
->addOption('no-entity', null, InputOption::VALUE_NONE, 'Use this option to generate a plank transformer') | ||
->setHelp(file_get_contents(__DIR__ . '/../Resources/help/MakeFractalTransformer.txt')); | ||
|
||
$inputConf->setArgumentAsNonInteractive('entity-class'); | ||
$inputConf->setArgumentAsNonInteractive('class-name'); | ||
} | ||
|
||
public function interact(InputInterface $input, ConsoleStyle $io, Command $command) | ||
{ | ||
if ($input->getOption('no-entity')) { | ||
$io->block([ | ||
'Note: You have choose to generate a blank Transformer.', | ||
], null, 'fg=yellow'); | ||
$classname = $io->ask(sprintf('The class name of new Transformer (e.g. <fg=yellow>%s</>)', Str::asClassName(Str::getRandomTerm())), null, [Validator::class, 'notBlank']); | ||
|
||
$input->setArgument('class-name', $classname); | ||
} | ||
else | ||
{ | ||
$argument = $command->getDefinition()->getArgument('entity-class'); | ||
$question = $this->createEntityClassQuestion($argument->getDescription()); | ||
$value = $io->askQuestion($question); | ||
|
||
$input->setArgument('entity-class', $value); | ||
} | ||
} | ||
|
||
public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator) | ||
{ | ||
$noEntity = $input->getOption('no-entity'); | ||
$classname = !$noEntity ? null : Str::asClassName($input->getArgument('class-name')); | ||
|
||
$entityClassDetails = !$noEntity ? $generator->createClassNameDetails( | ||
Validator::entityExists($input->getArgument('entity-class'), $this->doctrineHelper->getEntitiesForAutocomplete()), | ||
'Entity\\' | ||
) : null; | ||
|
||
$transformerClassDetails = !$noEntity ? $generator->createClassNameDetails( | ||
$entityClassDetails->getShortName(), | ||
'Transformer\\', | ||
'Transformer' | ||
) : $generator->createClassNameDetails($classname, 'Transformer\\', 'Transformer'); | ||
|
||
$generator->generateClass( | ||
$transformerClassDetails->getFullName(), | ||
__DIR__ . '/../Resources/skeleton/Transformer.tpl.php', | ||
[ | ||
'no_entity' => $noEntity, | ||
'entity_class_name' => $entityClassDetails ? $entityClassDetails->getShortName() : null, | ||
'entity_variable_name' => $entityClassDetails ? Str::asLowerCamelCase($entityClassDetails->getShortName()) : null, | ||
'entity_full_class_name' => $entityClassDetails ? $entityClassDetails->getFullName(): null, | ||
] | ||
); | ||
|
||
$generator->writeChanges(); | ||
|
||
$this->writeSuccessMessage($io); | ||
|
||
$io->text([ | ||
'Next: Open your new transformer class and start customizing it.', | ||
]); | ||
} | ||
|
||
public function configureDependencies(DependencyBuilder $dependencies) | ||
{ | ||
$dependencies->addClassDependency(TransformerAbstract::class, 'fd6130/fractal-bundle'); | ||
} | ||
|
||
private function createEntityClassQuestion(string $questionText): Question | ||
{ | ||
$question = new Question($questionText); | ||
$question->setValidator([Validator::class, 'notBlank']); | ||
$question->setAutocompleterValues($this->doctrineHelper->getEntitiesForAutocomplete()); | ||
|
||
return $question; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?php | ||
|
||
namespace Fd\FractalBundle\Maker; | ||
|
||
use Symfony\Bundle\MakerBundle\Validator; | ||
use Symfony\Component\Console\Question\Question; | ||
|
||
trait MakerTrait | ||
{ | ||
private function createEntityClassQuestion(string $questionText): Question | ||
{ | ||
$question = new Question($questionText); | ||
$question->setValidator([Validator::class, 'notBlank']); | ||
$question->setAutocompleterValues($this->doctrineHelper->getEntitiesForAutocomplete()); | ||
|
||
return $question; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,27 @@ | ||
<?php | ||
|
||
use Fd\FractalBundle\ContainerAwareManager; | ||
use Fd\FractalBundle\Maker\MakeFractalTransformer; | ||
use League\Fractal\Manager; | ||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; | ||
|
||
use function Symfony\Component\DependencyInjection\Loader\Configurator\service; | ||
|
||
return static function (ContainerConfigurator $container) { | ||
$container->services() | ||
$services = $container->services(); | ||
|
||
$services | ||
->set(ContainerAwareManager::class, ContainerAwareManager::class) | ||
->public() | ||
->call('setContainer', [service('service_container')]) | ||
->alias('fd_fractal.manager', ContainerAwareManager::class) | ||
->public() | ||
->alias(Manager::class, ContainerAwareManager::class) | ||
->public() | ||
|
||
; | ||
$services->set("maker.maker.make_fractal_transformer", MakeFractalTransformer::class) | ||
->args([service("maker.doctrine_helper")]) | ||
->tag("maker.command") | ||
; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
The <info>%command.name%</info> command generates a new transformer class. | ||
|
||
<info>php %command.full_name%</info> | ||
|
||
<info>php %command.full_name% --no-entity</info> | ||
|
||
Arguments are optional. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?= "<?php\n" ?> | ||
|
||
namespace <?= $namespace; ?>; | ||
|
||
use League\Fractal\TransformerAbstract; | ||
<?php if(!$no_entity): ?>use <?= $entity_full_class_name. ";\n"?><?php endif ?> | ||
use League\Fractal\Resource\Collection; | ||
use League\Fractal\Resource\Item; | ||
|
||
class <?= $class_name ?> extends TransformerAbstract | ||
{ | ||
/** | ||
* List of resources possible to include | ||
* | ||
* @var array | ||
*/ | ||
protected $availableIncludes = []; | ||
|
||
/** | ||
* List of resources to automatically include | ||
* | ||
* @var array | ||
*/ | ||
protected $defaultIncludes = []; | ||
|
||
public function transform(<?php if(!$no_entity):?><?= $entity_class_name ?> $entity<?php else:?>$entity<?php endif ?>): array | ||
{ | ||
return []; | ||
} | ||
} |