Skip to content

Commit 3e4873c

Browse files
author
Codeliner
committed
Merge branch 'AddVoyageFeature' into ChapterOneStory
2 parents 0266b7d + 54e1dfa commit 3e4873c

38 files changed

+1576
-33
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore

features/add_cargo.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Feature: Add a Cargo
2-
In order to ship a Cargo
2+
In order to handle a Cargo
33
As a booking manager
44
I need to be able to add a new Cargo
55

features/add_voyage.feature

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Feature: Add a Voyage
2+
In order to manage a Voyage
3+
As a booking manager
4+
I need to be able to add a new Voyage
5+
6+
@javascript
7+
Scenario: Add a new Voyage
8+
Given I am on "application/voyage/add"
9+
When I fill in "voyage_number" with "SHIP123"
10+
And I fill in "name" with "HongkongToHamburg"
11+
And I fill in "capacity" with "50"
12+
And I click the submit button
13+
Then the url should match "application/voyage/index"

features/bootstrap/FeatureContext.php

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,15 @@ static public function iniializeZendFramework()
5151
}
5252

5353
/**
54-
* @BeforeScenario
54+
* @BeforeFeature
5555
*/
56-
public function clearDatabase()
56+
public static function clearDatabase()
5757
{
58-
//to stuff here
59-
}
60-
61-
/**
62-
* @return ServiceManager
63-
*/
64-
private function getServiceManager()
65-
{
66-
return self::$zendApp->getServiceManager();
58+
$em = self::$zendApp->getServiceManager()->get('doctrine.entitymanager.orm_default');
59+
$q = $em->createQuery('delete from Application\Domain\Model\Cargo\Cargo');
60+
$q->execute();
61+
$q = $em->createQuery('delete from Application\Domain\Model\Voyage\Voyage');
62+
$q->execute();
6763
}
6864

