diff --git a/config/forms/location_details.xml b/config/forms/location_details.xml
new file mode 100644
index 0000000..95df596
--- /dev/null
+++ b/config/forms/location_details.xml
@@ -0,0 +1,53 @@
+
+
diff --git a/config/packages/sulu_admin.yaml b/config/packages/sulu_admin.yaml
index 6e1a371..a669187 100644
--- a/config/packages/sulu_admin.yaml
+++ b/config/packages/sulu_admin.yaml
@@ -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:
diff --git a/config/services.yaml b/config/services.yaml
index 86b2bda..6ce490d 100644
--- a/config/services.yaml
+++ b/config/services.yaml
@@ -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'
diff --git a/src/Admin/LocationAdmin.php b/src/Admin/LocationAdmin.php
index f713a57..fed0ad9 100644
--- a/src/Admin/LocationAdmin.php
+++ b/src/Admin/LocationAdmin.php
@@ -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;
@@ -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
*/
@@ -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);
}
}
diff --git a/src/Controller/Admin/LocationController.php b/src/Controller/Admin/LocationController.php
index b3e251a..c454ae2 100644
--- a/src/Controller/Admin/LocationController.php
+++ b/src/Controller/Admin/LocationController.php
@@ -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")
*/
@@ -35,4 +96,53 @@ public function getListAction(Request $request): Response
return $this->json($listRepresentation->toArray());
}
+
+ /**
+ * @return array
+ */
+ 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 $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);
+ }
}
diff --git a/src/Repository/LocationRepository.php b/src/Repository/LocationRepository.php
index 8c52ba6..7d873c9 100644
--- a/src/Repository/LocationRepository.php
+++ b/src/Repository/LocationRepository.php
@@ -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;
}
diff --git a/src/Service/CountryCodeSelect.php b/src/Service/CountryCodeSelect.php
new file mode 100644
index 0000000..3323d5d
--- /dev/null
+++ b/src/Service/CountryCodeSelect.php
@@ -0,0 +1,27 @@
+ $title) {
+ $values[] = [
+ 'name' => $code,
+ 'title' => $title,
+ ];
+ }
+
+ return $values;
+ }
+}
diff --git a/tests/Functional/Controller/Admin/LocationControllerTest.php b/tests/Functional/Controller/Admin/LocationControllerTest.php
index be627c1..67db186 100644
--- a/tests/Functional/Controller/Admin/LocationControllerTest.php
+++ b/tests/Functional/Controller/Admin/LocationControllerTest.php
@@ -46,4 +46,189 @@ public function testGetList(): void
$this->assertSame($location1->getName(), $items[0]['name']);
$this->assertSame($location2->getName(), $items[1]['name']);
}
+
+ public function testGet(): void
+ {
+ $location = $this->createLocation('Sulu');
+
+ $this->client->jsonRequest('GET', '/admin/api/locations/' . $location->getId());
+
+ $response = $this->client->getResponse();
+ $this->assertInstanceOf(Response::class, $response);
+ $result = json_decode($response->getContent() ?: '', true);
+ $this->assertHttpStatusCode(200, $response);
+
+ $this->assertSame($location->getId(), $result['id']);
+ $this->assertSame($location->getName(), $result['name']);
+ }
+
+ public function testPost(): void
+ {
+ $this->client->jsonRequest(
+ 'POST',
+ '/admin/api/locations',
+ [
+ 'name' => 'Sulu',
+ 'street' => 'Teststreet',
+ 'number' => '42',
+ 'postalCode' => '6850',
+ 'city' => 'Dornbirn',
+ 'countryCode' => 'AT',
+ ]
+ );
+
+ $response = $this->client->getResponse();
+ $this->assertInstanceOf(Response::class, $response);
+ $result = json_decode($response->getContent() ?: '', true);
+ $this->assertHttpStatusCode(201, $response);
+
+ $this->assertArrayHasKey('id', $result);
+ $this->assertNotNull($result['id']);
+ $this->assertSame('Sulu', $result['name']);
+ $this->assertSame('Teststreet', $result['street']);
+ $this->assertSame('42', $result['number']);
+ $this->assertSame('6850', $result['postalCode']);
+ $this->assertSame('Dornbirn', $result['city']);
+ $this->assertSame('AT', $result['countryCode']);
+
+ $result = $this->findLocationById($result['id']);
+
+ $this->assertNotNull($result);
+ $this->assertSame('Sulu', $result->getName());
+ $this->assertSame('Teststreet', $result->getStreet());
+ $this->assertSame('42', $result->getNumber());
+ $this->assertSame('6850', $result->getPostalCode());
+ $this->assertSame('Dornbirn', $result->getCity());
+ $this->assertSame('AT', $result->getCountryCode());
+ }
+
+ public function testPostNullValues(): void
+ {
+ $this->client->jsonRequest(
+ 'POST',
+ '/admin/api/locations',
+ [
+ 'name' => 'Sulu',
+ ]
+ );
+
+ $response = $this->client->getResponse();
+ $this->assertInstanceOf(Response::class, $response);
+ $result = json_decode($response->getContent() ?: '', true);
+ $this->assertHttpStatusCode(201, $response);
+
+ $this->assertArrayHasKey('id', $result);
+ $this->assertNotNull($result['id']);
+ $this->assertSame('Sulu', $result['name']);
+ $this->assertEmpty($result['street']);
+ $this->assertEmpty($result['number']);
+ $this->assertEmpty($result['postalCode']);
+ $this->assertEmpty($result['city']);
+ $this->assertEmpty($result['countryCode']);
+
+ $result = $this->findLocationById($result['id']);
+
+ $this->assertNotNull($result);
+ $this->assertSame('Sulu', $result->getName());
+ $this->assertEmpty($result->getStreet());
+ $this->assertEmpty($result->getNumber());
+ $this->assertEmpty($result->getPostalCode());
+ $this->assertEmpty($result->getCity());
+ $this->assertEmpty($result->getCountryCode());
+ }
+
+ public function testPut(): void
+ {
+ $location = $this->createLocation('Symfony');
+
+ $this->client->jsonRequest(
+ 'PUT',
+ '/admin/api/locations/' . $location->getId(),
+ [
+ 'name' => 'Sulu',
+ 'street' => 'Teststreet',
+ 'number' => '42',
+ 'postalCode' => '6850',
+ 'city' => 'Dornbirn',
+ 'countryCode' => 'AT',
+ ]
+ );
+
+ $response = $this->client->getResponse();
+ $this->assertInstanceOf(Response::class, $response);
+ $result = json_decode($response->getContent() ?: '', true);
+ $this->assertHttpStatusCode(200, $response);
+
+ $this->assertArrayHasKey('id', $result);
+ $this->assertNotNull($result['id']);
+ $this->assertSame('Sulu', $result['name']);
+ $this->assertSame('Teststreet', $result['street']);
+ $this->assertSame('42', $result['number']);
+ $this->assertSame('6850', $result['postalCode']);
+ $this->assertSame('Dornbirn', $result['city']);
+ $this->assertSame('AT', $result['countryCode']);
+
+ $result = $this->findLocationById($result['id']);
+
+ $this->assertNotNull($result);
+ $this->assertSame('Sulu', $result->getName());
+ $this->assertSame('Teststreet', $result->getStreet());
+ $this->assertSame('42', $result->getNumber());
+ $this->assertSame('6850', $result->getPostalCode());
+ $this->assertSame('Dornbirn', $result->getCity());
+ $this->assertSame('AT', $result->getCountryCode());
+ }
+
+ public function testPutNullValues(): void
+ {
+ $location = $this->createLocation('Symfony');
+
+ $this->client->jsonRequest(
+ 'PUT',
+ '/admin/api/locations/' . $location->getId(),
+ [
+ 'name' => 'Sulu',
+ ]
+ );
+
+ $response = $this->client->getResponse();
+ $this->assertInstanceOf(Response::class, $response);
+ $result = json_decode($response->getContent() ?: '', true);
+ $this->assertHttpStatusCode(200, $response);
+
+ $this->assertArrayHasKey('id', $result);
+ $this->assertNotNull($result['id']);
+ $this->assertSame('Sulu', $result['name']);
+ $this->assertEmpty($result['street']);
+ $this->assertEmpty($result['number']);
+ $this->assertEmpty($result['postalCode']);
+ $this->assertEmpty($result['city']);
+ $this->assertEmpty($result['countryCode']);
+
+ $result = $this->findLocationById($result['id']);
+
+ $this->assertNotNull($result);
+ $this->assertSame('Sulu', $result->getName());
+ $this->assertEmpty($result->getStreet());
+ $this->assertEmpty($result->getNumber());
+ $this->assertEmpty($result->getPostalCode());
+ $this->assertEmpty($result->getCity());
+ $this->assertEmpty($result->getCountryCode());
+ }
+
+ public function testDelete(): void
+ {
+ $location = $this->createLocation('Symfony');
+
+ /** @var int $locationId */
+ $locationId = $location->getId();
+
+ $this->client->jsonRequest('DELETE', '/admin/api/locations/' . $location->getId());
+
+ $response = $this->client->getResponse();
+ $this->assertInstanceOf(Response::class, $response);
+ $this->assertHttpStatusCode(204, $response);
+
+ $this->assertNull($this->findLocationById($locationId));
+ }
}
diff --git a/tests/Functional/Traits/LocationTrait.php b/tests/Functional/Traits/LocationTrait.php
index d40c142..4a846e0 100644
--- a/tests/Functional/Traits/LocationTrait.php
+++ b/tests/Functional/Traits/LocationTrait.php
@@ -26,6 +26,11 @@ public function createLocation(string $name): Location
return $location;
}
+ public function findLocationById(int $id): ?Location
+ {
+ return $this->getLocationRepository()->findById($id);
+ }
+
protected function getLocationRepository(): LocationRepository
{
return static::getEntityManager()->getRepository(Location::class);