pruvodce/app.php

406 lines
14 KiB
PHP

<?php
// DEPENDENCIES
use severak\database\rows;
use severak\forms\form;
$dependencies['config'] = $config;
$singletons['pdo'] = function() {
$config = di('config');
return new PDO('sqlite:' . __DIR__ . '/' . $config['database']);
};
$singletons['rows'] = function(){
return new severak\database\rows(di('pdo'));
};
// ROUTY
// HP & LOGIN
route('', '/', function (){
// if (!user()) return redirect('/login/');
$rows = di('rows');
$Parsedown = new Parsedown();
$pois = $rows->more('poi', [], [], 999);
$geojson = pois2geojson($pois, $Parsedown);
return render('poi', ['geojson'=>$geojson]);
});
route('', '/poi/{slug}/', function ($req, $params){
$rows = di('rows');
$poi = $rows->one('poi', ['slug'=>$params['slug']]);
if (!$poi) return notFound();
$Parsedown = new Parsedown();
$poi['description'] = $Parsedown->text($poi['description']);
$poi['cheatsheet'] = $Parsedown->text($poi['cheatsheet']);
$pois = $rows->more('poi', [], [], 999);
$geojson = pois2geojson($pois, $Parsedown);
return render('poi', ['geojson'=>$geojson, 'poi'=>$poi]);
});
route('', '/login/', function ($req){
/** @var Psr\Http\Message\ServerRequestInterface $req */
/** @var severak\database\rows $rows */
$rows = di('rows');
$form = new form(['method'=>'POST']);
$form->field('username', ['required'=>true, 'label'=>'Jméno']);
$form->field('password', ['type'=>'password', 'required'=>true, 'label'=>'Heslo']);
$form->field('_login', ['type'=>'submit', 'label'=>'Přihlásit se']);
if ($req->getMethod()=='POST') {
$form->fill($req->getParsedBody());
if ($form->validate()) {
$uz = $rows->one('users', ['username'=>$form->values['username'], 'is_active'=>1]);
if (!$uz) {
$form->error('username', 'Uživatel nenalezen');
} elseif (password_verify($form->values['password'], $uz['password'])) {
unset($uz['password']);
$_SESSION['user'] = $uz;
return redirect('/');
} else {
$form->error('password', 'Špatné heslo.');
}
}
}
return render('form', ['form'=>$form]);
});
route('', '/logout/', function ($req){
unset($_SESSION['user']);
unset($_SESSION['flashes']);
return redirect('/');
});
route('', '/zmena-hesla/', function ($req){
if (!user()) return redirect('/login/');
$user = user();
/** @var Psr\Http\Message\ServerRequestInterface $req */
/** @var severak\database\rows $rows */
$rows = di('rows');
$form = new form(['method'=>'post']);
$form->field('password_current', ['required'=>true, 'type'=>'password', 'label'=>'Stávající heslo']);
$form->field('password', ['required'=>true, 'type'=>'password', 'label'=>'Nové heslo']);
$form->field('password_again', ['required'=>true, 'type'=>'password', 'label'=>'Nové heslo znovu']);
$form->field('_sbt', ['label'=>'Změnit heslo', 'type'=>'submit']);
$form->rule('password_again', function ($v, $o){
return $v==$o['password'];
}, 'Hesla se neshodují!');
$uz = $rows->one('users', $user['id']);
$form->rule('password_current', function ($v, $o) use ($uz) {
return password_verify($v, $uz['password']);
}, 'Špatné zadané současné heslo!');
if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody()) && $form->validate()) {
$rows->update('users', [
'password'=>password_hash($form->values['password'], PASSWORD_DEFAULT)
], [
'id'=>$user['id']
]);
flash('Heslo změněno.');
return redirect('/');
}
return render('form', ['form'=>$form, 'title'=>'Změnit heslo']);
});
$singletons['poi_form'] = function () {
$form = new severak\forms\form(['method'=>'post']);
$form->field('name', ['label'=>'Název', 'required'=>true]);
$form->field('description', ['label'=>'Popis', 'type'=>'textarea']);
$form->field('cheatsheet', ['label'=>'Tahák', 'type'=>'textarea']);
$form->field('internal', ['label'=>'Poznámka', 'type'=>'textarea']);
$form->field('is_public', ['label'=>'Zveřejněno?', 'type'=>'checkbox']);
$form->field('lon', ['type'=>'hidden']);
$form->field('lat', ['type'=>'hidden']);
$form->field('_sbt', ['label'=>'Uložit?', 'type'=>'submit']);
$form->rule('lon', function ($v, $o) {
return !empty($o['lon']) && !empty($o['lat']);
}, 'Musí být vyplněny souřadnice');
return $form;
};
// správa POI
route('GET', '/pois/', function ($req){
return redirect('/pois/edit/');
});
route('GET', '/pois/edit/', function ($req){
if (!user()) return redirect('/login/');
/** @var severak\database\rows $rows */
$rows = di('rows');
$page = $_GET['page'] ?? 1;
$pois = $rows->page('poi', [], ['name'=>'asc'], $page, 30);
$pages = $rows->pages;
return render('poi_list', ['pois'=>$pois, 'pages'=>$pages, 'page'=>$page]);
});
route('', '/pois/add/', function ($req){
if (!user()) return redirect('/login/');
/** @var Psr\Http\Message\ServerRequestInterface $req */
/** @var severak\database\rows $rows */
$rows = di('rows');
/** @var severak\forms\form $form */
$form = di('poi_form');
if ($req->getMethod()=='POST') {
$form->fill($req->getParsedBody());
if ($form->validate()) {
$slug = slugify($form->values['name']);
$rows->insert('poi', [
'name'=>$form->values['name'],
'description'=>$form->values['description'],
'cheatsheet'=>$form->values['cheatsheet'],
'internal'=>$form->values['internal'],
'slug'=>$slug,
'lon'=>$form->values['lon'],
'lat'=>$form->values['lat'],
'is_public'=>$form->values['is_public'] ?? 0,
]);
return redirect('/poi/' . $slug . '/');
}
}
return render('form', ['form'=>$form, 'title'=>'Přidat položku']);
});
route('', '/pois/edit/{id}/', function ($req, $params){
if (!user()) return redirect('/login/');
/** @var Psr\Http\Message\ServerRequestInterface $req */
/** @var severak\database\rows $rows */
$rows = di('rows');
/** @var severak\forms\form $form */
$form = di('poi_form');
$item = $rows->one('poi', $params['id']);
if (!$item) return notFound();
$form->fill($item);
if ($req->getMethod()=='POST') {
$form->fill($req->getParsedBody());
if ($form->validate()) {
$slug = slugify($form->values['name']);
$rows->update('poi', [
'name'=>$form->values['name'],
'description'=>$form->values['description'],
'cheatsheet'=>$form->values['cheatsheet'],
'internal'=>$form->values['internal'],
'slug'=>$slug,
'lon'=>$form->values['lon'],
'lat'=>$form->values['lat'],
'is_public'=>$form->values['is_public'] ?? 0,
], $params['id']);
return redirect('/poi/' . $slug . '/');
}
}
return render('form', ['form'=>$form, 'title'=>'Upravit položku']);
});
// TODO - tohle nechceme přes GET
route('', '/sklad/smazat/{id}/', function ($req, $params){
if (!user()) return redirect('/login/');
/** @var severak\database\rows $rows */
$rows = di('rows');
$rows->update('items', ['is_active'=>0], ['id'=>$params['id'] ]);
return redirect('/sklad/');
});
// OBSLUHA
route('GET', '/obsluha/', function ($req){
if (!user()) return redirect('/login/');
/** @var severak\database\rows $rows */
$rows = di('rows');
$items = $rows->page('users', [], ['is_active'=>'desc', 'name'=>'asc']);
return render('users', ['users'=>$items]);
});
route('', '/obsluha/pridat/', function ($req){
if (!user()) return redirect('/login/');
$user = user();
if (!$user['is_superuser']) {
flash('Obsluhu může přidávat jen admin.', 'warning');
return redirect('/');
}
/** @var Psr\Http\Message\ServerRequestInterface $req */
/** @var severak\database\rows $rows */
$rows = di('rows');
$form = new form(['method'=>'post']);
$form->field('username', ['label'=>'Uživatelské jméno']);
$form->field('password', ['required'=>true, 'type'=>'password', 'label'=>'Heslo']);
$form->field('password_again', ['required'=>true, 'type'=>'password', 'label'=>'Heslo znovu']);
$form->field('name', ['required'=>true, 'type'=>'text', 'label'=>'Jméno']);
$form->field('card_id', ['type'=>'number', 'label'=>'Číslo členské karty', 'id'=>'qrcode']);
$form->field('_sbt', ['label'=>'Přidat', 'type'=>'submit']);
$form->rule('password_again', function ($v, $o){
return $v==$o['password'];
}, 'Hesla se neshodují!');
if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody()) && $form->validate()) {
$duplicateUser = $rows->one('users', ['username'=>$form->values['username'] ]);
if ($duplicateUser) {
$form->error('username', 'Uživatel tohoto jména již v systému je.');
}
$memberId = null;
if ($form->values['card_id']) {
$card = $rows->one('cards', ['id'=>$form->values['card_id'], 'is_active'=>1]);
$memberId = $card['member_id'];
}
if ($form->isValid) {
$rows->insert('users', [
'username' => $form->values['username'],
'name' => $form->values['name'],
'password' => password_hash($form->values['password'], PASSWORD_DEFAULT),
'member_id'=> $memberId
]);
flash('Uživatel přidán.', 'success');
return redirect('/obsluha/');
}
}
return render('form', ['form'=>$form, 'title'=>'Přidat obsluhu']);
});
route('', '/obsluha/upravit/{id}/', function ($req, $params){
if (!user()) return redirect('/login/');
$user = user();
if (!$user['is_superuser']) {
flash('Obsluhu může upravovat jen admin.', 'warning');
return redirect('/');
}
$id = $params['id'];
/** @var Psr\Http\Message\ServerRequestInterface $req */
/** @var severak\database\rows $rows */
$rows = di('rows');
$form = new form(['method'=>'post']);
$form->field('username', ['label'=>'Uživatelské jméno']);
$form->field('password', ['type'=>'password', 'label'=>'Heslo']);
$form->field('password_again', ['type'=>'password', 'label'=>'Heslo znovu']);
$form->field('name', ['required'=>true, 'type'=>'text', 'label'=>'Jméno']);
$form->field('card_id', ['type'=>'number', 'label'=>'Číslo členské karty', 'id'=>'qrcode']);
$form->field('is_active', ['type'=>'checkbox', 'label'=>'Aktivní?']);
$form->field('is_superuser', ['type'=>'checkbox', 'label'=>'Je admin?']);
$form->field('note', ['type'=>'textarea', 'label'=>'Poznámka']);
$form->field('_sbt', ['label'=>'Uložit', 'type'=>'submit']);
$form->rule('password_again', function ($v, $o){
return $v==$o['password'];
}, 'Hesla se neshodují!');
if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody())) {
$form->validate();
$duplicateUser = $rows->one('users', ['username'=>$form->values['username'] ]);
if ($duplicateUser && $duplicateUser['id']!=$id) {
$form->error('username', 'Uživatel tohoto jména již v systému je.');
}
if ($form->values['password'] && $form->values['password']!=$form->values['password_again']) {
$form->error('password', 'Hesla se musí shodovat!');
}
if ($form->isValid) {
$update = $form->values; // TODO tohle je prasárna
unset($update['id'], $update['password'], $update['password_again'], $update['card_id'], $update['_sbt']);
if ($form->values['password'] && $form->values['password']!=$form->values['password_again']) {
$update['password'] = password_hash($form->values['password'], PASSWORD_DEFAULT);
}
if ($form->values['card_id']) {
$card = $rows->one('cards', ['id'=>$form->values['card_id'], 'is_active'=>1]);
$update['member_id'] = $card['member_id'];
}
$rows->update('users', $update, $id);
flash('Uživatel upraven.', 'success');
return redirect('/obsluha/');
}
} else {
$editedUser = $rows->one('users', $id);
unset($editedUser['password']);
if ($editedUser['member_id']) {
$card = $rows->one('cards', ['member_id'=>$editedUser['member_id'], 'is_active'=>1]);
if ($card) {
$editedUser['card_id'] = $card['id'];
}
}
$form->fill($editedUser);
}
return render('form', ['form'=>$form, 'title'=>'Upravit obsluhu']);
});
function pois2geojson($pois, $Parsedown)
{
$geojson = ['type'=>'FeatureCollection', 'features'=>[]];
foreach ($pois as $poi) {
$geojson['features'][] = [
'type' => 'Feature',
'properties' => [
'name' => $poi['name'],
'description' => $Parsedown->text($poi['description']),
'cheatsheet' => $Parsedown->text($poi['cheatsheet']),
'slug' => $poi['slug'],
'id' => $poi['id'],
],
'geometry'=>[
'type'=>'Point',
'coordinates'=>[$poi['lon'], $poi['lat']]
]
];
}
return $geojson;
}
function slugify($text, $divider = '-')
{
// replace non letter or digits by divider
$text = preg_replace('~[^\pL\d]+~u', $divider, $text);
// transliterate
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
// remove unwanted characters
$text = preg_replace('~[^-\w]+~', '', $text);
// trim
$text = trim($text, $divider);
// remove duplicate divider
$text = preg_replace('~-+~', $divider, $text);
// lowercase
$text = strtolower($text);
if (empty($text)) {
return 'n-a';
}
return $text;
}