Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The impact of API Platform on Open-Source

The impact of API Platform on Open-Source

From API Con 2023

Loïc Frémont

September 23, 2023
Tweet

More Decks by Loïc Frémont

Other Decks in Programming

Transcript

  1. 1. The impact of API Platform on Open-Source 2. Akawaka

    3. What is Monofony and Why use it? 4. New Sylius Resource System 5. Sylius Resource without driver 6. What’s next?
  2. Akawaka Experts for your web projects We help you design

    and improve your projects: We use clean architecture techniques via DDD methodologies for projects that stand the test of time,
  3. Akawaka Experts for your web projects We help you design

    and improve your projects: We use clean architecture techniques via DDD methodologies for projects that stand the test of time, A true quality approach through testing,
  4. Akawaka Experts for your web projects We help you design

    and improve your projects: We use clean architecture techniques via DDD methodologies for projects that stand the test of time, A true quality approach through testing, Efficient industrialization adapted to your projects,
  5. Akawaka Experts for your web projects We help you design

    and improve your projects: We use clean architecture techniques via DDD methodologies for projects that stand the test of time, A true quality approach through testing, Efficient industrialization adapted to your projects, On a contract or fixed-price basis, to create and/or integrate teams and work in complete collaboration.
  6. What is Monofony and Why use it? Bootstrapping a modern

    application on top of Symfony Leveraging Sylius bundles and components
  7. What is Monofony and Why use it? Bootstrapping a modern

    application on top of Symfony Leveraging Sylius bundles and components Helping you to focus more on what truly matters to your use-case
  8. Monofony API Pack voir l’installation détaillée dans la doc. $

    composer require monofony/api-pack "^0.10"
  9. New Sylius Resource System API Platform for the inspiration Akawaka

    & Commerce Weavers for sponsoring that development Łukasz Chruściel at Commerce Weavers for the code reviews We can thank:
  10. Use the Resource attribute PHP attribute #[Resource] configures your entity

    as a Sylius resource. ` ` namespace App\Entity; use App\Repository\BookRepository; use Doctrine\ORM\Mapping as ORM; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[ORM\Entity(repositoryClass: BookRepository::class)] #[Resource] class Book implements ResourceInterface { }
  11. Use the Resource attribute PHP attribute #[Resource] configures your entity

    as a Sylius resource. ` ` #[Resource] namespace App\Entity; use App\Repository\BookRepository; use Doctrine\ORM\Mapping as ORM; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[ORM\Entity(repositoryClass: BookRepository::class)] class Book implements ResourceInterface { }
  12. Use the Resource attribute PHP attribute #[Resource] configures your entity

    as a Sylius resource. ` ` use Sylius\Component\Resource\Metadata\Resource; #[Resource] namespace App\Entity; use App\Repository\BookRepository; use Doctrine\ORM\Mapping as ORM; use Sylius\Component\Resource\Model\ResourceInterface; #[ORM\Entity(repositoryClass: BookRepository::class)] class Book implements ResourceInterface { }
  13. Browsing books We’ll use Index operation which allows to browse

    all items of your resource. ` ` namespace App\Entity; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource] #[Index] class Book implements ResourceInterface { }
  14. Browsing books We’ll use Index operation which allows to browse

    all items of your resource. ` ` #[Index] namespace App\Entity; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource] class Book implements ResourceInterface { }
  15. Browsing books We’ll use Index operation which allows to browse

    all items of your resource. ` ` use Sylius\Component\Resource\Metadata\Index; #[Index] namespace App\Entity; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource] class Book implements ResourceInterface { }
  16. Route It will configure this route for your index operation.

    Name Method Path app_book_index GET /books ` `
  17. final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { public static

    function getName(): string { return 'app_book'; } public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ; }
  18. final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { public static

    function getName(): string { return 'app_book'; } public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ; }
  19. public static function getName(): string { return 'app_book'; } final

    class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ; }
  20. ->orderBy('name', 'asc') final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface {

    public static function getName(): string { return 'app_book'; } public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ; }
  21. ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) final class BookGrid extends AbstractGrid

    implements ResourceAwareGridInterface { public static function getName(): string { return 'app_book'; } public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->orderBy('name', 'asc') ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ; }
  22. ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) final class BookGrid extends AbstractGrid

    implements ResourceAwareGridInterface { public static function getName(): string { return 'app_book'; } public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) ; }
  23. Use this grid for your index operation To use a

    grid for you operation, you need to install the Sylius grid package
  24. Use this grid for your index operation To use a

    grid for you operation, you need to install the Sylius grid package namespace App\Entity; use App\Grid\BookGrid; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource] // You can use either the FQCN of your grid #[Index(grid: BookGrid::class)] // Or you can use the grid name #[Index(grid: 'app_book')] class Book implements ResourceInterface { }
  25. Use this grid for your index operation To use a

    grid for you operation, you need to install the Sylius grid package // You can use either the FQCN of your grid #[Index(grid: BookGrid::class)] namespace App\Entity; use App\Grid\BookGrid; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource] // Or you can use the grid name #[Index(grid: 'app_book')] class Book implements ResourceInterface { }
  26. Use this grid for your index operation To use a

    grid for you operation, you need to install the Sylius grid package use App\Grid\BookGrid; // You can use either the FQCN of your grid #[Index(grid: BookGrid::class)] namespace App\Entity; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource] // Or you can use the grid name #[Index(grid: 'app_book')] class Book implements ResourceInterface { }
  27. Use this grid for your index operation To use a

    grid for you operation, you need to install the Sylius grid package // Or you can use the grid name #[Index(grid: 'app_book')] namespace App\Entity; use App\Grid\BookGrid; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource] // You can use either the FQCN of your grid #[Index(grid: BookGrid::class)] class Book implements ResourceInterface { }
  28. Use this grid for your index operation To use a

    grid for you operation, you need to install the Sylius grid package // Or you can use the grid name #[Index(grid: 'app_book')] namespace App\Entity; use App\Grid\BookGrid; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource] // You can use either the FQCN of your grid #[Index(grid: BookGrid::class)] class Book implements ResourceInterface { }
  29. Adding books We’ll use Create operation which allows to add

    a new item of your resource. ` ` namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Create] #[Index] class Book implements ResourceInterface { }
  30. Adding books We’ll use Create operation which allows to add

    a new item of your resource. ` ` #[Resource(formType: BookType::class)] namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Create] #[Index] class Book implements ResourceInterface { }
  31. Adding books We’ll use Create operation which allows to add

    a new item of your resource. ` ` use App\Form\BookType; #[Resource(formType: BookType::class)] namespace App\Entity; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Create] #[Index] class Book implements ResourceInterface { }
  32. Adding books We’ll use Create operation which allows to add

    a new item of your resource. ` ` #[Create] namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Index] class Book implements ResourceInterface { }
  33. Adding books We’ll use Create operation which allows to add

    a new item of your resource. ` ` use Sylius\Component\Resource\Metadata\Create; #[Create] namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Index] class Book implements ResourceInterface { }
  34. Route It will configure this route for your create operation.

    Name Method Path app_book_create GET, POST /books/new ` `
  35. final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...]

    public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) ; }
  36. ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) final class BookGrid extends AbstractGrid

    implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ; }
  37. ->addActionGroup( final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) MainActionGroup::create( CreateAction::create(), ) ) ; }
  38. MainActionGroup::create( final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ->addActionGroup( CreateAction::create(), ) ) ; }
  39. CreateAction::create(), final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('sylius.ui.name') ->setSortable(true) ) ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ->addActionGroup( MainActionGroup::create( ) ) ; }
  40. Editing books We’ll use Update operation which allows to edit

    an existing item of your resource. ` ` namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Create] #[Update] #[Index] class Book implements ResourceInterface { }
  41. Editing books We’ll use Update operation which allows to edit

    an existing item of your resource. ` ` #[Update] namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Create] #[Index] class Book implements ResourceInterface { }
  42. Editing books We’ll use Update operation which allows to edit

    an existing item of your resource. ` ` use Sylius\Component\Resource\Metadata\Update; #[Update] namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Create] #[Index] class Book implements ResourceInterface { }
  43. Route It will configure this route for your update operation.

    Name Method Path app_book_update GET, PUT, PATCH, POST /books/{id}/edit ` `
  44. final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...]

    public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), ) ) ; } public function getResourceClass(): string { return Book::class; } }
  45. ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), ) ) final class BookGrid extends AbstractGrid

    implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) ; } public function getResourceClass(): string { return Book::class; } }
  46. ->addActionGroup( final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) ItemActionGroup::create( UpdateAction::create(), ) ) ; } public function getResourceClass(): string { return Book::class; } }
  47. ItemActionGroup::create( final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) ->addActionGroup( UpdateAction::create(), ) ) ; } public function getResourceClass(): string { return Book::class; } }
  48. UpdateAction::create(), final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) ->addActionGroup( ItemActionGroup::create( ) ) ; } public function getResourceClass(): string { return Book::class; } }
  49. Removing books We’ll use Delete operation which allows to remove

    an existing item of your resource. ` ` namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Delete; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Create] #[Update] #[Delete] #[Index] class Book implements ResourceInterface { }
  50. Removing books We’ll use Delete operation which allows to remove

    an existing item of your resource. ` ` #[Delete] namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Delete; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Create] #[Update] #[Index] class Book implements ResourceInterface { }
  51. Removing books We’ll use Delete operation which allows to remove

    an existing item of your resource. ` ` use Sylius\Component\Resource\Metadata\Delete; #[Delete] namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Create] #[Update] #[Index] class Book implements ResourceInterface { }
  52. Route It will configure this route for your delete operation.

    Name Method Path app_book_delete DELETE, POST /books/{id}/delete ` `
  53. final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...]

    public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), DeleteAction::create(), ) ) ; } public function getResourceClass(): string { return Book::class; }
  54. ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), DeleteAction::create(), ) ) final class BookGrid extends

    AbstractGrid implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) ; } public function getResourceClass(): string { return Book::class; }
  55. UpdateAction::create(), final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) ->addActionGroup( ItemActionGroup::create( DeleteAction::create(), ) ) ; } public function getResourceClass(): string { return Book::class; }
  56. DeleteAction::create(), final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( MainActionGroup::create( CreateAction::create(), ) ) ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), ) ) ; } public function getResourceClass(): string { return Book::class; }
  57. Removing many books We’ll use Bulk Delete operation which allows

    to remove several items of your resource at the same time. ` `
  58. Removing many books We’ll use Bulk Delete operation which allows

    to remove several items of your resource at the same time. ` ` namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\BulkDelete; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Delete; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Create] #[Update] #[BulkDelete] #[Delete] #[Index] class Book implements ResourceInterface { }
  59. Removing many books We’ll use Bulk Delete operation which allows

    to remove several items of your resource at the same time. ` ` #[BulkDelete] namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\BulkDelete; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Delete; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Create] #[Update] #[Delete] #[Index] class Book implements ResourceInterface { }
  60. Removing many books We’ll use Bulk Delete operation which allows

    to remove several items of your resource at the same time. ` ` use Sylius\Component\Resource\Metadata\BulkDelete; #[BulkDelete] namespace App\Entity; use App\Form\BookType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; use Sylius\Component\Resource\Metadata\Delete; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; #[Resource(formType: BookType::class)] #[Create] #[Update] #[Delete] #[Index] class Book implements ResourceInterface { }
  61. Route It will configure this route for your bulk_delete operation.

    Name Method Path app_book_bulk_delete DELETE, POST /books/bulk_delete ` `
  62. final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...]

    public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), DeleteAction::create(), ) ) ->addActionGroup( BulkActionGroup::create( DeleteAction::create() ) ) ; } public function getResourceClass(): string { return Book::class; }
  63. ->addActionGroup( BulkActionGroup::create( DeleteAction::create() ) ) final class BookGrid extends AbstractGrid

    implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), DeleteAction::create(), ) ) ; } public function getResourceClass(): string { return Book::class; }
  64. ->addActionGroup( final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), DeleteAction::create(), ) ) BulkActionGroup::create( DeleteAction::create() ) ) ; } public function getResourceClass(): string { return Book::class; }
  65. BulkActionGroup::create( final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), DeleteAction::create(), ) ) ->addActionGroup( DeleteAction::create() ) ) ; } public function getResourceClass(): string { return Book::class; }
  66. DeleteAction::create() final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), DeleteAction::create(), ) ) ->addActionGroup( BulkActionGroup::create( ) ) ; } public function getResourceClass(): string { return Book::class; }
  67. Publishing books We’ll use apply_state_machine_transition operation which allows to apply

    a transition using a state machine. ` ` namespace App\Entity; use Sylius\Component\Resource\Metadata\ApplyStateMachineTransition; use Sylius\Component\Resource\Model\ResourceInterface; // [...] #[ApplyStateMachineTransition(stateMachineTransition: 'publish')] class Book implements ResourceInterface { }
  68. Publishing books We’ll use apply_state_machine_transition operation which allows to apply

    a transition using a state machine. ` ` #[ApplyStateMachineTransition(stateMachineTransition: 'publish')] namespace App\Entity; use Sylius\Component\Resource\Metadata\ApplyStateMachineTransition; use Sylius\Component\Resource\Model\ResourceInterface; // [...] class Book implements ResourceInterface { }
  69. Publishing books We’ll use apply_state_machine_transition operation which allows to apply

    a transition using a state machine. ` ` use Sylius\Component\Resource\Metadata\ApplyStateMachineTransition; #[ApplyStateMachineTransition(stateMachineTransition: 'publish')] namespace App\Entity; use Sylius\Component\Resource\Model\ResourceInterface; // [...] class Book implements ResourceInterface { }
  70. Route It will configure this route for your apply_state_machine_transition operation.

    Name Method Path app_book_publish PUT, PATCH, POST /books/{id}/publish ` `
  71. final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...]

    public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ->addField( TwigField::create('state', '@SyliusUi/Grid/Field/state.html.twig') ->setLabel('sylius.ui.state') ->setOption('vars', ['labels' => 'admin/book/label/state']), ) ; } public function getResourceClass(): string { return Book::class; } }
  72. ->addField( TwigField::create('state', '@SyliusUi/Grid/Field/state.html.twig') ->setLabel('sylius.ui.state') ->setOption('vars', ['labels' => 'admin/book/label/state']), ) ;

    final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) } public function getResourceClass(): string { return Book::class; } }
  73. TwigField::create('state', '@SyliusUi/Grid/Field/state.html.twig') final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface {

    // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ->addField( ->setLabel('sylius.ui.state') ->setOption('vars', ['labels' => 'admin/book/label/state']), ) ; } public function getResourceClass(): string { return Book::class; } }
  74. ->setLabel('sylius.ui.state') final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ->addField( TwigField::create('state', '@SyliusUi/Grid/Field/state.html.twig') ->setOption('vars', ['labels' => 'admin/book/label/state']), ) ; } public function getResourceClass(): string { return Book::class; } }
  75. ->setOption('vars', ['labels' => 'admin/book/label/state']), final class BookGrid extends AbstractGrid implements

    ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addField( StringField::create('author') ->setLabel('sylius.ui.author') ->setSortable(true) ) ->addField( TwigField::create('state', '@SyliusUi/Grid/Field/state.html.twig') ->setLabel('sylius.ui.state') ) ; } public function getResourceClass(): string { return Book::class; } }
  76. final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...]

    public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), ApplyTransitionAction::create( name: 'publish', route: 'app_admin_book_publish', routeParameters: ['id' => 'resource.id'], options: [ 'class' => 'green', ], ) ->setLabel('app.ui.publish') ->setIcon('checkmark'), DeleteAction::create(), ) ) ; }
  77. ApplyTransitionAction::create( name: 'publish', route: 'app_admin_book_publish', routeParameters: ['id' => 'resource.id'], options:

    [ 'class' => 'green', ], ) ->setLabel('app.ui.publish') ->setIcon('checkmark'), final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), DeleteAction::create(), ) ) ; }
  78. ApplyTransitionAction::create( final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), name: 'publish', route: 'app_admin_book_publish', routeParameters: ['id' => 'resource.id'], options: [ 'class' => 'green', ], ) ->setLabel('app.ui.publish') ->setIcon('checkmark'), DeleteAction::create(), ) ) ; }
  79. name: 'publish', final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface {

    // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), ApplyTransitionAction::create( route: 'app_admin_book_publish', routeParameters: ['id' => 'resource.id'], options: [ 'class' => 'green', ], ) ->setLabel('app.ui.publish') ->setIcon('checkmark'), DeleteAction::create(), ) ) ; }
  80. route: 'app_admin_book_publish', final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface {

    // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), ApplyTransitionAction::create( name: 'publish', routeParameters: ['id' => 'resource.id'], options: [ 'class' => 'green', ], ) ->setLabel('app.ui.publish') ->setIcon('checkmark'), DeleteAction::create(), ) ) ; }
  81. routeParameters: ['id' => 'resource.id'], final class BookGrid extends AbstractGrid implements

    ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), ApplyTransitionAction::create( name: 'publish', route: 'app_admin_book_publish', options: [ 'class' => 'green', ], ) ->setLabel('app.ui.publish') ->setIcon('checkmark'), DeleteAction::create(), ) ) ; }
  82. options: [ 'class' => 'green', ], final class BookGrid extends

    AbstractGrid implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), ApplyTransitionAction::create( name: 'publish', route: 'app_admin_book_publish', routeParameters: ['id' => 'resource.id'], ) ->setLabel('app.ui.publish') ->setIcon('checkmark'), DeleteAction::create(), ) ) ; }
  83. ->setLabel('app.ui.publish') final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), ApplyTransitionAction::create( name: 'publish', route: 'app_admin_book_publish', routeParameters: ['id' => 'resource.id'], options: [ 'class' => 'green', ], ) ->setIcon('checkmark'), DeleteAction::create(), ) ) ; }
  84. ->setIcon('checkmark'), final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { //

    [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( ItemActionGroup::create( UpdateAction::create(), ApplyTransitionAction::create( name: 'publish', route: 'app_admin_book_publish', routeParameters: ['id' => 'resource.id'], options: [ 'class' => 'green', ], ) ->setLabel('app.ui.publish') DeleteAction::create(), ) ) ; }
  85. Publishing books with custom processor We configure an update operation.

    ` ` namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; // [...] #[Update( methods: ['PUT', 'PATCH', 'POST'], shortName: 'publish', processor: PublishBookProcessor::class, validate: false, )] class Book implements ResourceInterface { }
  86. Publishing books with custom processor We configure an update operation.

    ` ` #[Update( methods: ['PUT', 'PATCH', 'POST'], shortName: 'publish', processor: PublishBookProcessor::class, validate: false, )] namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; // [...] class Book implements ResourceInterface { }
  87. Publishing books with custom processor We configure an update operation.

    ` ` use Sylius\Component\Resource\Metadata\Update; #[Update( methods: ['PUT', 'PATCH', 'POST'], shortName: 'publish', processor: PublishBookProcessor::class, validate: false, )] namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Model\ResourceInterface; // [...] class Book implements ResourceInterface { }
  88. Publishing books with custom processor We configure an update operation.

    ` ` methods: ['PUT', 'PATCH', 'POST'], namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; // [...] #[Update( shortName: 'publish', processor: PublishBookProcessor::class, validate: false, )] class Book implements ResourceInterface { }
  89. Publishing books with custom processor We configure an update operation.

    ` ` shortName: 'publish', namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; // [...] #[Update( methods: ['PUT', 'PATCH', 'POST'], processor: PublishBookProcessor::class, validate: false, )] class Book implements ResourceInterface { }
  90. Publishing books with custom processor We configure an update operation.

    ` ` processor: PublishBookProcessor::class, namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; // [...] #[Update( methods: ['PUT', 'PATCH', 'POST'], shortName: 'publish', validate: false, )] class Book implements ResourceInterface { }
  91. Publishing books with custom processor We configure an update operation.

    ` ` use App\State\Processor\PublishBookProcessor; processor: PublishBookProcessor::class, namespace App\Entity; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; // [...] #[Update( methods: ['PUT', 'PATCH', 'POST'], shortName: 'publish', validate: false, )] class Book implements ResourceInterface { }
  92. Publishing books with custom processor We configure an update operation.

    ` ` validate: false, namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\Update; use Sylius\Component\Resource\Model\ResourceInterface; // [...] #[Update( methods: ['PUT', 'PATCH', 'POST'], shortName: 'publish', processor: PublishBookProcessor::class, )] class Book implements ResourceInterface { }
  93. Route It will configure this route for your publish operation.

    Name Method Path app_book_publish PUT, PATCH, POST /books/{id}/publish ` `
  94. // src/State/Processor/PublishBookProcessor.php use Sylius\Component\Resource\Context\Context; use Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor; use Sylius\Component\Resource\Metadata\Operation; use Sylius\Component\Resource\State\ProcessorInterface;

    use Symfony\Component\Workflow\WorkflowInterface; final class PublishBookProcessor implements ProcessorInterface { public function __construct( private readonly WorkflowInterface $bookPublishingStateMachine, private readonly PersistProcessor $persistProcessor, ) { } public function process(mixed $data, Operation $operation, Context $context): mixed { if ($this->bookPublishingStateMachine->can($data, 'publish')) { $this->bookPublishingStateMachine->apply($data, 'publish'); } return $this->persistProcessor->process($data, $operation, $context); } }
  95. final class PublishBookProcessor implements ProcessorInterface // src/State/Processor/PublishBookProcessor.php use Sylius\Component\Resource\Context\Context; use

    Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor; use Sylius\Component\Resource\Metadata\Operation; use Sylius\Component\Resource\State\ProcessorInterface; use Symfony\Component\Workflow\WorkflowInterface; { public function __construct( private readonly WorkflowInterface $bookPublishingStateMachine, private readonly PersistProcessor $persistProcessor, ) { } public function process(mixed $data, Operation $operation, Context $context): mixed { if ($this->bookPublishingStateMachine->can($data, 'publish')) { $this->bookPublishingStateMachine->apply($data, 'publish'); } return $this->persistProcessor->process($data, $operation, $context); } }
  96. use Sylius\Component\Resource\State\ProcessorInterface; final class PublishBookProcessor implements ProcessorInterface // src/State/Processor/PublishBookProcessor.php use

    Sylius\Component\Resource\Context\Context; use Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor; use Sylius\Component\Resource\Metadata\Operation; use Symfony\Component\Workflow\WorkflowInterface; { public function __construct( private readonly WorkflowInterface $bookPublishingStateMachine, private readonly PersistProcessor $persistProcessor, ) { } public function process(mixed $data, Operation $operation, Context $context): mixed { if ($this->bookPublishingStateMachine->can($data, 'publish')) { $this->bookPublishingStateMachine->apply($data, 'publish'); } return $this->persistProcessor->process($data, $operation, $context); } }
  97. private readonly WorkflowInterface $bookPublishingStateMachine, // src/State/Processor/PublishBookProcessor.php use Sylius\Component\Resource\Context\Context; use Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor;

    use Sylius\Component\Resource\Metadata\Operation; use Sylius\Component\Resource\State\ProcessorInterface; use Symfony\Component\Workflow\WorkflowInterface; final class PublishBookProcessor implements ProcessorInterface { public function __construct( private readonly PersistProcessor $persistProcessor, ) { } public function process(mixed $data, Operation $operation, Context $context): mixed { if ($this->bookPublishingStateMachine->can($data, 'publish')) { $this->bookPublishingStateMachine->apply($data, 'publish'); } return $this->persistProcessor->process($data, $operation, $context); } }
  98. use Symfony\Component\Workflow\WorkflowInterface; private readonly WorkflowInterface $bookPublishingStateMachine, // src/State/Processor/PublishBookProcessor.php use Sylius\Component\Resource\Context\Context;

    use Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor; use Sylius\Component\Resource\Metadata\Operation; use Sylius\Component\Resource\State\ProcessorInterface; final class PublishBookProcessor implements ProcessorInterface { public function __construct( private readonly PersistProcessor $persistProcessor, ) { } public function process(mixed $data, Operation $operation, Context $context): mixed { if ($this->bookPublishingStateMachine->can($data, 'publish')) { $this->bookPublishingStateMachine->apply($data, 'publish'); } return $this->persistProcessor->process($data, $operation, $context); } }
  99. private readonly PersistProcessor $persistProcessor, // src/State/Processor/PublishBookProcessor.php use Sylius\Component\Resource\Context\Context; use Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor;

    use Sylius\Component\Resource\Metadata\Operation; use Sylius\Component\Resource\State\ProcessorInterface; use Symfony\Component\Workflow\WorkflowInterface; final class PublishBookProcessor implements ProcessorInterface { public function __construct( private readonly WorkflowInterface $bookPublishingStateMachine, ) { } public function process(mixed $data, Operation $operation, Context $context): mixed { if ($this->bookPublishingStateMachine->can($data, 'publish')) { $this->bookPublishingStateMachine->apply($data, 'publish'); } return $this->persistProcessor->process($data, $operation, $context); } }
  100. use Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor; private readonly PersistProcessor $persistProcessor, // src/State/Processor/PublishBookProcessor.php use Sylius\Component\Resource\Context\Context;

    use Sylius\Component\Resource\Metadata\Operation; use Sylius\Component\Resource\State\ProcessorInterface; use Symfony\Component\Workflow\WorkflowInterface; final class PublishBookProcessor implements ProcessorInterface { public function __construct( private readonly WorkflowInterface $bookPublishingStateMachine, ) { } public function process(mixed $data, Operation $operation, Context $context): mixed { if ($this->bookPublishingStateMachine->can($data, 'publish')) { $this->bookPublishingStateMachine->apply($data, 'publish'); } return $this->persistProcessor->process($data, $operation, $context); } }
  101. public function process(mixed $data, Operation $operation, Context $context): mixed //

    src/State/Processor/PublishBookProcessor.php use Sylius\Component\Resource\Context\Context; use Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor; use Sylius\Component\Resource\Metadata\Operation; use Sylius\Component\Resource\State\ProcessorInterface; use Symfony\Component\Workflow\WorkflowInterface; final class PublishBookProcessor implements ProcessorInterface { public function __construct( private readonly WorkflowInterface $bookPublishingStateMachine, private readonly PersistProcessor $persistProcessor, ) { } { if ($this->bookPublishingStateMachine->can($data, 'publish')) { $this->bookPublishingStateMachine->apply($data, 'publish'); } return $this->persistProcessor->process($data, $operation, $context); } }
  102. if ($this->bookPublishingStateMachine->can($data, 'publish')) { // src/State/Processor/PublishBookProcessor.php use Sylius\Component\Resource\Context\Context; use Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor;

    use Sylius\Component\Resource\Metadata\Operation; use Sylius\Component\Resource\State\ProcessorInterface; use Symfony\Component\Workflow\WorkflowInterface; final class PublishBookProcessor implements ProcessorInterface { public function __construct( private readonly WorkflowInterface $bookPublishingStateMachine, private readonly PersistProcessor $persistProcessor, ) { } public function process(mixed $data, Operation $operation, Context $context): mixed { $this->bookPublishingStateMachine->apply($data, 'publish'); } return $this->persistProcessor->process($data, $operation, $context); } }
  103. $this->bookPublishingStateMachine->apply($data, 'publish'); // src/State/Processor/PublishBookProcessor.php use Sylius\Component\Resource\Context\Context; use Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor; use Sylius\Component\Resource\Metadata\Operation;

    use Sylius\Component\Resource\State\ProcessorInterface; use Symfony\Component\Workflow\WorkflowInterface; final class PublishBookProcessor implements ProcessorInterface { public function __construct( private readonly WorkflowInterface $bookPublishingStateMachine, private readonly PersistProcessor $persistProcessor, ) { } public function process(mixed $data, Operation $operation, Context $context): mixed { if ($this->bookPublishingStateMachine->can($data, 'publish')) { } return $this->persistProcessor->process($data, $operation, $context); } }
  104. return $this->persistProcessor->process($data, $operation, $context); // src/State/Processor/PublishBookProcessor.php use Sylius\Component\Resource\Context\Context; use Sylius\Component\Resource\Doctrine\Common\State\PersistProcessor;

    use Sylius\Component\Resource\Metadata\Operation; use Sylius\Component\Resource\State\ProcessorInterface; use Symfony\Component\Workflow\WorkflowInterface; final class PublishBookProcessor implements ProcessorInterface { public function __construct( private readonly WorkflowInterface $bookPublishingStateMachine, private readonly PersistProcessor $persistProcessor, ) { } public function process(mixed $data, Operation $operation, Context $context): mixed { if ($this->bookPublishingStateMachine->can($data, 'publish')) { $this->bookPublishingStateMachine->apply($data, 'publish'); } } }
  105. Publishing many books We’ll use Bulk Update operation which allows

    to update several items of your resource at the same time. ` `
  106. Publishing many books We’ll use Bulk Update operation which allows

    to update several items of your resource at the same time. ` ` namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\BulkUpdate; // [...] #[BulkUpdate( shortName: 'bulk_publish', processor: PublishBookProcessor::class, validate: false, )] class Book implements ResourceInterface { }
  107. Publishing many books We’ll use Bulk Update operation which allows

    to update several items of your resource at the same time. ` ` #[BulkUpdate( namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\BulkUpdate; // [...] shortName: 'bulk_publish', processor: PublishBookProcessor::class, validate: false, )] class Book implements ResourceInterface { }
  108. Publishing many books We’ll use Bulk Update operation which allows

    to update several items of your resource at the same time. ` ` use Sylius\Component\Resource\Metadata\BulkUpdate; #[BulkUpdate( namespace App\Entity; use App\State\Processor\PublishBookProcessor; // [...] shortName: 'bulk_publish', processor: PublishBookProcessor::class, validate: false, )] class Book implements ResourceInterface { }
  109. Publishing many books We’ll use Bulk Update operation which allows

    to update several items of your resource at the same time. ` ` shortName: 'bulk_publish', namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\BulkUpdate; // [...] #[BulkUpdate( processor: PublishBookProcessor::class, validate: false, )] class Book implements ResourceInterface { }
  110. Publishing many books We’ll use Bulk Update operation which allows

    to update several items of your resource at the same time. ` ` processor: PublishBookProcessor::class, namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\BulkUpdate; // [...] #[BulkUpdate( shortName: 'bulk_publish', validate: false, )] class Book implements ResourceInterface { }
  111. Publishing many books We’ll use Bulk Update operation which allows

    to update several items of your resource at the same time. ` ` validate: false, namespace App\Entity; use App\State\Processor\PublishBookProcessor; use Sylius\Component\Resource\Metadata\BulkUpdate; // [...] #[BulkUpdate( shortName: 'bulk_publish', processor: PublishBookProcessor::class, )] class Book implements ResourceInterface { }
  112. Route It will configure this route for your bulk_publish operation.

    Name Method Path app_book_bulk_publish PUT, PATCH, POST /books/bulk_publish ` `
  113. final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...]

    public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( BulkActionGroup::create( DeleteAction::create(), Action::create('publish', 'apply_transition') ->setLabel('app.ui.publish') ->setIcon('icon: checkmark') ->setOptions([ 'link' => [ 'route' => 'app_admin_book_bulk_publish', ], 'class' => 'green', ]), ) ) ; } public function getResourceClass(): string
  114. Action::create('publish', 'apply_transition') ->setLabel('app.ui.publish') ->setIcon('icon: checkmark') ->setOptions([ 'link' => [ 'route'

    => 'app_admin_book_bulk_publish', ], 'class' => 'green', ]), ) ) ; } final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( BulkActionGroup::create( DeleteAction::create(), public function getResourceClass(): string
  115. Action::create('publish', 'apply_transition') final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface {

    // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( BulkActionGroup::create( DeleteAction::create(), ->setLabel('app.ui.publish') ->setIcon('icon: checkmark') ->setOptions([ 'link' => [ 'route' => 'app_admin_book_bulk_publish', ], 'class' => 'green', ]), ) ) ; } public function getResourceClass(): string
  116. ->setOptions([ 'link' => [ 'route' => 'app_admin_book_bulk_publish', ], 'class' =>

    'green', ]), ) final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( BulkActionGroup::create( DeleteAction::create(), Action::create('publish', 'apply_transition') ->setLabel('app.ui.publish') ->setIcon('icon: checkmark') ) ; } public function getResourceClass(): string
  117. 'link' => [ 'route' => 'app_admin_book_bulk_publish', ], final class BookGrid

    extends AbstractGrid implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder // [...] ->addActionGroup( BulkActionGroup::create( DeleteAction::create(), Action::create('publish', 'apply_transition') ->setLabel('app.ui.publish') ->setIcon('icon: checkmark') ->setOptions([ 'class' => 'green', ]), ) ) ; } public function getResourceClass(): string
  118. Resource with data from a CSV file config/data/board_games.csv 6b2fff2b-0b43-489b-8c48-9c0427a1c4c7,Stone Age,"Travel

    to the time of hunters and gatherers in this classic game of tool d068029a-0c32-4728-95bf-5f614d53440b,Ticket to Ride,"Build your railroad across North America to connect cities and comp 5ba27cbd-e230-48b7-86ae-ad2eaa05ebc0,7 Wonders,"Draft cards to develop your ancient civilization and build its Wonder of 2919785a-66e7-44da-b356-b98e07fbb9e8,Puerto Rico,"Ship goods, construct buildings, and choose roles that benefit you mor c4856c93-3a41-40eb-9994-f58a1035d99b,Azul, "Artfully embellish the walls of your palace by drafting the most beautiful t a953d760-07d5-4add-b87e-b483ebb194df,Die Fürsten von Florenz,"Attract artisans and scholars to your palazzo by building ce461300-25c3-4a72-aa7d-6ec7021d7b80,The Voyages of Marco Polo,"Using unique abilities, fulfill contracts and reach your 599dcd98-8167-4f4a-b181-efd7c24bb434,Tigris & Euphrates,"Keep your Mesopotamian civilisation in perfect balance through 305749e6-7a05-468a-b1aa-46ee6c1a89ac,Patchwork,"Piece together a quilt and leave no holes to become the button master." 5e980dad-d8ef-4e47-910a-4dc9f91b38fd,Cartagena,"Groups of pirates race to reach their ship and escape from Cartegena." 6a47110b-b65d-4e94-9ce0-a06cd7823ecc,Village,"Send your villagers to work, travel, pray, and... die when it brings the m e75c5edd-bf6a-49f8-a409-90183aea660c,Splendor,"Renaissance merchants race to grab gems, acquire property, and please nob 74c0d7ba-8acf-46eb-a6a7-c8f04c1860ff,Ra,"Bid to acquire the most valuable sets of Egyptian artifacts and resources." 44bc972e-6a0e-423a-9140-caae3f7f8710,Carcassonne,"Shape the medieval landscape of France, claiming cities, monasteries a 0a937d58-24dd-4dae-894a-b600dfa334d4,Modern Art,"Four types of auctions challenge players in this classic game of art sp c3661009-d024-4c83-8ef6-a967a0a21e6f,Goa,"Run a spice trade business in colonial-era India in this closed-loop economy g edbb5801-f1ae-4c14-b86a-130a7c3a1c4a,Shogun,"Gain control of medieval Japan by amassing troops and sending them out to b 1dec8957-3203-4f84-95c5-ceb3754e4b50,Samurai,"Dispute the favor of three different castes in order to unite Japan under 110c7432-c754-4174-9d0b-7402dc57a500,Kingdomino,"Build a kingdom with varied terrains on domino-shaped tiles in this fas
  119. namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; use Symfony\Component\Validator\Constraints\NotBlank; #[Resource(driver: false)]

    final class BoardGameResource implements ResourceInterface { public function __construct( public ?string $id = null, #[NotBlank] public ?string $name = null, public ?string $shortDescription = null, ) { } public function getId(): string { return $this->id; } }
  120. #[Resource(driver: false)] namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; use Symfony\Component\Validator\Constraints\NotBlank;

    final class BoardGameResource implements ResourceInterface { public function __construct( public ?string $id = null, #[NotBlank] public ?string $name = null, public ?string $shortDescription = null, ) { } public function getId(): string { return $this->id; } }
  121. use Sylius\Component\Resource\Metadata\Resource; #[Resource(driver: false)] namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; use Sylius\Component\Resource\Model\ResourceInterface; use Symfony\Component\Validator\Constraints\NotBlank;

    final class BoardGameResource implements ResourceInterface { public function __construct( public ?string $id = null, #[NotBlank] public ?string $name = null, public ?string $shortDescription = null, ) { } public function getId(): string { return $this->id; } }
  122. final class BoardGameResource implements ResourceInterface namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; use Sylius\Component\Resource\Metadata\Resource; use

    Sylius\Component\Resource\Model\ResourceInterface; use Symfony\Component\Validator\Constraints\NotBlank; #[Resource(driver: false)] { public function __construct( public ?string $id = null, #[NotBlank] public ?string $name = null, public ?string $shortDescription = null, ) { } public function getId(): string { return $this->id; } }
  123. use Sylius\Component\Resource\Model\ResourceInterface; final class BoardGameResource implements ResourceInterface namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; use

    Sylius\Component\Resource\Metadata\Resource; use Symfony\Component\Validator\Constraints\NotBlank; #[Resource(driver: false)] { public function __construct( public ?string $id = null, #[NotBlank] public ?string $name = null, public ?string $shortDescription = null, ) { } public function getId(): string { return $this->id; } }
  124. use Sylius\Component\Resource\Model\ResourceInterface; final class BoardGameResource implements ResourceInterface public function getId():

    string { return $this->id; } namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; use Sylius\Component\Resource\Metadata\Resource; use Symfony\Component\Validator\Constraints\NotBlank; #[Resource(driver: false)] { public function __construct( public ?string $id = null, #[NotBlank] public ?string $name = null, public ?string $shortDescription = null, ) { } }
  125. Browsing board games namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Resource; use

    Sylius\Component\Resource\Model\ResourceInterface; use Symfony\Component\Validator\Constraints\NotBlank; #[Resource(driver: false)] #[Index( grid: 'app_board_game' )] final class BoardGameResource implements ResourceInterface { // [...] }
  126. Browsing board games #[Index( grid: 'app_board_game' )] final class BoardGameResource

    implements ResourceInterface { namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; use Symfony\Component\Validator\Constraints\NotBlank; #[Resource(driver: false)] // [...] }
  127. Browsing board games use Sylius\Component\Resource\Metadata\Index; #[Index( grid: 'app_board_game' )] final

    class BoardGameResource implements ResourceInterface { namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Resource\Model\ResourceInterface; use Symfony\Component\Validator\Constraints\NotBlank; #[Resource(driver: false)] // [...] }
  128. // src/BoardGameBlog/Infrastructure/Sylius/Grid/BoardGameGrid.php final class BoardGameGrid extends AbstractGrid implements ResourceAwareGridInterface {

    public static function getName(): string { return 'app_board_game'; } public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->setProvider(BoardGameGridProvider::class) ->addField( StringField::create('name') ->setLabel('Name') ) ->addField( StringField::create('shortDescription') ->setLabel('Short Description'), ) ; } public function getResourceClass(): string { return BoardGameResource::class; } }
  129. public function getResourceClass(): string { return BoardGameResource::class; } // src/BoardGameBlog/Infrastructure/Sylius/Grid/BoardGameGrid.php

    final class BoardGameGrid extends AbstractGrid implements ResourceAwareGridInterface { public static function getName(): string { return 'app_board_game'; } public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->setProvider(BoardGameGridProvider::class) ->addField( StringField::create('name') ->setLabel('Name') ) ->addField( StringField::create('shortDescription') ->setLabel('Short Description'), ) ; } }
  130. ->setProvider(BoardGameGridProvider::class) // src/BoardGameBlog/Infrastructure/Sylius/Grid/BoardGameGrid.php final class BoardGameGrid extends AbstractGrid implements ResourceAwareGridInterface

    { public static function getName(): string { return 'app_board_game'; } public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->addField( StringField::create('name') ->setLabel('Name') ) ->addField( StringField::create('shortDescription') ->setLabel('Short Description'), ) ; } public function getResourceClass(): string { return BoardGameResource::class; } }
  131. namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; // [...] use Sylius\Component\Grid\Data\DataProviderInterface; final class BoardGameGridProvider implements

    DataProviderInterface { public function __construct(private readonly string $dataDir) {} public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; foreach ($this->getFileData() as $row) { [$id, $name, $shortDescription] = $row; $data[] = new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, ); } return new Pagerfanta(new ArrayAdapter($data)); }
  132. namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; // [...] use Sylius\Component\Grid\Data\DataProviderInterface; final class BoardGameGridProvider implements

    DataProviderInterface { public function __construct(private readonly string $dataDir) {} public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; foreach ($this->getFileData() as $row) { [$id, $name, $shortDescription] = $row; $data[] = new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, ); } return new Pagerfanta(new ArrayAdapter($data)); }
  133. use Sylius\Component\Grid\Data\DataProviderInterface; final class BoardGameGridProvider implements DataProviderInterface namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; //

    [...] { public function __construct(private readonly string $dataDir) {} public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; foreach ($this->getFileData() as $row) { [$id, $name, $shortDescription] = $row; $data[] = new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, ); } return new Pagerfanta(new ArrayAdapter($data)); }
  134. use Sylius\Component\Grid\Data\DataProviderInterface; final class BoardGameGridProvider implements DataProviderInterface public function getData(Grid

    $grid, Parameters $parameters): Pagerfanta namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; // [...] { public function __construct(private readonly string $dataDir) {} { $data = []; foreach ($this->getFileData() as $row) { [$id, $name, $shortDescription] = $row; $data[] = new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, ); } return new Pagerfanta(new ArrayAdapter($data)); }
  135. $data = []; namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; // [...] use Sylius\Component\Grid\Data\DataProviderInterface; final

    class BoardGameGridProvider implements DataProviderInterface { public function __construct(private readonly string $dataDir) {} public function getData(Grid $grid, Parameters $parameters): Pagerfanta { foreach ($this->getFileData() as $row) { [$id, $name, $shortDescription] = $row; $data[] = new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, ); } return new Pagerfanta(new ArrayAdapter($data)); }
  136. foreach ($this->getFileData() as $row) { namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; // [...] use

    Sylius\Component\Grid\Data\DataProviderInterface; final class BoardGameGridProvider implements DataProviderInterface { public function __construct(private readonly string $dataDir) {} public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; [$id, $name, $shortDescription] = $row; $data[] = new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, ); } return new Pagerfanta(new ArrayAdapter($data)); }
  137. [$id, $name, $shortDescription] = $row; namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; // [...] use

    Sylius\Component\Grid\Data\DataProviderInterface; final class BoardGameGridProvider implements DataProviderInterface { public function __construct(private readonly string $dataDir) {} public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; foreach ($this->getFileData() as $row) { $data[] = new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, ); } return new Pagerfanta(new ArrayAdapter($data)); }
  138. $data[] = new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription,

    ); namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; // [...] use Sylius\Component\Grid\Data\DataProviderInterface; final class BoardGameGridProvider implements DataProviderInterface { public function __construct(private readonly string $dataDir) {} public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; foreach ($this->getFileData() as $row) { [$id, $name, $shortDescription] = $row; } return new Pagerfanta(new ArrayAdapter($data)); }
  139. return new Pagerfanta(new ArrayAdapter($data)); namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; // [...] use Sylius\Component\Grid\Data\DataProviderInterface;

    final class BoardGameGridProvider implements DataProviderInterface { public function __construct(private readonly string $dataDir) {} public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; foreach ($this->getFileData() as $row) { [$id, $name, $shortDescription] = $row; $data[] = new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, ); } }
  140. namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; // [...] use Sylius\Component\Grid\Data\DataProviderInterface; final class BoardGameGridProvider implements

    DataProviderInterface { // [...] private function getFileData(): array { return array_map('str_getcsv', file($this->dataDir . '/board_games.csv')); } }
  141. private function getFileData(): array { return array_map('str_getcsv', file($this->dataDir . '/board_games.csv'));

    } namespace App\BoardGameBlog\Infrastructure\Sylius\Grid\DataProvider; // [...] use Sylius\Component\Grid\Data\DataProviderInterface; final class BoardGameGridProvider implements DataProviderInterface { // [...] }
  142. Adding board games namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\CreateBoardGameProcessor; use

    App\BoardGameBlog\Infrastructure\Symfony\Form\Type\BoardGameType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; #[Resource( driver: false, formType: BoardGameType::class), ] #[Index( grid: 'app_board_game' )] #[Create( processor: CreateBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  143. Adding board games formType: BoardGameType::class), namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use

    App\BoardGameBlog\Infrastructure\Sylius\State\Processor\CreateBoardGameProcessor; use App\BoardGameBlog\Infrastructure\Symfony\Form\Type\BoardGameType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; #[Resource( driver: false, ] #[Index( grid: 'app_board_game' )] #[Create( processor: CreateBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  144. Adding board games use App\BoardGameBlog\Infrastructure\Symfony\Form\Type\BoardGameType; formType: BoardGameType::class), namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; //

    [...] use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\CreateBoardGameProcessor; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; #[Resource( driver: false, ] #[Index( grid: 'app_board_game' )] #[Create( processor: CreateBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  145. Adding board games processor: CreateBoardGameProcessor::class, namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use

    App\BoardGameBlog\Infrastructure\Sylius\State\Processor\CreateBoardGameProcessor; use App\BoardGameBlog\Infrastructure\Symfony\Form\Type\BoardGameType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; #[Resource( driver: false, formType: BoardGameType::class), ] #[Index( grid: 'app_board_game' )] #[Create( )] final class BoardGameResource implements ResourceInterface { // [...] }
  146. Adding board games use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\CreateBoardGameProcessor; processor: CreateBoardGameProcessor::class, namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; //

    [...] use App\BoardGameBlog\Infrastructure\Symfony\Form\Type\BoardGameType; use Sylius\Component\Resource\Metadata\Index; use Sylius\Component\Resource\Metadata\Create; #[Resource( driver: false, formType: BoardGameType::class), ] #[Index( grid: 'app_board_game' )] #[Create( )] final class BoardGameResource implements ResourceInterface { // [...] }
  147. namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class CreateBoardGameProcessor implements

    ProcessorInterface { public function __construct(private readonly string $dataDir) {} public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->createBoardGame($data); return null; } private function createBoardGame(BoardGameResource $boardGameResource): void { $handle = fopen($this->dataDir . '/board_games.csv', 'a'); fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); fclose($handle); } }
  148. final class CreateBoardGameProcessor implements ProcessorInterface namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; // [...] use

    Sylius\Component\Resource\State\ProcessorInterface; { public function __construct(private readonly string $dataDir) {} public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->createBoardGame($data); return null; } private function createBoardGame(BoardGameResource $boardGameResource): void { $handle = fopen($this->dataDir . '/board_games.csv', 'a'); fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); fclose($handle); } }
  149. use Sylius\Component\Resource\State\ProcessorInterface; final class CreateBoardGameProcessor implements ProcessorInterface namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; //

    [...] { public function __construct(private readonly string $dataDir) {} public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->createBoardGame($data); return null; } private function createBoardGame(BoardGameResource $boardGameResource): void { $handle = fopen($this->dataDir . '/board_games.csv', 'a'); fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); fclose($handle); } }
  150. use Sylius\Component\Resource\State\ProcessorInterface; final class CreateBoardGameProcessor implements ProcessorInterface public function process(mixed

    $data, Operation $operation, Context $context): mixed namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; // [...] { public function __construct(private readonly string $dataDir) {} { Assert::isInstanceOf($data, BoardGameResource::class); $this->createBoardGame($data); return null; } private function createBoardGame(BoardGameResource $boardGameResource): void { $handle = fopen($this->dataDir . '/board_games.csv', 'a'); fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); fclose($handle); } }
  151. Assert::isInstanceOf($data, BoardGameResource::class); namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class

    CreateBoardGameProcessor implements ProcessorInterface { public function __construct(private readonly string $dataDir) {} public function process(mixed $data, Operation $operation, Context $context): mixed { $this->createBoardGame($data); return null; } private function createBoardGame(BoardGameResource $boardGameResource): void { $handle = fopen($this->dataDir . '/board_games.csv', 'a'); fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); fclose($handle); } }
  152. $this->createBoardGame($data); namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class CreateBoardGameProcessor

    implements ProcessorInterface { public function __construct(private readonly string $dataDir) {} public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); return null; } private function createBoardGame(BoardGameResource $boardGameResource): void { $handle = fopen($this->dataDir . '/board_games.csv', 'a'); fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); fclose($handle); } }
  153. $this->createBoardGame($data); private function createBoardGame(BoardGameResource $boardGameResource): void { $handle = fopen($this->dataDir

    . '/board_games.csv', 'a'); fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); fclose($handle); } namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class CreateBoardGameProcessor implements ProcessorInterface { public function __construct(private readonly string $dataDir) {} public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); return null; } }
  154. $handle = fopen($this->dataDir . '/board_games.csv', 'a'); namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; // [...]

    use Sylius\Component\Resource\State\ProcessorInterface; final class CreateBoardGameProcessor implements ProcessorInterface { public function __construct(private readonly string $dataDir) {} public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->createBoardGame($data); return null; } private function createBoardGame(BoardGameResource $boardGameResource): void { fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); fclose($handle); } }
  155. fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; // [...] use

    Sylius\Component\Resource\State\ProcessorInterface; final class CreateBoardGameProcessor implements ProcessorInterface { public function __construct(private readonly string $dataDir) {} public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->createBoardGame($data); return null; } private function createBoardGame(BoardGameResource $boardGameResource): void { $handle = fopen($this->dataDir . '/board_games.csv', 'a'); fclose($handle); } }
  156. fclose($handle); namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class CreateBoardGameProcessor

    implements ProcessorInterface { public function __construct(private readonly string $dataDir) {} public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->createBoardGame($data); return null; } private function createBoardGame(BoardGameResource $boardGameResource): void { $handle = fopen($this->dataDir . '/board_games.csv', 'a'); fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); } }
  157. return null; namespace App\BoardGameBlog\Infrastructure\Sylius\State\Processor; // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class

    CreateBoardGameProcessor implements ProcessorInterface { public function __construct(private readonly string $dataDir) {} public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->createBoardGame($data); } private function createBoardGame(BoardGameResource $boardGameResource): void { $handle = fopen($this->dataDir . '/board_games.csv', 'a'); fputcsv($handle, [(string) Uuid::v4(), $boardGameResource->name, $boardGameResource->shortDescription]); fclose($handle); } }
  158. Editing board games namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\UpdateBoardGameProcessor; use

    App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; use Sylius\Component\Resource\Metadata\Update; // [...] #[Update( provider: BoardGameItemProvider::class, processor: UpdateBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  159. Editing board games #[Update( namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\UpdateBoardGameProcessor;

    use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; use Sylius\Component\Resource\Metadata\Update; // [...] provider: BoardGameItemProvider::class, processor: UpdateBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  160. Editing board games use Sylius\Component\Resource\Metadata\Update; #[Update( namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...]

    use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\UpdateBoardGameProcessor; use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; // [...] provider: BoardGameItemProvider::class, processor: UpdateBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  161. Editing board games provider: BoardGameItemProvider::class, namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use

    App\BoardGameBlog\Infrastructure\Sylius\State\Processor\UpdateBoardGameProcessor; use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; use Sylius\Component\Resource\Metadata\Update; // [...] #[Update( processor: UpdateBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  162. Editing board games use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; provider: BoardGameItemProvider::class, namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; //

    [...] use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\UpdateBoardGameProcessor; use Sylius\Component\Resource\Metadata\Update; // [...] #[Update( processor: UpdateBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  163. Editing board games processor: UpdateBoardGameProcessor::class, namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use

    App\BoardGameBlog\Infrastructure\Sylius\State\Processor\UpdateBoardGameProcessor; use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; use Sylius\Component\Resource\Metadata\Update; // [...] #[Update( provider: BoardGameItemProvider::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  164. Editing board games use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\UpdateBoardGameProcessor; processor: UpdateBoardGameProcessor::class, namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; //

    [...] use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; use Sylius\Component\Resource\Metadata\Update; // [...] #[Update( provider: BoardGameItemProvider::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  165. // [...] use Sylius\Component\Resource\State\ProviderInterface; final class BoardGameItemProvider implements ProviderInterface {

    public function __construct(private readonly string $dataDir) {} public function provide(Operation $operation, Context $context): ?BoardGameResource { $request = $context->get(RequestOption::class)?->request(); Assert::notNull($request); $id = $request->attributes->get('id'); Assert::nullOrString($id); [$id, $name, $shortDescription] = $this->getFileData()[$id] ?? null; if (null === $id) { return null; } return new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, );
  166. final class BoardGameItemProvider implements ProviderInterface // [...] use Sylius\Component\Resource\State\ProviderInterface; {

    public function __construct(private readonly string $dataDir) {} public function provide(Operation $operation, Context $context): ?BoardGameResource { $request = $context->get(RequestOption::class)?->request(); Assert::notNull($request); $id = $request->attributes->get('id'); Assert::nullOrString($id); [$id, $name, $shortDescription] = $this->getFileData()[$id] ?? null; if (null === $id) { return null; } return new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, );
  167. use Sylius\Component\Resource\State\ProviderInterface; final class BoardGameItemProvider implements ProviderInterface // [...] {

    public function __construct(private readonly string $dataDir) {} public function provide(Operation $operation, Context $context): ?BoardGameResource { $request = $context->get(RequestOption::class)?->request(); Assert::notNull($request); $id = $request->attributes->get('id'); Assert::nullOrString($id); [$id, $name, $shortDescription] = $this->getFileData()[$id] ?? null; if (null === $id) { return null; } return new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, );
  168. public function provide(Operation $operation, Context $context): ?BoardGameResource // [...] use

    Sylius\Component\Resource\State\ProviderInterface; final class BoardGameItemProvider implements ProviderInterface { public function __construct(private readonly string $dataDir) {} { $request = $context->get(RequestOption::class)?->request(); Assert::notNull($request); $id = $request->attributes->get('id'); Assert::nullOrString($id); [$id, $name, $shortDescription] = $this->getFileData()[$id] ?? null; if (null === $id) { return null; } return new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, );
  169. $request = $context->get(RequestOption::class)?->request(); Assert::notNull($request); // [...] use Sylius\Component\Resource\State\ProviderInterface; final class

    BoardGameItemProvider implements ProviderInterface { public function __construct(private readonly string $dataDir) {} public function provide(Operation $operation, Context $context): ?BoardGameResource { $id = $request->attributes->get('id'); Assert::nullOrString($id); [$id, $name, $shortDescription] = $this->getFileData()[$id] ?? null; if (null === $id) { return null; } return new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, );
  170. $id = $request->attributes->get('id'); Assert::nullOrString($id); // [...] use Sylius\Component\Resource\State\ProviderInterface; final class

    BoardGameItemProvider implements ProviderInterface { public function __construct(private readonly string $dataDir) {} public function provide(Operation $operation, Context $context): ?BoardGameResource { $request = $context->get(RequestOption::class)?->request(); Assert::notNull($request); [$id, $name, $shortDescription] = $this->getFileData()[$id] ?? null; if (null === $id) { return null; } return new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, );
  171. [$id, $name, $shortDescription] = $this->getFileData()[$id] ?? null; // [...] use

    Sylius\Component\Resource\State\ProviderInterface; final class BoardGameItemProvider implements ProviderInterface { public function __construct(private readonly string $dataDir) {} public function provide(Operation $operation, Context $context): ?BoardGameResource { $request = $context->get(RequestOption::class)?->request(); Assert::notNull($request); $id = $request->attributes->get('id'); Assert::nullOrString($id); if (null === $id) { return null; } return new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, );
  172. if (null === $id) { return null; } // [...]

    use Sylius\Component\Resource\State\ProviderInterface; final class BoardGameItemProvider implements ProviderInterface { public function __construct(private readonly string $dataDir) {} public function provide(Operation $operation, Context $context): ?BoardGameResource { $request = $context->get(RequestOption::class)?->request(); Assert::notNull($request); $id = $request->attributes->get('id'); Assert::nullOrString($id); [$id, $name, $shortDescription] = $this->getFileData()[$id] ?? null; return new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, );
  173. return new BoardGameResource( id: $id, name: $name, shortDescription: $shortDescription, );

    // [...] use Sylius\Component\Resource\State\ProviderInterface; final class BoardGameItemProvider implements ProviderInterface { public function __construct(private readonly string $dataDir) {} public function provide(Operation $operation, Context $context): ?BoardGameResource { $request = $context->get(RequestOption::class)?->request(); Assert::notNull($request); $id = $request->attributes->get('id'); Assert::nullOrString($id); [$id, $name, $shortDescription] = $this->getFileData()[$id] ?? null; if (null === $id) { return null; }
  174. // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class UpdateBoardGameProcessor implements ProcessorInterface {

    public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->updateBoardGame($data); return null; } private function updateBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); $row = &$fileData[$boardGameResource->id]; $row[1] = $boardGameResource->name; $row[2] = $boardGameResource->shortDescription; $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data);
  175. final class UpdateBoardGameProcessor implements ProcessorInterface // [...] use Sylius\Component\Resource\State\ProcessorInterface; {

    public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->updateBoardGame($data); return null; } private function updateBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); $row = &$fileData[$boardGameResource->id]; $row[1] = $boardGameResource->name; $row[2] = $boardGameResource->shortDescription; $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data);
  176. use Sylius\Component\Resource\State\ProcessorInterface; final class UpdateBoardGameProcessor implements ProcessorInterface // [...] {

    public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->updateBoardGame($data); return null; } private function updateBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); $row = &$fileData[$boardGameResource->id]; $row[1] = $boardGameResource->name; $row[2] = $boardGameResource->shortDescription; $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data);
  177. public function process(mixed $data, Operation $operation, Context $context): mixed //

    [...] use Sylius\Component\Resource\State\ProcessorInterface; final class UpdateBoardGameProcessor implements ProcessorInterface { { Assert::isInstanceOf($data, BoardGameResource::class); $this->updateBoardGame($data); return null; } private function updateBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); $row = &$fileData[$boardGameResource->id]; $row[1] = $boardGameResource->name; $row[2] = $boardGameResource->shortDescription; $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data);
  178. Assert::isInstanceOf($data, BoardGameResource::class); // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class UpdateBoardGameProcessor implements

    ProcessorInterface { public function process(mixed $data, Operation $operation, Context $context): mixed { $this->updateBoardGame($data); return null; } private function updateBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); $row = &$fileData[$boardGameResource->id]; $row[1] = $boardGameResource->name; $row[2] = $boardGameResource->shortDescription; $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data);
  179. $this->updateBoardGame($data); // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class UpdateBoardGameProcessor implements ProcessorInterface

    { public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); return null; } private function updateBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); $row = &$fileData[$boardGameResource->id]; $row[1] = $boardGameResource->name; $row[2] = $boardGameResource->shortDescription; $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data);
  180. $this->updateBoardGame($data); private function updateBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData();

    $row = &$fileData[$boardGameResource->id]; $row[1] = $boardGameResource->name; $row[2] = $boardGameResource->shortDescription; $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data); // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class UpdateBoardGameProcessor implements ProcessorInterface { public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); return null; }
  181. return null; // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class UpdateBoardGameProcessor implements

    ProcessorInterface { public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->updateBoardGame($data); } private function updateBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); $row = &$fileData[$boardGameResource->id]; $row[1] = $boardGameResource->name; $row[2] = $boardGameResource->shortDescription; $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data);
  182. Deleting board games namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\DeleteBoardGameProcessor; use

    App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; use Sylius\Component\Resource\Metadata\Delete; // [...] #[Delete( provider: BoardGameItemProvider::class, processor: DeleteBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  183. Deleting board games #[Delete( namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\DeleteBoardGameProcessor;

    use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; use Sylius\Component\Resource\Metadata\Delete; // [...] provider: BoardGameItemProvider::class, processor: DeleteBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  184. Deleting board games use Sylius\Component\Resource\Metadata\Delete; #[Delete( namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...]

    use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\DeleteBoardGameProcessor; use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; // [...] provider: BoardGameItemProvider::class, processor: DeleteBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  185. Deleting board games provider: BoardGameItemProvider::class, namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use

    App\BoardGameBlog\Infrastructure\Sylius\State\Processor\DeleteBoardGameProcessor; use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; use Sylius\Component\Resource\Metadata\Delete; // [...] #[Delete( processor: DeleteBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  186. Deleting board games use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; provider: BoardGameItemProvider::class, namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; //

    [...] use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\DeleteBoardGameProcessor; use Sylius\Component\Resource\Metadata\Delete; // [...] #[Delete( processor: DeleteBoardGameProcessor::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  187. Deleting board games processor: DeleteBoardGameProcessor::class, namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; // [...] use

    App\BoardGameBlog\Infrastructure\Sylius\State\Processor\DeleteBoardGameProcessor; use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; use Sylius\Component\Resource\Metadata\Delete; // [...] #[Delete( provider: BoardGameItemProvider::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  188. Deleting board games use App\BoardGameBlog\Infrastructure\Sylius\State\Processor\DeleteBoardGameProcessor; processor: DeleteBoardGameProcessor::class, namespace App\BoardGameBlog\Infrastructure\Sylius\Resource; //

    [...] use App\BoardGameBlog\Infrastructure\Sylius\State\Provider\BoardGameItemProvider; use Sylius\Component\Resource\Metadata\Delete; // [...] #[Delete( provider: BoardGameItemProvider::class, )] final class BoardGameResource implements ResourceInterface { // [...] }
  189. // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class DeleteBoardGameProcessor implements ProcessorInterface {

    public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->deleteBoardGame($data); return null; } private function deleteBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); unset($fileData[$boardGameResource->id]); $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data); } fclose($handle);
  190. final class DeleteBoardGameProcessor implements ProcessorInterface // [...] use Sylius\Component\Resource\State\ProcessorInterface; {

    public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->deleteBoardGame($data); return null; } private function deleteBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); unset($fileData[$boardGameResource->id]); $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data); } fclose($handle);
  191. use Sylius\Component\Resource\State\ProcessorInterface; final class DeleteBoardGameProcessor implements ProcessorInterface // [...] {

    public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->deleteBoardGame($data); return null; } private function deleteBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); unset($fileData[$boardGameResource->id]); $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data); } fclose($handle);
  192. public function process(mixed $data, Operation $operation, Context $context): mixed //

    [...] use Sylius\Component\Resource\State\ProcessorInterface; final class DeleteBoardGameProcessor implements ProcessorInterface { { Assert::isInstanceOf($data, BoardGameResource::class); $this->deleteBoardGame($data); return null; } private function deleteBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); unset($fileData[$boardGameResource->id]); $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data); } fclose($handle);
  193. Assert::isInstanceOf($data, BoardGameResource::class); // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class DeleteBoardGameProcessor implements

    ProcessorInterface { public function process(mixed $data, Operation $operation, Context $context): mixed { $this->deleteBoardGame($data); return null; } private function deleteBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); unset($fileData[$boardGameResource->id]); $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data); } fclose($handle);
  194. $this->deleteBoardGame($data); // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class DeleteBoardGameProcessor implements ProcessorInterface

    { public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); return null; } private function deleteBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); unset($fileData[$boardGameResource->id]); $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data); } fclose($handle);
  195. $this->deleteBoardGame($data); private function deleteBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData();

    unset($fileData[$boardGameResource->id]); $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data); } fclose($handle); // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class DeleteBoardGameProcessor implements ProcessorInterface { public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); return null; }
  196. return null; // [...] use Sylius\Component\Resource\State\ProcessorInterface; final class DeleteBoardGameProcessor implements

    ProcessorInterface { public function process(mixed $data, Operation $operation, Context $context): mixed { Assert::isInstanceOf($data, BoardGameResource::class); $this->deleteBoardGame($data); } private function deleteBoardGame(BoardGameResource $boardGameResource): void { $fileData = $this->getFileData(); unset($fileData[$boardGameResource->id]); $handle = fopen($this->dataDir . '/board_games.csv', 'wb'); foreach ($fileData as $data) { fputcsv($handle, $data); } fclose($handle);
  197. Sorting board games final class BoardGameGrid extends AbstractGrid implements ResourceAwareGridInterface

    { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->setProvider(BoardGameGridProvider::class) ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('Name') ->setSortable(true), ) // [...] ; } // [...] }
  198. Sorting board games ->addField( StringField::create('name') ->setLabel('Name') ->setSortable(true), ) final class

    BoardGameGrid extends AbstractGrid implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->setProvider(BoardGameGridProvider::class) ->orderBy('name', 'asc') // [...] ; } // [...] }
  199. Sorting board games ->setSortable(true), final class BoardGameGrid extends AbstractGrid implements

    ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->setProvider(BoardGameGridProvider::class) ->orderBy('name', 'asc') ->addField( StringField::create('name') ->setLabel('Name') ) // [...] ; } // [...] }
  200. Sorting board games ->orderBy('name', 'asc') final class BoardGameGrid extends AbstractGrid

    implements ResourceAwareGridInterface { // [...] public function buildGrid(GridBuilderInterface $gridBuilder): void { $gridBuilder ->setProvider(BoardGameGridProvider::class) ->addField( StringField::create('name') ->setLabel('Name') ->setSortable(true), ) // [...] ; } // [...] }
  201. final class BoardGameGridProvider implements DataProviderInterface { public function getData(Grid $grid,

    Parameters $parameters): Pagerfanta { $data = []; $fileData = $this->getFileData(); $sorting = $parameters->get('sorting') ?? []; $fileData = $this->sortData($fileData, $sorting); // [...] } private function sortData(array $data, array $sorting): array { if ('asc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameAsc']); } if ('desc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameDesc']); } return $data;
  202. $sorting = $parameters->get('sorting') ?? []; final class BoardGameGridProvider implements DataProviderInterface

    { public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; $fileData = $this->getFileData(); $fileData = $this->sortData($fileData, $sorting); // [...] } private function sortData(array $data, array $sorting): array { if ('asc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameAsc']); } if ('desc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameDesc']); } return $data;
  203. $fileData = $this->sortData($fileData, $sorting); final class BoardGameGridProvider implements DataProviderInterface {

    public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; $fileData = $this->getFileData(); $sorting = $parameters->get('sorting') ?? []; // [...] } private function sortData(array $data, array $sorting): array { if ('asc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameAsc']); } if ('desc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameDesc']); } return $data;
  204. $fileData = $this->sortData($fileData, $sorting); private function sortData(array $data, array $sorting):

    array { if ('asc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameAsc']); } if ('desc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameDesc']); } return $data; final class BoardGameGridProvider implements DataProviderInterface { public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; $fileData = $this->getFileData(); $sorting = $parameters->get('sorting') ?? []; // [...] }
  205. final class BoardGameGridProvider implements DataProviderInterface { // [...] private function

    sortData(array $data, array $sorting): array { if ('asc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameAsc']); } if ('desc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameDesc']); } return $data; } private function sortByNameAsc($a, $b): int { return strcmp($a[1], $b[1]); } private function sortByNameDesc($a, $b): int { return strcmp($b[1], $a[1]); }
  206. if ('asc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameAsc']);

    } final class BoardGameGridProvider implements DataProviderInterface { // [...] private function sortData(array $data, array $sorting): array { if ('desc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameDesc']); } return $data; } private function sortByNameAsc($a, $b): int { return strcmp($a[1], $b[1]); } private function sortByNameDesc($a, $b): int { return strcmp($b[1], $a[1]); }
  207. if ('asc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameAsc']);

    } private function sortByNameAsc($a, $b): int { return strcmp($a[1], $b[1]); } final class BoardGameGridProvider implements DataProviderInterface { // [...] private function sortData(array $data, array $sorting): array { if ('desc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameDesc']); } return $data; } private function sortByNameDesc($a, $b): int { return strcmp($b[1], $a[1]); }
  208. if ('desc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameDesc']);

    } final class BoardGameGridProvider implements DataProviderInterface { // [...] private function sortData(array $data, array $sorting): array { if ('asc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameAsc']); } return $data; } private function sortByNameAsc($a, $b): int { return strcmp($a[1], $b[1]); } private function sortByNameDesc($a, $b): int { return strcmp($b[1], $a[1]); }
  209. if ('desc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameDesc']);

    } private function sortByNameDesc($a, $b): int { return strcmp($b[1], $a[1]); } final class BoardGameGridProvider implements DataProviderInterface { // [...] private function sortData(array $data, array $sorting): array { if ('asc' === ($sorting['name'] ?? null)) { usort($data, [$this, 'sortByNameAsc']); } return $data; } private function sortByNameAsc($a, $b): int { return strcmp($a[1], $b[1]); }
  210. final class BoardGameGridProvider implements DataProviderInterface { public function getData(Grid $grid,

    Parameters $parameters): Pagerfanta { $data = []; $fileData = $this->getFileData(); $sorting = $parameters->get('sorting') ?? []; $fileData = $this->sortData($fileData, $sorting); // [...] } // [...] }
  211. $sorting = $parameters->get('sorting') ?? []; final class BoardGameGridProvider implements DataProviderInterface

    { public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; $fileData = $this->getFileData(); $fileData = $this->sortData($fileData, $sorting); // [...] } // [...] }
  212. $sorting = $parameters->get('sorting') ?? $grid->getSorting(); final class BoardGameGridProvider implements DataProviderInterface

    { public function getData(Grid $grid, Parameters $parameters): Pagerfanta { $data = []; $fileData = $this->getFileData(); $fileData = $this->sortData($fileData, $sorting); // [...] } // [...] }
  213. Resource configurator // config/package/sylius_resource.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription;

    use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Loader\Configuration\ResourceConfigurator; return static function (ResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withResource((new Resource(Book::class)) ->withRoutePrefix('admin') ->withOperations([ new Index(), new Create(), new Update(), new Delete(), ]) ) ->withResource((new Resource(Subscription::class)) ->withOperations([ new Index(), ]) )
  214. Resource configurator return static function (ResourceConfigurator $resourceConfigurator): void { //

    config/package/sylius_resource.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Loader\Configuration\ResourceConfigurator; $resourceConfigurator ->withResource((new Resource(Book::class)) ->withRoutePrefix('admin') ->withOperations([ new Index(), new Create(), new Update(), new Delete(), ]) ) ->withResource((new Resource(Subscription::class)) ->withOperations([ new Index(), ]) )
  215. Resource configurator use Sylius\Component\Loader\Configuration\ResourceConfigurator; return static function (ResourceConfigurator $resourceConfigurator): void

    { // config/package/sylius_resource.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription; use Sylius\Component\Resource\Metadata\Resource; $resourceConfigurator ->withResource((new Resource(Book::class)) ->withRoutePrefix('admin') ->withOperations([ new Index(), new Create(), new Update(), new Delete(), ]) ) ->withResource((new Resource(Subscription::class)) ->withOperations([ new Index(), ]) )
  216. Resource configurator ->withResource((new Resource(Book::class)) // config/package/sylius_resource.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book;

    use App\Entity\Subscription; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Loader\Configuration\ResourceConfigurator; return static function (ResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withRoutePrefix('admin') ->withOperations([ new Index(), new Create(), new Update(), new Delete(), ]) ) ->withResource((new Resource(Subscription::class)) ->withOperations([ new Index(), ]) )
  217. Resource configurator use Sylius\Component\Resource\Metadata\Resource; ->withResource((new Resource(Book::class)) // config/package/sylius_resource.php namespace Symfony\Component\DependencyInjection\Loader\Configurator;

    use App\Entity\Book; use App\Entity\Subscription; use Sylius\Component\Loader\Configuration\ResourceConfigurator; return static function (ResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withRoutePrefix('admin') ->withOperations([ new Index(), new Create(), new Update(), new Delete(), ]) ) ->withResource((new Resource(Subscription::class)) ->withOperations([ new Index(), ]) )
  218. Resource configurator ->withRoutePrefix('admin') // config/package/sylius_resource.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use

    App\Entity\Subscription; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Loader\Configuration\ResourceConfigurator; return static function (ResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withResource((new Resource(Book::class)) ->withOperations([ new Index(), new Create(), new Update(), new Delete(), ]) ) ->withResource((new Resource(Subscription::class)) ->withOperations([ new Index(), ]) )
  219. Resource configurator ->withOperations([ new Index(), new Create(), new Update(), new

    Delete(), ]) // config/package/sylius_resource.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Loader\Configuration\ResourceConfigurator; return static function (ResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withResource((new Resource(Book::class)) ->withRoutePrefix('admin') ) ->withResource((new Resource(Subscription::class)) ->withOperations([ new Index(), ]) )
  220. Resource configurator ->withResource((new Resource(Subscription::class)) // config/package/sylius_resource.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book;

    use App\Entity\Subscription; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Loader\Configuration\ResourceConfigurator; return static function (ResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withResource((new Resource(Book::class)) ->withRoutePrefix('admin') ->withOperations([ new Index(), new Create(), new Update(), new Delete(), ]) ) ->withOperations([ new Index(), ]) )
  221. Resource configurator ->withOperations([ new Index(), ]) // config/package/sylius_resource.php namespace Symfony\Component\DependencyInjection\Loader\Configurator;

    use App\Entity\Book; use App\Entity\Subscription; use Sylius\Component\Resource\Metadata\Resource; use Sylius\Component\Loader\Configuration\ResourceConfigurator; return static function (ResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withResource((new Resource(Book::class)) ->withRoutePrefix('admin') ->withOperations([ new Index(), new Create(), new Update(), new Delete(), ]) ) ->withResource((new Resource(Subscription::class)) )
  222. // config/api_platform/resources.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription; use ApiPlatform\Metadata\ApiResource;

    use ApiPlatorm\Loader\Configuration\ApiResourceConfigurator; return static function (ApiResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withResource((new ApiResource(Book::class)) ->withRoutePrefix('admin') ->withOperations([ new GetCollection(), new Post(), new Put(), new Delete(), ]) ) ->withResource((new ApiResource(Subscription::class)) ->withOperations([ new GetCollection(), ]) ) ; };
  223. return static function (ApiResourceConfigurator $resourceConfigurator): void { // config/api_platform/resources.php namespace

    Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription; use ApiPlatform\Metadata\ApiResource; use ApiPlatorm\Loader\Configuration\ApiResourceConfigurator; $resourceConfigurator ->withResource((new ApiResource(Book::class)) ->withRoutePrefix('admin') ->withOperations([ new GetCollection(), new Post(), new Put(), new Delete(), ]) ) ->withResource((new ApiResource(Subscription::class)) ->withOperations([ new GetCollection(), ]) ) ; };
  224. use ApiPlatorm\Loader\Configuration\ApiResourceConfigurator; return static function (ApiResourceConfigurator $resourceConfigurator): void { //

    config/api_platform/resources.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription; use ApiPlatform\Metadata\ApiResource; $resourceConfigurator ->withResource((new ApiResource(Book::class)) ->withRoutePrefix('admin') ->withOperations([ new GetCollection(), new Post(), new Put(), new Delete(), ]) ) ->withResource((new ApiResource(Subscription::class)) ->withOperations([ new GetCollection(), ]) ) ; };
  225. ->withResource((new ApiResource(Book::class)) // config/api_platform/resources.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription;

    use ApiPlatform\Metadata\ApiResource; use ApiPlatorm\Loader\Configuration\ApiResourceConfigurator; return static function (ApiResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withRoutePrefix('admin') ->withOperations([ new GetCollection(), new Post(), new Put(), new Delete(), ]) ) ->withResource((new ApiResource(Subscription::class)) ->withOperations([ new GetCollection(), ]) ) ; };
  226. use ApiPlatform\Metadata\ApiResource; ->withResource((new ApiResource(Book::class)) // config/api_platform/resources.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book;

    use App\Entity\Subscription; use ApiPlatorm\Loader\Configuration\ApiResourceConfigurator; return static function (ApiResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withRoutePrefix('admin') ->withOperations([ new GetCollection(), new Post(), new Put(), new Delete(), ]) ) ->withResource((new ApiResource(Subscription::class)) ->withOperations([ new GetCollection(), ]) ) ; };
  227. ->withRoutePrefix('admin') // config/api_platform/resources.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription; use

    ApiPlatform\Metadata\ApiResource; use ApiPlatorm\Loader\Configuration\ApiResourceConfigurator; return static function (ApiResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withResource((new ApiResource(Book::class)) ->withOperations([ new GetCollection(), new Post(), new Put(), new Delete(), ]) ) ->withResource((new ApiResource(Subscription::class)) ->withOperations([ new GetCollection(), ]) ) ; };
  228. ->withOperations([ new GetCollection(), new Post(), new Put(), new Delete(), ])

    // config/api_platform/resources.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription; use ApiPlatform\Metadata\ApiResource; use ApiPlatorm\Loader\Configuration\ApiResourceConfigurator; return static function (ApiResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withResource((new ApiResource(Book::class)) ->withRoutePrefix('admin') ) ->withResource((new ApiResource(Subscription::class)) ->withOperations([ new GetCollection(), ]) ) ; };
  229. ->withResource((new ApiResource(Subscription::class)) // config/api_platform/resources.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book; use App\Entity\Subscription;

    use ApiPlatform\Metadata\ApiResource; use ApiPlatorm\Loader\Configuration\ApiResourceConfigurator; return static function (ApiResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withResource((new ApiResource(Book::class)) ->withRoutePrefix('admin') ->withOperations([ new GetCollection(), new Post(), new Put(), new Delete(), ]) ) ->withOperations([ new GetCollection(), ]) ) ; };
  230. ->withOperations([ new GetCollection(), ]) // config/api_platform/resources.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; use App\Entity\Book;

    use App\Entity\Subscription; use ApiPlatform\Metadata\ApiResource; use ApiPlatorm\Loader\Configuration\ApiResourceConfigurator; return static function (ApiResourceConfigurator $resourceConfigurator): void { $resourceConfigurator ->withResource((new ApiResource(Book::class)) ->withRoutePrefix('admin') ->withOperations([ new GetCollection(), new Post(), new Put(), new Delete(), ]) ) ->withResource((new ApiResource(Subscription::class)) ) ; };