Added shirt edit view
parent
5667fc2326
commit
5c90a1ef37
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
|
||||||
|
class AddShirtEditPermissions extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
if (!$this->schema->hasTable('GroupPrivileges')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('Privileges')
|
||||||
|
->insert(['name' => 'user.edit.shirt', 'desc' => 'Edit user shirts']);
|
||||||
|
|
||||||
|
$shiftCoordinator = -40;
|
||||||
|
$shirtManager = -30;
|
||||||
|
|
||||||
|
$userEditShirt = $db->table('Privileges')
|
||||||
|
->where('name', 'user.edit.shirt')
|
||||||
|
->get(['id'])->first();
|
||||||
|
$adminArrive = $db->table('Privileges')
|
||||||
|
->where('name', 'admin_arrive')
|
||||||
|
->get(['id'])->first();
|
||||||
|
|
||||||
|
$db->table('GroupPrivileges')
|
||||||
|
->insertOrIgnore([
|
||||||
|
['group_id' => $shiftCoordinator, 'privilege_id' => $userEditShirt->id],
|
||||||
|
['group_id' => $shirtManager, 'privilege_id' => $userEditShirt->id],
|
||||||
|
['group_id' => $shirtManager, 'privilege_id' => $adminArrive->id],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
if (!$this->schema->hasTable('GroupPrivileges')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('Privileges')
|
||||||
|
->where(['name' => 'user.edit.shirt'])
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
$shirtManager = -30;
|
||||||
|
$adminArrive = $db->table('Privileges')
|
||||||
|
->where('name', 'admin_arrive')
|
||||||
|
->get(['id'])->first();
|
||||||
|
|
||||||
|
$db->table('GroupPrivileges')
|
||||||
|
->where(['group_id' => $shirtManager, 'privilege_id' => $adminArrive->id])
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
{% extends "layouts/app.twig" %}
|
||||||
|
{% import 'macros/base.twig' as m %}
|
||||||
|
{% import 'macros/form.twig' as f %}
|
||||||
|
|
||||||
|
{% block title %}{{ __('user.edit.shirt') }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<h1>{{ block('title') }}</h1>
|
||||||
|
|
||||||
|
{% include 'layouts/parts/messages.twig' %}
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
{{ csrf() }}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ f.select('shirt_size', config('tshirt_sizes'), __('user.shirt_size'), userdata.personalData.shirt_size) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
{% if has_permission_to('admin_arrive') %}
|
||||||
|
{{ f.switch('arrived', __('user.arrived'), userdata.state.arrived) }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if userdata.state.force_active %}
|
||||||
|
{{ f.switch('force_active', __('user.force_active'), true, {'disabled': true}) }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{{ f.switch('active', __('user.active'), userdata.state.active) }}
|
||||||
|
|
||||||
|
{{ f.switch('got_shirt', __('user.got_shirt'), userdata.state.got_shirt) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
{{ f.submit(__('form.save')) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Controllers\Admin;
|
||||||
|
|
||||||
|
use Engelsystem\Config\Config;
|
||||||
|
use Engelsystem\Controllers\BaseController;
|
||||||
|
use Engelsystem\Controllers\HasUserNotifications;
|
||||||
|
use Engelsystem\Helpers\Authenticator;
|
||||||
|
use Engelsystem\Http\Redirector;
|
||||||
|
use Engelsystem\Http\Request;
|
||||||
|
use Engelsystem\Http\Response;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
class UserShirtController extends BaseController
|
||||||
|
{
|
||||||
|
use HasUserNotifications;
|
||||||
|
|
||||||
|
/** @var Authenticator */
|
||||||
|
protected $auth;
|
||||||
|
|
||||||
|
/** @var Config */
|
||||||
|
protected $config;
|
||||||
|
|
||||||
|
/** @var LoggerInterface */
|
||||||
|
protected $log;
|
||||||
|
|
||||||
|
/** @var Redirector */
|
||||||
|
protected $redirect;
|
||||||
|
|
||||||
|
/** @var Response */
|
||||||
|
protected $response;
|
||||||
|
|
||||||
|
/** @var User */
|
||||||
|
protected $user;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
protected $permissions = [
|
||||||
|
'editShirt' => 'user.edit.shirt',
|
||||||
|
'saveShirt' => 'user.edit.shirt',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Authenticator $auth
|
||||||
|
* @param Config $config
|
||||||
|
* @param LoggerInterface $log
|
||||||
|
* @param Redirector $redirector
|
||||||
|
* @param Response $response
|
||||||
|
* @param User $user
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Authenticator $auth,
|
||||||
|
Config $config,
|
||||||
|
LoggerInterface $log,
|
||||||
|
Redirector $redirector,
|
||||||
|
Response $response,
|
||||||
|
User $user
|
||||||
|
) {
|
||||||
|
$this->auth = $auth;
|
||||||
|
$this->config = $config;
|
||||||
|
$this->log = $log;
|
||||||
|
$this->redirect = $redirector;
|
||||||
|
$this->response = $response;
|
||||||
|
$this->user = $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function editShirt(Request $request): Response
|
||||||
|
{
|
||||||
|
$id = $request->getAttribute('id');
|
||||||
|
$user = $this->user->findOrFail($id);
|
||||||
|
|
||||||
|
return $this->response->withView(
|
||||||
|
'admin/user/edit-shirt.twig',
|
||||||
|
['userdata' => $user] + $this->getNotifications()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function saveShirt(Request $request): Response
|
||||||
|
{
|
||||||
|
$id = $request->getAttribute('id');
|
||||||
|
/** @var User $user */
|
||||||
|
$user = $this->user->findOrFail($id);
|
||||||
|
|
||||||
|
$data = $this->validate($request, [
|
||||||
|
'shirt_size' => 'required',
|
||||||
|
'arrived' => 'optional|checked',
|
||||||
|
'active' => 'optional|checked',
|
||||||
|
'got_shirt' => 'optional|checked',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (isset($this->config->get('tshirt_sizes')[$data['shirt_size']])) {
|
||||||
|
$user->personalData->shirt_size = $data['shirt_size'];
|
||||||
|
$user->personalData->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->auth->can('admin_arrive')) {
|
||||||
|
$user->state->arrived = (bool)$data['arrived'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->state->active = (bool)$data['active'];
|
||||||
|
$user->state->got_shirt = (bool)$data['got_shirt'];
|
||||||
|
$user->state->save();
|
||||||
|
|
||||||
|
$this->log->info(
|
||||||
|
'Updated user shirt state "{user}" ({id}): {size}, arrived: {arrived}, got shirt: {got_shirt}',
|
||||||
|
[
|
||||||
|
'id' => $user->id,
|
||||||
|
'user' => $user->name,
|
||||||
|
'size' => $user->personalData->shirt_size,
|
||||||
|
'arrived' => $user->state->arrived,
|
||||||
|
'got_shirt' => $user->state->got_shirt
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->addNotification('user.edit.success');
|
||||||
|
|
||||||
|
return $this->redirect->back();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,163 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Controllers\Admin;
|
||||||
|
|
||||||
|
use Engelsystem\Controllers\Admin\UserShirtController;
|
||||||
|
use Engelsystem\Helpers\Authenticator;
|
||||||
|
use Engelsystem\Http\Redirector;
|
||||||
|
use Engelsystem\Http\Validation\Validator;
|
||||||
|
use Engelsystem\Models\User\PersonalData;
|
||||||
|
use Engelsystem\Models\User\State;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
|
use Engelsystem\Test\Unit\Controllers\ControllerTest;
|
||||||
|
use Engelsystem\Test\Unit\HasDatabase;
|
||||||
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
|
||||||
|
class UserShirtControllerTest extends ControllerTest
|
||||||
|
{
|
||||||
|
use HasDatabase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\Admin\UserShirtController::editShirt
|
||||||
|
* @covers \Engelsystem\Controllers\Admin\UserShirtController::__construct
|
||||||
|
*/
|
||||||
|
public function testIndex()
|
||||||
|
{
|
||||||
|
$request = $this->request->withAttribute('id', 1);
|
||||||
|
/** @var Authenticator|MockObject $auth */
|
||||||
|
$auth = $this->createMock(Authenticator::class);
|
||||||
|
/** @var Redirector|MockObject $redirector */
|
||||||
|
$redirector = $this->createMock(Redirector::class);
|
||||||
|
$user = new User();
|
||||||
|
User::factory()->create();
|
||||||
|
|
||||||
|
$this->setExpects($this->response, 'withView', ['admin/user/edit-shirt.twig'], $this->response);
|
||||||
|
|
||||||
|
$controller = new UserShirtController($auth, $this->config, $this->log, $redirector, $this->response, $user);
|
||||||
|
|
||||||
|
$controller->editShirt($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\Admin\UserShirtController::editShirt
|
||||||
|
*/
|
||||||
|
public function testIndexUserNotFound()
|
||||||
|
{
|
||||||
|
/** @var Authenticator|MockObject $auth */
|
||||||
|
$auth = $this->createMock(Authenticator::class);
|
||||||
|
/** @var Redirector|MockObject $redirector */
|
||||||
|
$redirector = $this->createMock(Redirector::class);
|
||||||
|
$user = new User();
|
||||||
|
|
||||||
|
$controller = new UserShirtController($auth, $this->config, $this->log, $redirector, $this->response, $user);
|
||||||
|
|
||||||
|
$this->expectException(ModelNotFoundException::class);
|
||||||
|
$controller->editShirt($this->request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\Admin\UserShirtController::saveShirt
|
||||||
|
*/
|
||||||
|
public function testSaveShirt()
|
||||||
|
{
|
||||||
|
$request = $this->request
|
||||||
|
->withAttribute('id', 1)
|
||||||
|
->withParsedBody([
|
||||||
|
'shirt_size' => 'S',
|
||||||
|
]);
|
||||||
|
/** @var Authenticator|MockObject $auth */
|
||||||
|
$auth = $this->createMock(Authenticator::class);
|
||||||
|
$this->config->set('tshirt_sizes', ['S' => 'Small']);
|
||||||
|
/** @var Redirector|MockObject $redirector */
|
||||||
|
$redirector = $this->createMock(Redirector::class);
|
||||||
|
User::factory()
|
||||||
|
->has(State::factory())
|
||||||
|
->has(PersonalData::factory())
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$auth
|
||||||
|
->expects($this->exactly(4))
|
||||||
|
->method('can')
|
||||||
|
->with('admin_arrive')
|
||||||
|
->willReturnOnConsecutiveCalls(true, true, true, false);
|
||||||
|
$this->setExpects($redirector, 'back', null, $this->response, $this->exactly(4));
|
||||||
|
|
||||||
|
$controller = new UserShirtController(
|
||||||
|
$auth,
|
||||||
|
$this->config,
|
||||||
|
$this->log,
|
||||||
|
$redirector,
|
||||||
|
$this->response,
|
||||||
|
new User()
|
||||||
|
);
|
||||||
|
$controller->setValidator(new Validator());
|
||||||
|
|
||||||
|
// Set shirt size
|
||||||
|
$controller->saveShirt($request);
|
||||||
|
|
||||||
|
$this->assertHasNotification('user.edit.success');
|
||||||
|
$this->assertTrue($this->log->hasInfoThatContains('Updated user shirt state'));
|
||||||
|
|
||||||
|
$user = User::find(1);
|
||||||
|
$this->assertEquals('S', $user->personalData->shirt_size);
|
||||||
|
$this->assertFalse($user->state->arrived);
|
||||||
|
$this->assertFalse($user->state->active);
|
||||||
|
$this->assertFalse($user->state->got_shirt);
|
||||||
|
|
||||||
|
// Set active, arrived and got_shirt
|
||||||
|
$request = $request
|
||||||
|
->withParsedBody([
|
||||||
|
'shirt_size' => 'S',
|
||||||
|
'arrived' => '1',
|
||||||
|
'active' => '1',
|
||||||
|
'got_shirt' => '1',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$controller->saveShirt($request);
|
||||||
|
|
||||||
|
$user = User::find(1);
|
||||||
|
$this->assertTrue($user->state->active);
|
||||||
|
$this->assertTrue($user->state->arrived);
|
||||||
|
$this->assertTrue($user->state->got_shirt);
|
||||||
|
|
||||||
|
// Shirt size not available
|
||||||
|
$request = $request
|
||||||
|
->withParsedBody([
|
||||||
|
'shirt_size' => 'L',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$controller->saveShirt($request);
|
||||||
|
$user = User::find(1);
|
||||||
|
$this->assertEquals('S', $user->personalData->shirt_size);
|
||||||
|
|
||||||
|
// Not allowed changing arrived
|
||||||
|
$request = $request
|
||||||
|
->withParsedBody([
|
||||||
|
'shirt_size' => 'S',
|
||||||
|
'arrived' => '1',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertFalse($user->state->arrived);
|
||||||
|
$controller->saveShirt($request);
|
||||||
|
$user = User::find(1);
|
||||||
|
$this->assertFalse($user->state->arrived);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\Admin\UserShirtController::saveShirt
|
||||||
|
*/
|
||||||
|
public function testSaveShirtUserNotFound()
|
||||||
|
{
|
||||||
|
/** @var Authenticator|MockObject $auth */
|
||||||
|
$auth = $this->createMock(Authenticator::class);
|
||||||
|
/** @var Redirector|MockObject $redirector */
|
||||||
|
$redirector = $this->createMock(Redirector::class);
|
||||||
|
$user = new User();
|
||||||
|
|
||||||
|
$controller = new UserShirtController($auth, $this->config, $this->log, $redirector, $this->response, $user);
|
||||||
|
|
||||||
|
$this->expectException(ModelNotFoundException::class);
|
||||||
|
$controller->editShirt($this->request);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue