Skip to content

Commit 3c9f9f5

Browse files
wachterjohannesniklasnatter
authored andcommitted
10 - Add a form to add, edit or delete locations in the admin interface
1 parent 458ce4f commit 3c9f9f5

File tree

9 files changed

+454
-2
lines changed

9 files changed

+454
-2
lines changed

config/forms/location_details.xml

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?xml version="1.0" ?>
2+
<form xmlns="http://schemas.sulu.io/template/template"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://schemas.sulu.io/template/template http://schemas.sulu.io/template/form-1.0.xsd"
5+
>
6+
<key>location_details</key>
7+
8+
<properties>
9+
<property name="name" type="text_line" mandatory="true">
10+
<meta>
11+
<title>sulu_admin.name</title>
12+
</meta>
13+
</property>
14+
15+
<property name="street" type="text_line" colspan="9">
16+
<meta>
17+
<title>sulu_contact.street</title>
18+
</meta>
19+
</property>
20+
21+
<property name="number" type="text_line" colspan="3">
22+
<meta>
23+
<title>sulu_contact.number</title>
24+
</meta>
25+
</property>
26+
27+
<property name="postalCode" type="text_line" colspan="3">
28+
<meta>
29+
<title>sulu_contact.zip</title>
30+
</meta>
31+
</property>
32+
33+
<property name="city" type="text_line" colspan="6">
34+
<meta>
35+
<title>sulu_contact.city</title>
36+
</meta>
37+
</property>
38+
39+
<property name="countryCode" type="single_select" colspan="3">
40+
<meta>
41+
<title>sulu_contact.country</title>
42+
</meta>
43+
44+
<params>
45+
<param
46+
name="values"
47+
type="expression"
48+
value="service('app.country_select').getValues()"
49+
/>
50+
</params>
51+
</property>
52+
</properties>
53+
</form>

config/packages/sulu_admin.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ sulu_admin:
2121
locations:
2222
routes:
2323
list: app.get_location_list
24+
detail: app.get_location
2425

2526
# Registering Selection Field Types in this section
2627
field_type_options:

config/services.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ services:
4949
bind:
5050
$repository: '@App\Repository\EventRepository'
5151

52+
app.country_select:
53+
class: App\Service\CountryCodeSelect
54+
public: true
55+
5256
# following service definitions will be removed in the website context of sulu
5357
App\Admin\:
5458
resource: '../src/Admin'

src/Admin/LocationAdmin.php

+44-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Sulu\Bundle\AdminBundle\Admin\Admin;
99
use Sulu\Bundle\AdminBundle\Admin\Navigation\NavigationItem;
1010
use Sulu\Bundle\AdminBundle\Admin\Navigation\NavigationItemCollection;
11+
use Sulu\Bundle\AdminBundle\Admin\View\ToolbarAction;
1112
use Sulu\Bundle\AdminBundle\Admin\View\ViewBuilderFactoryInterface;
1213
use Sulu\Bundle\AdminBundle\Admin\View\ViewCollection;
1314

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

1819
const LOCATION_LIST_VIEW = 'app.locations_list';
1920

