Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Guardians of the Kretschmar Elock System
Doorcode
Commits
7d9dcf3f
Commit
7d9dcf3f
authored
May 17, 2020
by
Jacob Priddy
👌
Browse files
Overrides can now only have one active at a time and can be updated
Added use case for generating responses
parent
02ce4ebd
Changes
23
Hide whitespace changes
Inline
Side-by-side
src/web/backend/app/Http/Controllers/OverridesController.php
View file @
7d9dcf3f
...
...
@@ -17,11 +17,11 @@ class OverridesController extends ApiController
{
/**
* @param \Source\UseCases\Overrides\OverrideCreate\OverrideCreateUseCase $overrideCreate
* @param \App\Guards\ApiGuard $apiGuard
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Exception
*/
public
function
create
(
OverrideCreateUseCase
$overrideCreate
,
ApiGuard
$apiGuard
):
JsonResponse
{
...
...
@@ -29,7 +29,7 @@ class OverridesController extends ApiController
$this
->
validate
(
$this
->
request
,
[
'reason'
=>
'required|string|max:1024'
,
'door_id'
=>
'required|integer'
,
'type'
=>
'required|integer|between:'
.
Override
::
TYPE_OPEN
.
','
.
Override
::
TYPE_
NORMAL
,
'type'
=>
'required|integer|between:'
.
Override
::
TYPE_OPEN
.
','
.
Override
::
TYPE_
LOCKED
,
'start'
=>
'required|date|before:end'
,
'end'
=>
'required|date|after:start'
,
]);
...
...
src/web/backend/database/migrations/2020_05_17_041747_create_overrides_table.php
View file @
7d9dcf3f
...
...
@@ -13,6 +13,9 @@ class CreateOverridesTable extends Migration
*/
public
function
up
():
void
{
/*
* Only one override can be active at a time
*/
Schema
::
create
(
'overrides'
,
static
function
(
Blueprint
$table
)
{
$table
->
id
();
$table
->
string
(
'reason'
);
...
...
src/web/backend/src/Entities/Override.php
View file @
7d9dcf3f
...
...
@@ -10,7 +10,6 @@ class Override
{
public
const
TYPE_OPEN
=
0
;
public
const
TYPE_LOCKED
=
1
;
public
const
TYPE_NORMAL
=
2
;
protected
int
$id
;
...
...
@@ -53,7 +52,7 @@ class Override
?Carbon
$createdAt
=
null
,
?Carbon
$updatedAt
=
null
)
{
if
(
$type
>
self
::
TYPE_
NORMAL
||
$type
<
self
::
TYPE_OPEN
)
{
if
(
$type
>
self
::
TYPE_
LOCKED
||
$type
<
self
::
TYPE_OPEN
)
{
throw
new
InvalidArgumentException
(
'Type not valid override type.'
);
}
...
...
@@ -161,4 +160,22 @@ class Override
return
$date
->
isAfter
(
$this
->
getStart
());
}
/**
* @param int $type
* @return bool
*/
public
function
hasTypeOf
(
int
$type
):
bool
{
return
$this
->
getType
()
===
$type
;
}
/**
* @param string $id
* @return bool
*/
public
function
hasIdOf
(
string
$id
):
bool
{
return
$this
->
getId
()
===
$id
;
}
}
src/web/backend/src/Entities/Schedule.php
View file @
7d9dcf3f
...
...
@@ -178,6 +178,10 @@ class Schedule
return
$date
->
isAfter
(
$this
->
getStart
());
}
/**
* @param int|null $type
* @return bool
*/
public
function
hasTypeOf
(
?int
$type
):
bool
{
return
$this
->
type
===
$type
;
...
...
src/web/backend/src/Gateways/DoorSchedule/DatabaseDoorScheduleRepository.php
View file @
7d9dcf3f
...
...
@@ -12,8 +12,6 @@ class DatabaseDoorScheduleRepository implements DoorScheduleRepository
{
use
CastsTo
;
protected
const
DB_DATE_FORMAT
=
'Y-m-d H:i:s'
;
/**
* @var \Illuminate\Database\ConnectionInterface
*/
...
...
@@ -29,16 +27,17 @@ class DatabaseDoorScheduleRepository implements DoorScheduleRepository
*/
public
function
getActiveSchedulesForDoor
(
string
$doorId
):
array
{
$
openModeT
ype
=
Schedule
::
TYPE_OPEN_MODE
;
$
t
ype
=
Schedule
::
TYPE_OPEN_MODE
;
$query
=
<<<QUERY
select S.id, S.group_id, S.type, S.rset, S.start, S.end, S.duration_ms, S.description, S.created_at, S.updated_at
FROM schedules as S
INNER JOIN door_group AS DG ON DG.group_id = S.group_id AND DG.door_id =
?
WHERE S.type =
$openModeType
AND ((CURRENT_DATE BETWEEN S.start AND S.end) OR (CURRENT_DATE > S.start AND S.end IS NULL))
INNER JOIN door_group AS DG ON DG.group_id = S.group_id AND DG.door_id =
:DOOR_ID
WHERE S.type =
:TYPE
AND ((CURRENT_DATE BETWEEN S.start AND S.end) OR (CURRENT_DATE > S.start AND S.end IS NULL))
QUERY;
$schedules
=
$this
->
db
->
select
(
$query
,
[
$this
->
castToInt
(
$doorId
),
':DOOR_ID'
=>
$this
->
castToInt
(
$doorId
),
':TYPE'
=>
$this
->
castToInt
(
$type
),
]);
return
array_map
(
function
(
$schedule
)
{
...
...
@@ -49,10 +48,10 @@ QUERY;
$schedule
->
rset
,
$schedule
->
duration_ms
,
$schedule
->
description
,
$this
->
castTo
Date
(
$schedule
->
start
),
$this
->
castTo
Date
(
$schedule
->
end
),
$this
->
castTo
Date
(
$schedule
->
created_at
),
$this
->
castTo
Date
(
$schedule
->
updated_at
)
$this
->
castTo
Carbon
(
$schedule
->
start
),
$this
->
castTo
Carbon
(
$schedule
->
end
),
$this
->
castTo
Carbon
(
$schedule
->
created_at
),
$this
->
castTo
Carbon
(
$schedule
->
updated_at
)
);
},
$schedules
);
}
...
...
@@ -60,25 +59,23 @@ QUERY;
/**
* @inheritDoc
*/
public
function
getSchedulesForDorBetween
(
string
$doorId
,
Carbon
$begin
,
Carbon
$end
,
int
$type
=
Schedule
::
TYPE_OPEN_MODE
):
array
public
function
getSchedulesForDo
o
rBetween
(
string
$doorId
,
Carbon
$begin
,
Carbon
$end
,
int
$type
=
Schedule
::
TYPE_OPEN_MODE
):
array
{
$format
=
self
::
DB_DATE_FORMAT
;
$query
=
<<<QUERY
select S.id, S.group_id, S.type, S.rset, S.start, S.end, S.duration_ms, S.description, S.created_at, S.updated_at
FROM schedules as S
INNER JOIN door_group AS DG ON DG.group_id = S.group_id AND DG.door_id = :DOOR_ID
WHERE S.type = :TYPE AND (((
to_timestamp(:BEGIN, '$format'), to_timestamp(:END, '$format')
) OVERLAPS (s.start, S.end))
OR (S.start < to_timestamp(:END, '$format')
AND S.end IS NULL))
WHERE S.type = :TYPE AND (((
:BEGIN, :END
) OVERLAPS (s.start, S.end))
OR (S.start < :END
AND S.end IS NULL))
QUERY;
$schedules
=
$this
->
db
->
select
(
$query
,
[
':TYPE'
=>
$this
->
castToInt
(
$type
),
':DOOR_ID'
=>
$this
->
castToInt
(
$doorId
),
':BEGIN'
=>
$begin
->
format
(
self
::
DB_DATE_FORMAT
),
':END'
=>
$end
->
format
(
self
::
DB_DATE_FORMAT
),
':TYPE'
=>
$this
->
castToInt
(
$type
),
':BEGIN'
=>
$begin
,
':END'
=>
$end
,
]);
return
array_map
(
function
(
$schedule
)
{
return
new
Schedule
(
$schedule
->
id
,
...
...
@@ -87,10 +84,10 @@ QUERY;
$schedule
->
rset
,
$schedule
->
duration_ms
,
$schedule
->
description
,
$this
->
castTo
Date
(
$schedule
->
start
),
$this
->
castTo
Date
(
$schedule
->
end
),
$this
->
castTo
Date
(
$schedule
->
created_at
),
$this
->
castTo
Date
(
$schedule
->
updated_at
)
$this
->
castTo
Carbon
(
$schedule
->
start
),
$this
->
castTo
Carbon
(
$schedule
->
end
),
$this
->
castTo
Carbon
(
$schedule
->
created_at
),
$this
->
castTo
Carbon
(
$schedule
->
updated_at
)
);
},
$schedules
);
}
...
...
src/web/backend/src/Gateways/DoorSchedule/DoorScheduleRepository.php
View file @
7d9dcf3f
...
...
@@ -21,5 +21,5 @@ interface DoorScheduleRepository
* @param int $type
* @return \Source\Entities\Schedule[]
*/
public
function
getSchedulesForDorBetween
(
string
$doorId
,
Carbon
$begin
,
Carbon
$end
,
int
$type
=
Schedule
::
TYPE_OPEN_MODE
):
array
;
public
function
getSchedulesForDo
o
rBetween
(
string
$doorId
,
Carbon
$begin
,
Carbon
$end
,
int
$type
=
Schedule
::
TYPE_OPEN_MODE
):
array
;
}
src/web/backend/src/Gateways/DoorSchedule/InMemoryDoorScheduleRepository.php
View file @
7d9dcf3f
...
...
@@ -37,7 +37,7 @@ class InMemoryDoorScheduleRepository implements DoorScheduleRepository
/**
* @inheritDoc
*/
public
function
getSchedulesForDorBetween
(
string
$doorId
,
Carbon
$begin
,
Carbon
$end
,
int
$type
=
Schedule
::
TYPE_OPEN_MODE
):
array
public
function
getSchedulesForDo
o
rBetween
(
string
$doorId
,
Carbon
$begin
,
Carbon
$end
,
int
$type
=
Schedule
::
TYPE_OPEN_MODE
):
array
{
if
(
!
isset
(
$this
->
doorScheduleMap
[
$doorId
]))
{
return
[];
...
...
src/web/backend/src/Gateways/DoorUser/DatabaseDoorUserRepository.php
View file @
7d9dcf3f
...
...
@@ -43,8 +43,8 @@ QUERY;
$group
->
id
,
$group
->
title
,
$group
->
description
,
$this
->
castTo
Date
(
$group
->
created_at
),
$this
->
castTo
Date
(
$group
->
updated_at
)
$this
->
castTo
Carbon
(
$group
->
created_at
),
$this
->
castTo
Carbon
(
$group
->
updated_at
)
);
},
$commonGroups
);
}
...
...
src/web/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php
View file @
7d9dcf3f
...
...
@@ -6,12 +6,23 @@ namespace Source\Gateways\Overrides;
use
Carbon\Carbon
;
use
Source\Sanitize\CastsTo
;
use
Source\Entities\Override
;
use
Illuminate\Database\Eloquent\Builder
;
use
Illuminate\Database\ConnectionInterface
;
use
Source\Exceptions\EntityNotFoundException
;
class
DatabaseOverridesRepository
implements
OverridesRepository
{
use
CastsTo
;
/**
* @var \Illuminate\Database\ConnectionInterface
*/
protected
ConnectionInterface
$db
;
public
function
__construct
(
ConnectionInterface
$db
)
{
$this
->
db
=
$db
;
}
/**
* @param \App\Override $override
* @return \Source\Entities\Override
...
...
@@ -31,6 +42,25 @@ class DatabaseOverridesRepository implements OverridesRepository
);
}
/**
* @param $override
* @return \Source\Entities\Override
*/
protected
function
toOverrideFromRaw
(
$override
):
Override
{
return
new
Override
(
$override
->
id
,
$override
->
reason
,
$override
->
user_id
,
$override
->
door_id
,
$override
->
type
,
$this
->
castToCarbon
(
$override
->
start
),
$this
->
castToCarbon
(
$override
->
end
),
$this
->
castToCarbon
(
$override
->
created_at
),
$this
->
castToCarbon
(
$override
->
updated_at
)
);
}
/**
* @inheritDoc
*/
...
...
@@ -38,6 +68,7 @@ class DatabaseOverridesRepository implements OverridesRepository
{
$overrides
=
\
App\Override
::
query
()
->
where
(
'door_id'
,
$this
->
castToInt
(
$doorId
))
->
orderByDesc
(
'created_at'
)
->
get
()
->
values
()
->
all
();
return
array_map
(
static
function
(
\
App\Override
$override
)
{
...
...
@@ -50,37 +81,48 @@ class DatabaseOverridesRepository implements OverridesRepository
*/
public
function
overrideHistoryBetween
(
Carbon
$begin
,
Carbon
$end
):
array
{
$overrides
=
\
App\Override
::
query
()
->
whereBetween
(
'start'
,
[
$begin
,
$end
])
->
orWhereBetween
(
'end'
,
[
$begin
,
$end
])
->
orWhere
(
static
function
(
Builder
$query
)
use
(
$begin
,
$end
)
{
$query
->
where
(
'start'
,
'<'
,
$begin
)
->
where
(
'end'
,
'>'
,
$end
);
})
->
get
()
->
values
()
->
all
();
return
array_map
(
static
function
(
\
App\Override
$override
)
{
return
self
::
toOverride
(
$override
);
$query
=
<<<QUERY
select A.id, A.reason, A.user_id, A.door_id, A.type, A.start, A.end, A.created_at, A.updated_at
from overrides as A
WHERE ((:BEGIN, :END) OVERLAPS (A.start, A.end))
ORDER BY A.created_at DESC
QUERY;
$overrides
=
$this
->
db
->
select
(
$query
,
[
':BEGIN'
=>
$begin
,
':END'
=>
$end
,
]);
return
array_map
(
function
(
$override
)
{
return
$this
->
toOverrideFromRaw
(
$override
);
},
$overrides
);
}
/**
* @inheritDoc
*/
public
function
activeOverrideForDoor
(
string
$doorId
,
Carbon
$
date
):
?Override
public
function
activeOverrideForDoor
Between
(
string
$doorId
,
Carbon
$
begin
,
Carbon
$end
):
?Override
{
/** @var \App\Override|null $override */
$override
=
\
App\Override
::
query
()
->
where
(
'door_id'
,
$this
->
castToInt
(
$doorId
))
->
where
(
'start'
,
'<'
,
$date
)
->
where
(
'end'
,
'>'
,
$date
)
->
orderByDesc
(
'created_at'
)
->
first
();
$query
=
<<<QUERY
select A.id, A.reason, A.user_id, A.door_id, A.type, A.start, A.end, A.created_at, A.updated_at
from overrides as A
WHERE A.door_id = :DOOR_ID
AND ((:BEGIN, :END) OVERLAPS (A.start, A.end))
ORDER BY A.created_at DESC
LIMIT 1
QUERY;
$override
=
$this
->
db
->
selectOne
(
$query
,
[
':DOOR_ID'
=>
$this
->
castToInt
(
$doorId
),
':BEGIN'
=>
$begin
,
':END'
=>
$end
,
]);
if
(
!
$override
)
{
return
null
;
}
return
self
::
toOverride
(
$override
);
return
$this
->
toOverride
FromRaw
(
$override
);
}
/**
...
...
@@ -106,4 +148,27 @@ class DatabaseOverridesRepository implements OverridesRepository
return
self
::
toOverride
(
$o
);
}
/**
* @inheritDoc
*/
public
function
updateOverride
(
string
$overrideId
,
Override
$override
):
?Override
{
/** @var \App\Override $o */
$o
=
\
App\Override
::
query
()
->
find
(
$this
->
castToInt
(
$overrideId
));
if
(
!
$o
)
{
throw
new
EntityNotFoundException
(
'Override with id "'
.
$overrideId
.
'" does not exist.'
);
}
$o
->
setAttribute
(
'start'
,
$override
->
getStart
());
$o
->
setAttribute
(
'end'
,
$override
->
getEnd
());
$o
->
setAttribute
(
'reason'
,
$override
->
getReason
());
if
(
!
$o
->
save
())
{
return
null
;
}
return
self
::
toOverride
(
$o
);
}
}
src/web/backend/src/Gateways/Overrides/InMemoryOverridesRepository.php
View file @
7d9dcf3f
...
...
@@ -8,6 +8,9 @@ use Source\Entities\Override;
class
InMemoryOverridesRepository
implements
OverridesRepository
{
/**
* @var \Source\Entities\Override[]
*/
protected
array
$overrides
=
[];
/**
...
...
@@ -33,24 +36,33 @@ class InMemoryOverridesRepository implements OverridesRepository
/**
* @inheritDoc
*/
public
function
activeOverrideForDoor
(
string
$doorId
,
Carbon
$
date
):
?Override
public
function
activeOverrideForDoor
Between
(
string
$doorId
,
Carbon
$
begin
,
Carbon
$end
):
?Override
{
$overrides
=
array_filter
(
$this
->
overrides
,
static
function
(
Override
$override
)
use
(
$doorId
,
$
date
)
{
return
$override
->
hasDoorIdOf
(
$doorId
)
&&
$override
->
isActiveForDate
(
$
date
);
$overrides
=
array_filter
(
$this
->
overrides
,
static
function
(
Override
$override
)
use
(
$doorId
,
$
begin
,
$end
)
{
return
$override
->
hasDoorIdOf
(
$doorId
)
&&
(
$override
->
isActiveForDate
(
$
begin
)
||
$override
->
isActiveForDate
(
$end
)
);
});
return
array_shift
(
$overrides
);
}
if
(
count
(
$overrides
)
>
0
)
{
return
$overrides
[
0
];
}
/**
* @inheritDoc
*/
public
function
addOverride
(
Override
$override
):
?Override
{
$this
->
overrides
[]
=
$override
;
return
null
;
return
$override
;
}
/**
* @inheritDoc
*/
public
function
add
Override
(
Override
$override
):
?Override
public
function
update
Override
(
string
$overrideId
,
Override
$override
):
?Override
{
$this
->
overrides
=
array_filter
(
$this
->
overrides
,
static
function
(
Override
$o
)
use
(
$overrideId
)
{
return
!
$o
->
hasIdOf
(
$overrideId
);
});
$this
->
overrides
[]
=
$override
;
return
$override
;
...
...
src/web/backend/src/Gateways/Overrides/OverridesRepository.php
View file @
7d9dcf3f
...
...
@@ -25,14 +25,25 @@ interface OverridesRepository
* Gets active override during date (if any). Returns null otherwise.
*
* @param string $doorId
* @param \Carbon\Carbon $date
* @param \Carbon\Carbon $begin
* @param \Carbon\Carbon $end
* @return \Source\Entities\Override|null
*/
public
function
activeOverrideForDoor
(
string
$doorId
,
Carbon
$
date
):
?Override
;
public
function
activeOverrideForDoor
Between
(
string
$doorId
,
Carbon
$
begin
,
Carbon
$end
):
?Override
;
/**
* @param \Source\Entities\Override $override
* @return \Source\Entities\Override|null
*/
public
function
addOverride
(
Override
$override
):
?Override
;
/**
* Will only update start, end, and reason.
*
* @param string $overrideId
* @param \Source\Entities\Override $override
* @return \Source\Entities\Override|null
* @throws \Source\Exceptions\EntityNotFoundException
*/
public
function
updateOverride
(
string
$overrideId
,
Override
$override
):
?Override
;
}
src/web/backend/src/Gateways/Overrides/OverridesRepositoryServiceProvider.php
View file @
7d9dcf3f
...
...
@@ -4,6 +4,7 @@
namespace
Source\Gateways\Overrides
;
use
Illuminate\Support\ServiceProvider
;
use
Illuminate\Database\DatabaseManager
;
use
Illuminate\Contracts\Foundation\Application
;
use
Illuminate\Contracts\Support\DeferrableProvider
;
...
...
@@ -28,7 +29,10 @@ class OverridesRepositoryServiceProvider extends ServiceProvider implements Defe
return
new
InMemoryOverridesRepository
();
}
return
new
DatabaseOverridesRepository
();
/** @var DatabaseManager $manager */
$manager
=
$app
->
make
(
DatabaseManager
::
class
);
return
new
DatabaseOverridesRepository
(
$manager
->
connection
(
'doorcode'
));
});
}
...
...
src/web/backend/src/Sanitize/CastsTo.php
View file @
7d9dcf3f
...
...
@@ -11,7 +11,7 @@ trait CastsTo
* @param string $format
* @return \Carbon\Carbon|null
*/
protected
function
castTo
Date
(
$date
,
$format
=
'Y-m-d H:i:s'
):
?Carbon
protected
function
castTo
Carbon
(
$date
,
$format
=
'Y-m-d H:i:s'
):
?Carbon
{
if
(
empty
(
$date
))
{
return
null
;
...
...
@@ -26,7 +26,7 @@ trait CastsTo
*/
protected
function
castToInt
(
?string
$int
):
?int
{
if
(
!
$int
)
{
if
(
$int
===
null
)
{
return
null
;
}
...
...
src/web/backend/src/UseCases/Door/Access/Authorizers/DoorOverrideCheck/DefaultDoorOverrideCheck.php
View file @
7d9dcf3f
...
...
@@ -27,7 +27,8 @@ class DefaultDoorOverrideCheck implements DoorOverrideCheck
*/
public
function
checkForOverrides
(
string
$doorId
,
Carbon
$date
):
int
{
$active
=
$this
->
overrides
->
activeOverrideForDoor
(
$doorId
,
$date
);
// Over the next second
$active
=
$this
->
overrides
->
activeOverrideForDoorBetween
(
$doorId
,
$date
,
$date
->
clone
()
->
addSecond
());
if
(
!
$active
)
{
return
DoorOverrideCheck
::
NO_ACTION
;
...
...
src/web/backend/src/UseCases/Door/StatusResponse/JsonPresenter.php
View file @
7d9dcf3f
...
...
@@ -2,6 +2,7 @@
namespace
Source\UseCases\Door\StatusResponse
;
use
Source\Entities\Schedule
;
use
Source\UseCases\BasePresenter
;
class
JsonPresenter
extends
BasePresenter
implements
Presenter
...
...
@@ -11,6 +12,12 @@ class JsonPresenter extends BasePresenter implements Presenter
/** @inheritDoc */
public
function
present
(
ResponseModel
$responseModel
):
void
{
$this
->
viewModel
=
array_map
(
function
(
OpenEvent
$event
)
{
return
[
'begins_at'
=>
$this
->
formatDateTime
(
$event
->
getBegin
()),
'ends_at'
=>
$this
->
formatDateTime
(
$event
->
getEnd
()),
];
},
$responseModel
->
getEvents
());
}
/** @inheritDoc */
...
...
src/web/backend/src/UseCases/Door/StatusResponse/OpenEvent.php
0 → 100644
View file @
7d9dcf3f
<?php
namespace
Source\UseCases\Door\StatusResponse
;
use
Carbon\Carbon
;
class
OpenEvent
{
/**
* @var \Carbon\Carbon
*/
protected
Carbon
$begin
;
/**
* @var \Carbon\Carbon
*/
protected
Carbon
$end
;
public
function
__construct
(
Carbon
$begin
,
Carbon
$end
)
{
$this
->
begin
=
$begin
;
$this
->
end
=
$end
;
}
/**
* @return \Carbon\Carbon
*/
public
function
getBegin
():
Carbon
{
return
$this
->
begin
;
}
/**
* @return \Carbon\Carbon
*/
public
function
getEnd
():
Carbon
{
return
$this
->
end
;
}
/**
* @param \Carbon\Carbon $begin
*/
public
function
setBegin
(
Carbon
$begin
):
void
{
$this
->
begin
=
$begin
;
}
/**
* @param \Carbon\Carbon $end
*/
public
function
setEnd
(
Carbon
$end
):
void
{
$this
->
end
=
$end
;
}
}
src/web/backend/src/UseCases/Door/StatusResponse/ResponseModel.php
View file @
7d9dcf3f
...
...
@@ -4,4 +4,24 @@ namespace Source\UseCases\Door\StatusResponse;
class
ResponseModel
{
/**
* @var \Source\UseCases\Door\StatusResponse\OpenEvent[]
*/
protected
array
$events
=
[];
/**
* @param \Source\UseCases\Door\StatusResponse\OpenEvent $event
*/
public
function
addEvent
(
OpenEvent
$event
):
void