6965
/**

module/Application/config/module.config.php

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,40 @@
5959
),
6060
),
6161
),
62+
'voyagenumber' => array(
63+
'type' => 'Segment',
64+
'options' => array(
65+
'route' => '/voyagenumber/[:voyagenumber]',
66+
'constraints' => array(
67+
'voyagenumber' => '[a-zA-Z0-9_-]*',
68+
),
69+
'defaults' => array(
70+
),
71+
),
72+
),
6273
),
6374
),
6475
),
6576
),
6677
),
6778
),
6879
'service_manager' => array(
80+
'invokables' => array(
81+
'overbooking_policy' => 'Application\Service\Policy\TenPercentOverbookingPolicy',
82+
),
6983
'factories' => array(
7084
'main_navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory',
7185
'cargo_form' => 'Application\Form\Service\CargoFormFactory',
86+
'voyage_form' => 'Application\Form\Service\VoyageFormFactory',
87+
'booking_service' => 'Application\Service\Factory\BookingServiceFactory',
7288
'cargo_repository' => function($sl) {
7389
$em = $sl->get('doctrine.entitymanager.orm_default');
7490
return $em->getRepository('Application\Domain\Model\Cargo\Cargo');
7591
},
92+
'voyage_repository' => function($sl) {
93+
$em = $sl->get('doctrine.entitymanager.orm_default');
94+
return $em->getRepository('Application\Domain\Model\Voyage\Voyage');
95+
}
7696
),
7797
'abstract_factories' => array(
7898
'Zend\Cache\Service\StorageCacheAbstractServiceFactory',
@@ -104,8 +124,26 @@
104124

105125
$cargoController = new Application\Controller\CargoController();
106126
$cargoController->setCargoRepository($cargoRepository);
127+
$cargoController->setVoyageRepository($serviceManager->get('voyage_repository'));
107128
$cargoController->setCargoForm($serviceManager->get('cargo_form'));
108129
return $cargoController;
130+
},
131+
'Application\Controller\Voyage' => function($controllerLoader) {
132+
$serviceManager = $controllerLoader->getServiceLocator();
133+
134+
$voyageController = new Application\Controller\VoyageController();
135+
$voyageController->setVoyageForm($serviceManager->get('voyage_form'));
136+
$voyageController->setVoyageRepository($serviceManager->get('voyage_repository'));
137+
return $voyageController;
138+
},
139+
'Application\Controller\Booking' => function($controllerLoader) {
140+
$serviceManager = $controllerLoader->getServiceLocator();
141+
142+
$bookingController = new Application\Controller\BookingController();
143+
$bookingController->setCargoRepository($serviceManager->get('cargo_repository'));
144+
$bookingController->setVoyageRepository($serviceManager->get('voyage_repository'));
145+
$bookingController->setBookingService($serviceManager->get('booking_service'));
146+
return $bookingController;
109147
}
110148
)
111149
),
@@ -130,8 +168,8 @@
130168
'orm_default' => array(
131169
//Define custom doctrine types to map the ddd value objects
132170
'types' => array(
133-
'uid' => 'Application\Infrastructure\Persistence\Doctrine\Type\UID',
134171
'trackingid' => 'Application\Infrastructure\Persistence\Doctrine\Type\TrackingId',
172+
'voyagenumber' => 'Application\Infrastructure\Persistence\Doctrine\Type\VoyageNumber',
135173
),
136174
),
137175
),
@@ -140,7 +178,8 @@
140178
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
141179
'cache' => 'array',
142180
'paths' => array(
143-
__DIR__ . '/../src/Application/Domain/Model/Cargo/'
181+
__DIR__ . '/../src/Application/Domain/Model/Cargo/',
182+
__DIR__ . '/../src/Application/Domain/Model/Voyage/'
144183
)
145184
),
146185
'orm_default' => array(
@@ -173,6 +212,24 @@
173212
'label' => 'add Cargo'
174213
)
175214
)
215+
),
216+
'voyage' => array(
217+
'type' => 'uri',
218+
'label' => 'Voyage',
219+
'pages' => array(
220+
'list' => array(
221+
'route' => 'application/default',
222+
'controller' => 'voyage',
223+
'action' => 'index',
224+
'label' => 'list Voyages'
225+
),
226+
'add' => array(
227+
'route' => 'application/default',
228+
'controller' => 'voyage',
229+
'action' => 'add',
230+
'label' => 'add Voyage'
231+
)
232+
)
176233
)
177234
)
178235
),
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<?php
2+
/*
3+
* This file is part of the codeliner/php-ddd-cargo-sample package.
4+
* (c) Alexander Miertsch <[email protected]>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
namespace Application\Controller;
10+
11+
use Zend\Mvc\Controller\AbstractActionController;
12+
use Zend\View\Model\ViewModel;
13+
use Zend\Validator\StringLength;
14+
use Zend\Validator\Regex;
15+
use Application\Domain\Model\Cargo;
16+
use Application\Domain\Model\Voyage;
17+
use Application\Service\BookingService;
18+
use Application\Service\Exception\ServiceException;
19+
use Application\Service\Exception\RuntimeException;
20+
/**
21+
* MVC Controller that manages the booking process of Voyage.
22+
*
23+
* @author Alexander Miertsch <[email protected]>
24+
*/
25+
class BookingController extends AbstractActionController
26+
{
27+
/**
28+
* The CargoRepository
29+
*
30+
* @var Cargo\CargoRepositoryInterface
31+
*/
32+
protected $cargoRepository;
33+
34+
/**
35+
*
36+
* @var Voyage\VoyageRepositoryInterface
37+
*/
38+
protected $voyageRepository;
39+
40+
/**
41+
*
42+
* @var BookingService
43+
*/
44+
protected $bookingService;
45+
46+
/**
47+
* Book a Cargo on a Voyage
48+
*/
49+
public function bookingAction()
50+
{
51+
//we use the post redirect get pattern and redirect to same location
52+
$prg = $this->prg();
53+
54+
if ($prg instanceof \Zend\Http\PhpEnvironment\Response) {
55+
// returned a response to redirect us
56+
return $prg;
57+
} elseif ($prg === false) {
58+
throw new RuntimeException('Request is out of date.');
59+
}
60+
61+
try {
62+
$trackingId = $prg['tracking_id'];
63+
64+
if (empty($trackingId)) {
65+
throw new RuntimeException('TrackingId must not be empty');
66+
}
67+
68+
$strLengthVal = new StringLength(1, 13);
69+
$regexVal = new Regex('/^[a-zA-Z0-9_-]+$/');
70+
71+
if (!$strLengthVal->isValid($trackingId) || !$regexVal->isValid($trackingId)) {
72+
throw new RuntimeException('TrackingId is invalid');
73+
}
74+
75+
$voyageNumber = $prg['voyage_number'];
76+
77+
if (empty($voyageNumber)) {
78+
throw new RuntimeException('VoyageNumber must not be empty');
79+
}
80+
81+
$strLengthVal = new StringLength(3, 30);
82+
$regexVal = new Regex('/^[a-zA-Z0-9_-]+$/');
83+
84+
if (!$strLengthVal->isValid($voyageNumber) || !$regexVal->isValid($voyageNumber)) {
85+
throw new RuntimeException('VoyageNumber is invalid');
86+
}
87+
88+
$cargo = $this->cargoRepository->findCargo(new Cargo\TrackingId($trackingId));
89+
90+
if (is_null($cargo)) {
91+
throw new RuntimeException('Cargo can not be found');
92+
}
93+
94+
$voyage = $this->voyageRepository->findVoyage(new Voyage\VoyageNumber($voyageNumber));
95+
96+
if (is_null($voyage)) {
97+
throw new RuntimeException('Voyage can not be found');
98+
}
99+
100+
$this->bookingService->bookNewCargo($cargo, $voyage);
101+
102+
return array('msg' => 'Cargo was successfully booked', 'success' => true);
103+
104+
} catch (ServiceException $ex) {
105+
return array('msg' => $ex->getMessage(), 'success' => false);
106+
}
107+
}
108+
109+
/**
110+
* Set the CargoRepository
111+
*
112+
* @param Cargo\CargoRepositoryInterface $cargoRepository
113+
* @return void
114+
*/
115+
public function setCargoRepository(Cargo\CargoRepositoryInterface $cargoRepository)
116+
{
117+
$this->cargoRepository = $cargoRepository;
118+
}
119+
120+
/**
121+
* Set the voyage repository
122+
*
123+
* @param Voyage\VoyageRepositoryInterface $voyageRepository
124+
* @return void
125+
*/
126+
public function setVoyageRepository(Voyage\VoyageRepositoryInterface $voyageRepository)
127+
{
128+
$this->voyageRepository = $voyageRepository;
129+
}
130+
131+
/**
132+
* Set BookingService
133+
*
134+
* @param BookingService $bookingService
135+
* @return void
136+
*/
137+
public function setBookingService(BookingService $bookingService)
138+
{
139+
$this->bookingService = $bookingService;
140+
}
141+
}