21+
const LOCATION_ADD_FORM_VIEW = 'app.location_add_form';
22+
23+
const LOCATION_EDIT_FORM_VIEW = 'app.location_edit_form';
24+
2025
/**
2126
* @var ViewBuilderFactoryInterface
2227
*/
@@ -40,12 +45,50 @@ public function configureNavigationItems(NavigationItemCollection $navigationIte
4045

4146
public function configureViews(ViewCollection $viewCollection): void
4247
{
48+
$listToolbarActions = [
49+
new ToolbarAction('sulu_admin.add'),
50+
new ToolbarAction('sulu_admin.delete'),
51+
];
4352
$listView = $this->viewBuilderFactory->createListViewBuilder(self::LOCATION_LIST_VIEW, '/locations')
4453
->setResourceKey(Location::RESOURCE_KEY)
4554
->setListKey(self::LOCATION_LIST_KEY)
4655
->setTitle('app.locations')
4756
->addListAdapters(['table'])
48-
->addToolbarActions([]);
57+
->setAddView(static::LOCATION_ADD_FORM_VIEW)
58+
->setEditView(static::LOCATION_EDIT_FORM_VIEW)
59+
->addToolbarActions($listToolbarActions);
4960
$viewCollection->add($listView);
61+
62+
$addFormView = $this->viewBuilderFactory->createResourceTabViewBuilder(self::LOCATION_ADD_FORM_VIEW, '/locations/add')
63+
->setResourceKey('locations')
64+
->setBackView(static::LOCATION_LIST_VIEW);
65+
$viewCollection->add($addFormView);
66+
67+
$addDetailsFormView = $this->viewBuilderFactory->createFormViewBuilder(self::LOCATION_ADD_FORM_VIEW . '.details', '/details')
68+
->setResourceKey('locations')
69+
->setFormKey('location_details')
70+
->setTabTitle('sulu_admin.details')
71+
->setEditView(static::LOCATION_EDIT_FORM_VIEW)
72+
->addToolbarActions([new ToolbarAction('sulu_admin.save')])
73+
->setParent(static::LOCATION_ADD_FORM_VIEW);
74+
$viewCollection->add($addDetailsFormView);
75+
76+
$editFormView = $this->viewBuilderFactory->createResourceTabViewBuilder(static::LOCATION_EDIT_FORM_VIEW, '/locations/:id')
77+
->setResourceKey('locations')
78+
->setBackView(static::LOCATION_LIST_VIEW)
79+
->setTitleProperty('title');
80+
$viewCollection->add($editFormView);
81+
82+
$formToolbarActions = [
83+
new ToolbarAction('sulu_admin.save'),
84+
new ToolbarAction('sulu_admin.delete'),
85+
];
86+
$editDetailsFormView = $this->viewBuilderFactory->createFormViewBuilder(static::LOCATION_EDIT_FORM_VIEW . '.details', '/details')
87+
->setResourceKey('locations')
88+
->setFormKey('location_details')
89+
->setTabTitle('sulu_admin.details')
90+
->addToolbarActions($formToolbarActions)
91+
->setParent(static::LOCATION_EDIT_FORM_VIEW);
92+
$viewCollection->add($editDetailsFormView);
5093
}
5194
}

src/Controller/Admin/LocationController.php

+110
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,85 @@
66

77
use App\Common\DoctrineListRepresentationFactory;
88
use App\Entity\Location;
9+
use App\Repository\LocationRepository;
910
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
1011
use Symfony\Component\HttpFoundation\Request;
1112
use Symfony\Component\HttpFoundation\Response;
13+
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
1214
use Symfony\Component\Routing\Annotation\Route;
1315

