Skip to content

Commit

Permalink
10 - Add a form to add, edit or delete locations in the admin interface
Browse files Browse the repository at this point in the history
  • Loading branch information
wachterjohannes authored and niklasnatter committed Jun 20, 2022
1 parent 458ce4f commit 3c9f9f5
Show file tree
Hide file tree
Showing 9 changed files with 454 additions and 2 deletions.
53 changes: 53 additions & 0 deletions config/forms/location_details.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" ?>
<form xmlns="http://schemas.sulu.io/template/template"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.sulu.io/template/template http://schemas.sulu.io/template/form-1.0.xsd"
>
<key>location_details</key>

<properties>
<property name="name" type="text_line" mandatory="true">
<meta>
<title>sulu_admin.name</title>
</meta>
</property>

<property name="street" type="text_line" colspan="9">
<meta>
<title>sulu_contact.street</title>
</meta>
</property>

<property name="number" type="text_line" colspan="3">
<meta>
<title>sulu_contact.number</title>
</meta>
</property>

<property name="postalCode" type="text_line" colspan="3">
<meta>
<title>sulu_contact.zip</title>
</meta>
</property>

<property name="city" type="text_line" colspan="6">
<meta>
<title>sulu_contact.city</title>
</meta>
</property>

<property name="countryCode" type="single_select" colspan="3">
<meta>
<title>sulu_contact.country</title>
</meta>

<params>
<param
name="values"
type="expression"
value="service('app.country_select').getValues()"
/>
</params>
</property>
</properties>
</form>
1 change: 1 addition & 0 deletions config/packages/sulu_admin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ sulu_admin:
locations:
routes:
list: app.get_location_list
detail: app.get_location

# Registering Selection Field Types in this section
field_type_options:
Expand Down
4 changes: 4 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ services:
bind:
$repository: '@App\Repository\EventRepository'

app.country_select:
class: App\Service\CountryCodeSelect
public: true

# following service definitions will be removed in the website context of sulu
App\Admin\:
resource: '../src/Admin'
Expand Down
45 changes: 44 additions & 1 deletion src/Admin/LocationAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Sulu\Bundle\AdminBundle\Admin\Admin;
use Sulu\Bundle\AdminBundle\Admin\Navigation\NavigationItem;
use Sulu\Bundle\AdminBundle\Admin\Navigation\NavigationItemCollection;
use Sulu\Bundle\AdminBundle\Admin\View\ToolbarAction;
use Sulu\Bundle\AdminBundle\Admin\View\ViewBuilderFactoryInterface;
use Sulu\Bundle\AdminBundle\Admin\View\ViewCollection;

Expand All @@ -17,6 +18,10 @@ class LocationAdmin extends Admin

const LOCATION_LIST_VIEW = 'app.locations_list';

const LOCATION_ADD_FORM_VIEW = 'app.location_add_form';

const LOCATION_EDIT_FORM_VIEW = 'app.location_edit_form';

/**
* @var ViewBuilderFactoryInterface
*/
Expand All @@ -40,12 +45,50 @@ public function configureNavigationItems(NavigationItemCollection $navigationIte

public function configureViews(ViewCollection $viewCollection): void
{
$listToolbarActions = [
new ToolbarAction('sulu_admin.add'),
new ToolbarAction('sulu_admin.delete'),
];
$listView = $this->viewBuilderFactory->createListViewBuilder(self::LOCATION_LIST_VIEW, '/locations')
->setResourceKey(Location::RESOURCE_KEY)
->setListKey(self::LOCATION_LIST_KEY)
->setTitle('app.locations')
->addListAdapters(['table'])
->addToolbarActions([]);
->setAddView(static::LOCATION_ADD_FORM_VIEW)
->setEditView(static::LOCATION_EDIT_FORM_VIEW)
->addToolbarActions($listToolbarActions);
$viewCollection->add($listView);

$addFormView = $this->viewBuilderFactory->createResourceTabViewBuilder(self::LOCATION_ADD_FORM_VIEW, '/locations/add')
->setResourceKey('locations')
->setBackView(static::LOCATION_LIST_VIEW);
$viewCollection->add($addFormView);

$addDetailsFormView = $this->viewBuilderFactory->createFormViewBuilder(self::LOCATION_ADD_FORM_VIEW . '.details', '/details')
->setResourceKey('locations')
->setFormKey('location_details')
->setTabTitle('sulu_admin.details')
->setEditView(static::LOCATION_EDIT_FORM_VIEW)
->addToolbarActions([new ToolbarAction('sulu_admin.save')])
->setParent(static::LOCATION_ADD_FORM_VIEW);
$viewCollection->add($addDetailsFormView);

$editFormView = $this->viewBuilderFactory->createResourceTabViewBuilder(static::LOCATION_EDIT_FORM_VIEW, '/locations/:id')
->setResourceKey('locations')
->setBackView(static::LOCATION_LIST_VIEW)
->setTitleProperty('title');
$viewCollection->add($editFormView);

$formToolbarActions = [
new ToolbarAction('sulu_admin.save'),
new ToolbarAction('sulu_admin.delete'),
];
$editDetailsFormView = $this->viewBuilderFactory->createFormViewBuilder(static::LOCATION_EDIT_FORM_VIEW . '.details', '/details')
->setResourceKey('locations')
->setFormKey('location_details')
->setTabTitle('sulu_admin.details')
->addToolbarActions($formToolbarActions)
->setParent(static::LOCATION_EDIT_FORM_VIEW);
$viewCollection->add($editDetailsFormView);
}
}
110 changes: 110 additions & 0 deletions src/Controller/Admin/LocationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,85 @@