module/Application/src/Application/Controller/CargoController.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Zend\Mvc\Controller\AbstractActionController;
1212
use Zend\View\Model\ViewModel;
1313
use Application\Domain\Model\Cargo;
14+
use Application\Domain\Model\Voyage\VoyageRepositoryInterface;
1415
use Application\Form\CargoForm;
1516
/**
1617
* MVC Controller for Cargo Management
@@ -26,6 +27,13 @@ class CargoController extends AbstractActionController
2627
*/
2728
protected $cargoRepository;
2829

30+
/**
31+
*
32+
* @var VoyageRepositoryInterface
33+
*/
34+
protected $voyageRepository;
35+
36+
2937
/**
3038
*
3139
* @var CargoForm
@@ -56,7 +64,13 @@ public function showAction()
5664
throw new \RuntimeException('Cargo can not be found. Please check the trackingId!');
5765
}
5866

59-
return array('cargo' => $cargo);
67+
if ($cargo->isBooked()) {
68+
$voyages = array();
69+
} else {
70+
$voyages = $this->voyageRepository->findAll();
71+
}
72+
73+
return array('cargo' => $cargo, 'voyages' => $voyages);
6074
}
6175

6276
public function addAction()
@@ -103,6 +117,17 @@ public function setCargoRepository(Cargo\CargoRepositoryInterface $cargoReposito
103117
$this->cargoRepository = $cargoRepository;
104118
}
105119

120+
/**
121+
* Set the voyage repository
122+
*
123+
* @param VoyageRepositoryInterface $voyageRepository
124+
* @return void
125+
*/
126+
public function setVoyageRepository(VoyageRepositoryInterface $voyageRepository)
127+
{
128+
$this->voyageRepository = $voyageRepository;
129+
}
130+
106131
/**
107132
* Set a cargo form.
108133
*

0 commit comments

Comments
 (0)