1416
class LocationController extends AbstractController
1517
{
18+
/**
19+
* @var LocationRepository
20+
*/
21+
private $locationRepository;
22+
1623
/**
1724
* @var DoctrineListRepresentationFactory
1825
*/
1926
private $doctrineListRepresentationFactory;
2027

2128
public function __construct(
29+
LocationRepository $repository,
2230
DoctrineListRepresentationFactory $doctrineListRepresentationFactory
2331
) {
32+
$this->locationRepository = $repository;
2433
$this->doctrineListRepresentationFactory = $doctrineListRepresentationFactory;
2534
}
2635

36+
/**
37+
* @Route("/admin/api/locations/{id}", methods={"GET"}, name="app.get_location")
38+
*/
39+
public function getAction(int $id, Request $request): Response
40+
{
41+
$location = $this->load($id);
42+
if (!$location) {
43+
throw new NotFoundHttpException();
44+
}
45+
46+
return $this->json($this->getDataForEntity($location));
47+
}
48+
49+
/**
50+
* @Route("/admin/api/locations/{id}", methods={"PUT"}, name="app.put_location")
51+
*/
52+
public function putAction(int $id, Request $request): Response
53+
{
54+
$location = $this->load($id);
55+
if (!$location) {
56+
throw new NotFoundHttpException();
57+
}
58+
59+
$this->mapDataToEntity($request->toArray(), $location);
60+
$this->save($location);
61+
62+
return $this->json($this->getDataForEntity($location));
63+
}
64+
65+
/**
66+
* @Route("/admin/api/locations", methods={"POST"}, name="app.post_location")
67+
*/
68+
public function postAction(Request $request): Response
69+
{
70+
$location = $this->create();
71+
72+
$this->mapDataToEntity($request->toArray(), $location);
73+
$this->save($location);
74+
75+
return $this->json($this->getDataForEntity($location), 201);
76+
}
77+
78+
/**
79+
* @Route("/admin/api/locations/{id}", methods={"DELETE"}, name="app.delete_location")
80+
*/
81+
public function deleteAction(int $id): Response
82+
{
83+
$this->remove($id);
84+
85+
return $this->json(null, 204);
86+
}
87+
2788
/**
2889
* @Route("/admin/api/locations", methods={"GET"}, name="app.get_location_list")
2990
*/
@@ -35,4 +96,53 @@ public function getListAction(Request $request): Response
3596

3697
return $this->json($listRepresentation->toArray());
3798
}
99+
100+
/**
101+
* @return array<string, mixed>
102+
*/
103+
protected function getDataForEntity(Location $entity): array
104+
{
105+
return [
106+
'id' => $entity->getId(),
107+
'name' => $entity->getName(),
108+
'street' => $entity->getStreet(),
109+
'number' => $entity->getNumber(),
110+
'postalCode' => $entity->getPostalCode(),
111+
'city' => $entity->getCity(),
112+
'countryCode' => $entity->getCountryCode(),
113+
];
114+
}
115+
116+
/**
117+
* @param array<string, mixed> $data
118+
*/
119+
protected function mapDataToEntity(array $data, Location $entity): void
120+
{
121+
$entity->setName($data['name']);
122+
$entity->setStreet($data['street'] ?? '');
123+
$entity->setNumber($data['number'] ?? '');
124+
$entity->setPostalCode($data['postalCode'] ?? '');
125+
$entity->setCity($data['city'] ?? '');
126+
$entity->setCountryCode($data['countryCode'] ?? '');
127+
}
128+
129+
protected function load(int $id): ?Location
130+
{
131+
return $this->locationRepository->findById($id);
132+
}
133+
134+
protected function create(): Location
135+
{
136+
return $this->locationRepository->create();
137+
}
138+
139+
protected function save(Location $entity): void
140+
{
141+
$this->locationRepository->save($entity);
142+
}
143+
144+
protected function remove(int $id): void
145+
{
146+
$this->locationRepository->remove($id);
147+
}
38148
}

src/Repository/LocationRepository.php

+25-1
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,33 @@ public function __construct(ManagerRegistry $registry)
2525

2626
public function create(): Location
2727
{
28-
$location = new Location();
28+
return new Location();
29+
}
30+
31+
public function remove(int $id): void
32+
{
33+
/** @var object $location */
34+
$location = $this->getEntityManager()->getReference(
35+
$this->getClassName(),
36+
$id
37+
);
38+
39+
$this->getEntityManager()->remove($location);
40+
$this->getEntityManager()->flush();
41+
}
2942

43+
public function save(Location $location): void
44+
{
3045
$this->getEntityManager()->persist($location);
46+
$this->getEntityManager()->flush();
47+
}
48+
49+
public function findById(int $id): ?Location
50+
{
51+
$location = $this->find($id);
52+
if (!$location) {
53+
return null;
54+
}
3155

3256
return $location;
3357
}

src/Service/CountryCodeSelect.php

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Service;
6+
7+
use Symfony\Component\Intl\Countries;
8+
9+
class CountryCodeSelect
10+
{
11+
/**
12+
* @return array[]
13+
*/
14+
public function getValues(): array
15+
{
16+
$values = [];
17+
18+
foreach (Countries::getNames() as $code => $title) {
19+
$values[] = [
20+
'name' => $code,
21+
'title' => $title,
22+
];
23+
}
24+
25+
return $values;
26+
}
27+
}

0 commit comments

Comments
 (0)