use App\Common\DoctrineListRepresentationFactory;
use App\Entity\Location;
use App\Repository\LocationRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;

class LocationController extends AbstractController
{
/**
* @var LocationRepository
*/
private $locationRepository;

/**
* @var DoctrineListRepresentationFactory
*/
private $doctrineListRepresentationFactory;

public function __construct(
LocationRepository $repository,
DoctrineListRepresentationFactory $doctrineListRepresentationFactory
) {
$this->locationRepository = $repository;
$this->doctrineListRepresentationFactory = $doctrineListRepresentationFactory;
}

/**
* @Route("/admin/api/locations/{id}", methods={"GET"}, name="app.get_location")
*/
public function getAction(int $id, Request $request): Response
{
$location = $this->load($id);
if (!$location) {
throw new NotFoundHttpException();
}

return $this->json($this->getDataForEntity($location));
}

/**
* @Route("/admin/api/locations/{id}", methods={"PUT"}, name="app.put_location")
*/
public function putAction(int $id, Request $request): Response
{
$location = $this->load($id);
if (!$location) {
throw new NotFoundHttpException();
}

$this->mapDataToEntity($request->toArray(), $location);
$this->save($location);

return $this->json($this->getDataForEntity($location));
}

/**
* @Route("/admin/api/locations", methods={"POST"}, name="app.post_location")
*/
public function postAction(Request $request): Response
{
$location = $this->create();

$this->mapDataToEntity($request->toArray(), $location);
$this->save($location);

return $this->json($this->getDataForEntity($location), 201);
}

/**
* @Route("/admin/api/locations/{id}", methods={"DELETE"}, name="app.delete_location")
*/
public function deleteAction(int $id): Response
{
$this->remove($id);

return $this->json(null, 204);
}

/**
* @Route("/admin/api/locations", methods={"GET"}, name="app.get_location_list")
*/
Expand All @@ -35,4 +96,53 @@ public function getListAction(Request $request): Response

return $this->json($listRepresentation->toArray());
}

/**
* @return array<string, mixed>
*/
protected function getDataForEntity(Location $entity): array
{
return [
'id' => $entity->getId(),
'name' => $entity->getName(),
'street' => $entity->getStreet(),
'number' => $entity->getNumber(),
'postalCode' => $entity->getPostalCode(),
'city' => $entity->getCity(),
'countryCode' => $entity->getCountryCode(),
];
}

/**
* @param array<string, mixed> $data
*/
protected function mapDataToEntity(array $data, Location $entity): void
{
$entity->setName($data['name']);
$entity->setStreet($data['street'] ?? '');
$entity->setNumber($data['number'] ?? '');
$entity->setPostalCode($data['postalCode'] ?? '');
$entity->setCity($data['city'] ?? '');
$entity->setCountryCode($data['countryCode'] ?? '');
}

protected function load(int $id): ?Location
{
return $this->locationRepository->findById($id);
}

protected function create(): Location
{
return $this->locationRepository->create();
}

protected function save(Location $entity): void
{
$this->locationRepository->save($entity);
}

protected function remove(int $id): void
{
$this->locationRepository->remove($id);
}
}
26 changes: 25 additions & 1 deletion src/Repository/LocationRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,33 @@ public function __construct(ManagerRegistry $registry)

public function create(): Location
{
$location = new Location();
return new Location();
}

public function remove(int $id): void
{
/** @var object $location */
$location = $this->getEntityManager()->getReference(
$this->getClassName(),
$id
);

$this->getEntityManager()->remove($location);
$this->getEntityManager()->flush();
}

public function save(Location $location): void
{
$this->getEntityManager()->persist($location);
$this->getEntityManager()->flush();
}

public function findById(int $id): ?Location
{
$location = $this->find($id);
if (!$location) {
return null;
}

return $location;
}
Expand Down
27 changes: 27 additions & 0 deletions src/Service/CountryCodeSelect.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace App\Service;

use Symfony\Component\Intl\Countries;

class CountryCodeSelect
{
/**
* @return array[]
*/
public function getValues(): array
{
$values = [];

foreach (Countries::getNames() as $code => $title) {
$values[] = [
'name' => $code,
'title' => $title,
];
}

return $values;
}
}
Loading

0 comments on commit 3c9f9f5

Please sign in to comment.