Basic functionality
This commit is contained in:
4
.prettierrc
Normal file
4
.prettierrc
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true
|
||||
}
|
||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"nuxt.isNuxtApp": false
|
||||
"nuxt.isNuxtApp": false
|
||||
}
|
||||
@@ -14,6 +14,14 @@ class Bootstrap
|
||||
$configurator = new Configurator;
|
||||
$appDir = dirname(__DIR__);
|
||||
|
||||
// Provide some parameters
|
||||
$configurator->addParameters([
|
||||
'rootDir' => realpath(__DIR__ . '/..'),
|
||||
'appDir' => __DIR__,
|
||||
'wwwDir' => realpath(__DIR__ . '/../www'),
|
||||
]);
|
||||
|
||||
|
||||
$configurator->setDebugMode($_SERVER['HTTP_HOST'] === 'localhost');
|
||||
$configurator->enableTracy($appDir . '/log');
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Presenters;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
final class Error4xxPresenter extends Nette\Application\UI\Presenter
|
||||
{
|
||||
public function startup(): void
|
||||
{
|
||||
parent::startup();
|
||||
if (!$this->getRequest()->isMethod(Nette\Application\Request::FORWARD)) {
|
||||
$this->error();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function renderDefault(Nette\Application\BadRequestException $exception): void
|
||||
{
|
||||
// load template 403.latte or 404.latte or ... 4xx.latte
|
||||
$file = __DIR__ . "/templates/Error/{$exception->getCode()}.latte";
|
||||
$this->template->setFile(is_file($file) ? $file : __DIR__ . '/templates/Error/4xx.latte');
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Presenters;
|
||||
|
||||
use Nette;
|
||||
use Nette\Application\Responses;
|
||||
use Nette\Http;
|
||||
use Tracy\ILogger;
|
||||
|
||||
|
||||
final class ErrorPresenter implements Nette\Application\IPresenter
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
|
||||
/** @var ILogger */
|
||||
private $logger;
|
||||
|
||||
|
||||
public function __construct(ILogger $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
|
||||
public function run(Nette\Application\Request $request): Nette\Application\Response
|
||||
{
|
||||
$exception = $request->getParameter('exception');
|
||||
|
||||
if ($exception instanceof Nette\Application\BadRequestException) {
|
||||
[$module, , $sep] = Nette\Application\Helpers::splitName($request->getPresenterName());
|
||||
return new Responses\ForwardResponse($request->setPresenterName($module . $sep . 'Error4xx'));
|
||||
}
|
||||
|
||||
$this->logger->log($exception, ILogger::EXCEPTION);
|
||||
return new Responses\CallbackResponse(function (Http\IRequest $httpRequest, Http\IResponse $httpResponse): void {
|
||||
if (preg_match('#^text/html(?:;|$)#', (string) $httpResponse->getHeader('Content-Type'))) {
|
||||
require __DIR__ . '/templates/Error/500.phtml';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Presenters;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
final class HomepagePresenter extends BasePresenter
|
||||
{
|
||||
}
|
||||
@@ -1,38 +1,66 @@
|
||||
<span title="Toggle Vite" data-action="netteVite">
|
||||
<svg width="410" height="404" viewBox="0 0 410 404" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M399.641 59.5246L215.643 388.545C211.844 395.338 202.084 395.378 198.228 388.618L10.5817 59.5563C6.38087 52.1896 12.6802 43.2665 21.0281 44.7586L205.223 77.6824C206.398 77.8924 207.601 77.8904 208.776 77.6763L389.119 44.8058C397.439 43.2894 403.768 52.1434 399.641 59.5246Z" fill="url(#paint0_linear)"/>
|
||||
<path d="M292.965 1.5744L156.801 28.2552C154.563 28.6937 152.906 30.5903 152.771 32.8664L144.395 174.33C144.198 177.662 147.258 180.248 150.51 179.498L188.42 170.749C191.967 169.931 195.172 173.055 194.443 176.622L183.18 231.775C182.422 235.487 185.907 238.661 189.532 237.56L212.947 230.446C216.577 229.344 220.065 232.527 219.297 236.242L201.398 322.875C200.278 328.294 207.486 331.249 210.492 326.603L212.5 323.5L323.454 102.072C325.312 98.3645 322.108 94.137 318.036 94.9228L279.014 102.454C275.347 103.161 272.227 99.746 273.262 96.1583L298.731 7.86689C299.767 4.27314 296.636 0.855181 292.965 1.5744Z" fill="url(#paint1_linear)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear" x1="6.00017" y1="32.9999" x2="235" y2="344" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41D1FF"/>
|
||||
<stop offset="1" stop-color="#BD34FE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="194.651" y1="8.81818" x2="236.076" y2="292.989" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFEA83"/>
|
||||
<stop offset="0.0833333" stop-color="#FFDD35"/>
|
||||
<stop offset="1" stop-color="#FFA800"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
<svg
|
||||
width="410"
|
||||
height="404"
|
||||
viewBox="0 0 410 404"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M399.641 59.5246L215.643 388.545C211.844 395.338 202.084 395.378 198.228 388.618L10.5817 59.5563C6.38087 52.1896 12.6802 43.2665 21.0281 44.7586L205.223 77.6824C206.398 77.8924 207.601 77.8904 208.776 77.6763L389.119 44.8058C397.439 43.2894 403.768 52.1434 399.641 59.5246Z"
|
||||
fill="url(#paint0_linear)"
|
||||
/>
|
||||
<path
|
||||
d="M292.965 1.5744L156.801 28.2552C154.563 28.6937 152.906 30.5903 152.771 32.8664L144.395 174.33C144.198 177.662 147.258 180.248 150.51 179.498L188.42 170.749C191.967 169.931 195.172 173.055 194.443 176.622L183.18 231.775C182.422 235.487 185.907 238.661 189.532 237.56L212.947 230.446C216.577 229.344 220.065 232.527 219.297 236.242L201.398 322.875C200.278 328.294 207.486 331.249 210.492 326.603L212.5 323.5L323.454 102.072C325.312 98.3645 322.108 94.137 318.036 94.9228L279.014 102.454C275.347 103.161 272.227 99.746 273.262 96.1583L298.731 7.86689C299.767 4.27314 296.636 0.855181 292.965 1.5744Z"
|
||||
fill="url(#paint1_linear)"
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="paint0_linear"
|
||||
x1="6.00017"
|
||||
y1="32.9999"
|
||||
x2="235"
|
||||
y2="344"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#41D1FF" />
|
||||
<stop offset="1" stop-color="#BD34FE" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint1_linear"
|
||||
x1="194.651"
|
||||
y1="8.81818"
|
||||
x2="236.076"
|
||||
y2="292.989"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#FFEA83" />
|
||||
<stop offset="0.0833333" stop-color="#FFDD35" />
|
||||
<stop offset="1" stop-color="#FFA800" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</span>
|
||||
<style>
|
||||
#tracy-debug [data-action="netteVite"] {
|
||||
#tracy-debug [data-action='netteVite'] {
|
||||
cursor: pointer;
|
||||
padding: 0 .4em;
|
||||
margin: 0 -.4em;
|
||||
padding: 0 0.4em;
|
||||
margin: 0 -0.4em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#tracy-debug [data-action="netteVite"]:hover {
|
||||
#tracy-debug [data-action='netteVite']:hover {
|
||||
background: #c3c1b8;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function getCookie(n, a = `; ${document.cookie}`.match(`;\\s*${n}=([^;]+)`)) {
|
||||
return a ? JSON.parse(a[1]) : false;
|
||||
return a ? JSON.parse(a[1]) : false
|
||||
}
|
||||
|
||||
const element = document.querySelector('#tracy-debug [data-action="netteVite"]')
|
||||
const element = document.querySelector(
|
||||
'#tracy-debug [data-action="netteVite"]'
|
||||
)
|
||||
|
||||
console.log(getCookie('netteVite'))
|
||||
|
||||
@@ -41,9 +69,13 @@
|
||||
}
|
||||
|
||||
element.addEventListener('click', () => {
|
||||
document.cookie = getCookie('netteVite') ? 'netteVite=false; path=/;' : 'netteVite=true; path=/;'
|
||||
document.cookie = getCookie('netteVite')
|
||||
? 'netteVite=false; path=/;'
|
||||
: 'netteVite=true; path=/;'
|
||||
|
||||
getCookie('netteVite') ? (element.style.opacity = '') : (element.style.opacity = '40%')
|
||||
getCookie('netteVite')
|
||||
? (element.style.opacity = '')
|
||||
: (element.style.opacity = '40%')
|
||||
document.location.reload()
|
||||
})
|
||||
</script>
|
||||
|
||||
32
app/domain/Api/MyApi/v1/Handlers/TermsHandler.php
Executable file
32
app/domain/Api/MyApi/v1/Handlers/TermsHandler.php
Executable file
@@ -0,0 +1,32 @@
|
||||
<?php //declare(strict_types = 1);
|
||||
|
||||
namespace App\MyApi\v1\Handlers;
|
||||
|
||||
use App\Model\Database\EntityManager;
|
||||
use Tomaj\NetteApi\Handlers\BaseHandler;
|
||||
use Tomaj\NetteApi\Response\JsonApiResponse;
|
||||
use Tomaj\NetteApi\Response\ResponseInterface;
|
||||
use App\Model\Database\Facade\TermFacade;
|
||||
|
||||
class TermsHandler extends Basehandler
|
||||
{
|
||||
private $em;
|
||||
private $termFacade;
|
||||
|
||||
public function __construct(EntityManager $em, TermFacade $tf)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->em = $em;
|
||||
$this->termFacade = $tf;
|
||||
}
|
||||
|
||||
public function handle(array $params): ResponseInterface
|
||||
{
|
||||
$translation = $this->em->getTranslationRepository()->findOneBy(['id' => $_GET['translation']]);
|
||||
$this->termFacade->setDirection($translation->direction);
|
||||
$q = $this->termFacade->findByStringFull($_GET['string'], $translation->dictionary, '');
|
||||
$terms = $q->getArrayResult();
|
||||
|
||||
return new JsonApiResponse(200, ['status' => 'ok', 'terms' => $terms]);
|
||||
}
|
||||
}
|
||||
39
app/domain/Api/MyApi/v1/Handlers/TranslationsHandler.php
Normal file
39
app/domain/Api/MyApi/v1/Handlers/TranslationsHandler.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php //declare(strict_types = 1);
|
||||
|
||||
namespace App\MyApi\v1\Handlers;
|
||||
|
||||
use App\Model\Database\EntityManager;
|
||||
use Tomaj\NetteApi\Handlers\BaseHandler;
|
||||
use Tomaj\NetteApi\Response\JsonApiResponse;
|
||||
use Tomaj\NetteApi\Response\ResponseInterface;
|
||||
use App\Model\Database\Facade\TermFacade;
|
||||
use Nette\Utils\Strings;
|
||||
|
||||
class TranslationsHandler extends Basehandler
|
||||
{
|
||||
private $em;
|
||||
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function handle(array $params): ResponseInterface
|
||||
{
|
||||
$trs = $this->em->getTranslationRepository()->findBy([], ['id' => 'ASC', 'direction' => 'ASC']);
|
||||
$translations = [];
|
||||
foreach ($trs as $t) {
|
||||
$lang1 = $t->getLangName1();
|
||||
$lang2 = $t->getLangName2();
|
||||
|
||||
$lang = mb_substr($lang1, 0, -1);
|
||||
$lang .= "o-" . $lang2;
|
||||
$slug = Strings::webalize($lang);
|
||||
$translations[$t->id]["slug"] = $slug;
|
||||
$translations[$t->id]["lang"] = $lang;
|
||||
}
|
||||
|
||||
return new JsonApiResponse(200, ['status' => 'ok', 'translations' => $translations]);
|
||||
}
|
||||
}
|
||||
29
app/domain/Api/MyApi/v1/Handlers/UsersListingHandler.php
Executable file
29
app/domain/Api/MyApi/v1/Handlers/UsersListingHandler.php
Executable file
@@ -0,0 +1,29 @@
|
||||
<?php //declare(strict_types = 1);
|
||||
|
||||
namespace App\MyApi\v1\Handlers;
|
||||
|
||||
use App\Model\Database\EntityManager;
|
||||
use Tomaj\NetteApi\Handlers\BaseHandler;
|
||||
use Tomaj\NetteApi\Response\JsonApiResponse;
|
||||
use Tomaj\NetteApi\Response\ResponseInterface;
|
||||
|
||||
class UsersListingHandler extends Basehandler
|
||||
{
|
||||
private $em;
|
||||
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function handle(array $params): ResponseInterface
|
||||
{
|
||||
//$users = [];
|
||||
//foreach ($this->userRepository->all() as $user) {
|
||||
// $users[] = $user->toArray();
|
||||
//}
|
||||
$users = [ 'name' => 'test'];
|
||||
return new JsonApiResponse(200, ['status' => 'ok', 'users' => $users]);
|
||||
}
|
||||
}
|
||||
25
app/domain/Http/RequestLoggerSubscriber.php
Executable file
25
app/domain/Http/RequestLoggerSubscriber.php
Executable file
@@ -0,0 +1,25 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Domain\Http;
|
||||
|
||||
use Contributte\Events\Extra\Event\Application\RequestEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Tracy\Debugger;
|
||||
|
||||
class RequestLoggerSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [RequestEvent::class => 'onRequest'];
|
||||
}
|
||||
|
||||
public function onRequest(RequestEvent $event): void
|
||||
{
|
||||
Debugger::barDump($event->getRequest());
|
||||
}
|
||||
|
||||
}
|
||||
25
app/domain/Order/Event/OrderCreated.php
Executable file
25
app/domain/Order/Event/OrderCreated.php
Executable file
@@ -0,0 +1,25 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Domain\Order\Event;
|
||||
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
final class OrderCreated extends Event
|
||||
{
|
||||
|
||||
public const NAME = 'order.created';
|
||||
|
||||
/** @var string */
|
||||
private $order;
|
||||
|
||||
public function __construct(string $order)
|
||||
{
|
||||
$this->order = $order;
|
||||
}
|
||||
|
||||
public function getOrder(): string
|
||||
{
|
||||
return $this->order;
|
||||
}
|
||||
|
||||
}
|
||||
42
app/domain/Order/OrderLogSubscriber.php
Executable file
42
app/domain/Order/OrderLogSubscriber.php
Executable file
@@ -0,0 +1,42 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Domain\Order;
|
||||
|
||||
use App\Domain\Order\Event\OrderCreated;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Tracy\Debugger;
|
||||
|
||||
class OrderLogSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
OrderCreated::NAME => [
|
||||
['onOrderCreatedBefore', 100],
|
||||
['onOrderCreated', 0],
|
||||
['onOrderCreatedAfter', -100],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function onOrderCreatedBefore(OrderCreated $event): void
|
||||
{
|
||||
Debugger::barDump('BEFORE');
|
||||
}
|
||||
|
||||
public function onOrderCreated(OrderCreated $event): void
|
||||
{
|
||||
Debugger::log($event, 'info');
|
||||
Debugger::barDump($event);
|
||||
}
|
||||
|
||||
public function onOrderCreatedAfter(OrderCreated $event): void
|
||||
{
|
||||
Debugger::barDump('AFTER');
|
||||
}
|
||||
|
||||
}
|
||||
48
app/domain/User/CreateUserFacade.php
Executable file
48
app/domain/User/CreateUserFacade.php
Executable file
@@ -0,0 +1,48 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Domain\User;
|
||||
|
||||
use App\Model\Database\Entity\User;
|
||||
use App\Model\Database\EntityManager;
|
||||
use App\Model\Security\Passwords;
|
||||
|
||||
class CreateUserFacade
|
||||
{
|
||||
|
||||
/** @var EntityManager */
|
||||
private $em;
|
||||
|
||||
public function __construct(
|
||||
EntityManager $em
|
||||
)
|
||||
{
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $data
|
||||
*/
|
||||
public function createUser(array $data): User
|
||||
{
|
||||
// Create User
|
||||
$user = new User(
|
||||
$data['name'],
|
||||
$data['surname'],
|
||||
$data['email'],
|
||||
$data['username'],
|
||||
Passwords::create()->hash($data['password'] ?? md5(microtime()))
|
||||
);
|
||||
|
||||
// Set role
|
||||
if (isset($data['role'])) {
|
||||
$user->setRole($data['role']);
|
||||
}
|
||||
|
||||
// Save user
|
||||
$this->em->persist($user);
|
||||
$this->em->flush();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
}
|
||||
14
app/model/App.php
Executable file
14
app/model/App.php
Executable file
@@ -0,0 +1,14 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
final class App
|
||||
{
|
||||
|
||||
public const DESTINATION_FRONT_HOMEPAGE = ':Front:Home:';
|
||||
public const DESTINATION_ADMIN_HOMEPAGE = ':Admin:Home:';
|
||||
public const DESTINATION_SIGN_IN = ':Admin:Sign:in';
|
||||
public const DESTINATION_AFTER_SIGN_IN = self::DESTINATION_ADMIN_HOMEPAGE;
|
||||
public const DESTINATION_AFTER_SIGN_OUT = self::DESTINATION_FRONT_HOMEPAGE;
|
||||
|
||||
}
|
||||
25
app/model/Console/HelloCommand.php
Executable file
25
app/model/Console/HelloCommand.php
Executable file
@@ -0,0 +1,25 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Console;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class HelloCommand extends Command
|
||||
{
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('hello');
|
||||
$this->setDescription('Hello world!');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$output->write('Hello world!');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
8
app/model/Database/Entity/AbstractEntity.php
Executable file
8
app/model/Database/Entity/AbstractEntity.php
Executable file
@@ -0,0 +1,8 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
abstract class AbstractEntity
|
||||
{
|
||||
use \Nette\SmartObject;
|
||||
}
|
||||
33
app/model/Database/Entity/Attributes/TCreatedAt.php
Executable file
33
app/model/Database/Entity/Attributes/TCreatedAt.php
Executable file
@@ -0,0 +1,33 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Entity\Attributes;
|
||||
|
||||
use App\Model\Utils\DateTime;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
trait TCreatedAt
|
||||
{
|
||||
|
||||
/**
|
||||
* @var DateTime
|
||||
* @ORM\Column(type="datetime", nullable=FALSE)
|
||||
*/
|
||||
protected $createdAt;
|
||||
|
||||
public function getCreatedAt(): DateTime
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Doctrine annotation
|
||||
*
|
||||
* @ORM\PrePersist
|
||||
* @internal
|
||||
*/
|
||||
public function setCreatedAt(): void
|
||||
{
|
||||
$this->createdAt = new DateTime();
|
||||
}
|
||||
|
||||
}
|
||||
29
app/model/Database/Entity/Attributes/TId.php
Executable file
29
app/model/Database/Entity/Attributes/TId.php
Executable file
@@ -0,0 +1,29 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Entity\Attributes;
|
||||
|
||||
trait TId
|
||||
{
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="integer", nullable=FALSE)
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
*
|
||||
* @property int $id
|
||||
*/
|
||||
private $id;
|
||||
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$this->id = null;
|
||||
}
|
||||
|
||||
}
|
||||
33
app/model/Database/Entity/Attributes/TUpdatedAt.php
Executable file
33
app/model/Database/Entity/Attributes/TUpdatedAt.php
Executable file
@@ -0,0 +1,33 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Entity\Attributes;
|
||||
|
||||
use App\Model\Utils\DateTime;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
trait TUpdatedAt
|
||||
{
|
||||
|
||||
/**
|
||||
* @var DateTime|NULL
|
||||
* @ORM\Column(type="datetime", nullable=TRUE)
|
||||
*/
|
||||
protected $updatedAt;
|
||||
|
||||
public function getUpdatedAt(): ?DateTime
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Doctrine annotation
|
||||
*
|
||||
* @ORM\PreUpdate
|
||||
* @internal
|
||||
*/
|
||||
public function setUpdatedAt(): void
|
||||
{
|
||||
$this->updatedAt = new DateTime();
|
||||
}
|
||||
|
||||
}
|
||||
50
app/model/Database/Entity/DictType.php
Executable file
50
app/model/Database/Entity/DictType.php
Executable file
@@ -0,0 +1,50 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use App\Model\Database\Entity\Attributes\TId;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\DictTypeRepository")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @property int $id
|
||||
* @property String $shortName
|
||||
* @property String $fullName
|
||||
*/
|
||||
class DictType extends AbstractEntity
|
||||
{
|
||||
use TId;
|
||||
|
||||
public function __construct($short_name,$full_name)
|
||||
{
|
||||
$this->shortName = $short_name;
|
||||
$this->fullName = $full_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $shortName;
|
||||
|
||||
public function getShortName()
|
||||
{
|
||||
return $this->shortName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $fullName;
|
||||
|
||||
public function getFullName()
|
||||
{
|
||||
return $this->fullName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
94
app/model/Database/Entity/Dictionary.php
Executable file
94
app/model/Database/Entity/Dictionary.php
Executable file
@@ -0,0 +1,94 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use App\Model\Database\Entity\Attributes\TId;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\DictionaryRepository")
|
||||
* @ORM\Table(name="`dictionary`")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @property int $id
|
||||
* @property String $name
|
||||
* @property String $fullname
|
||||
* @property Term $terms
|
||||
* @property Language $lang1
|
||||
* @property Language $lang2
|
||||
*/
|
||||
class Dictionary extends AbstractEntity
|
||||
{
|
||||
|
||||
use Tid;
|
||||
|
||||
public function __construct($name,$fullname)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->fullName = $fullname;
|
||||
$this->translations = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="\App\Model\Database\Entity\Translation", mappedBy="dictionary", cascade={"persist"})
|
||||
* @var Collection&iterable<Translation>
|
||||
*/
|
||||
protected Collection $translations;
|
||||
|
||||
public function getTranslations()
|
||||
{
|
||||
return $this->translations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\OnetoMany(targetEntity="\App\Model\Database\Entity\Term", mappedBy="dictionary")
|
||||
* @var Collection&iterable<Term>
|
||||
*/
|
||||
protected Collection $terms;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Language", inversedBy="dictionaries1")
|
||||
* @ORM\JoinColumn(name="lang1_id", referencedColumnName="id")
|
||||
*/
|
||||
protected ?Language $lang1;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Language", inversedBy="dictionaries2")
|
||||
* @ORM\JoinColumn(name="lang2_id", referencedColumnName="id")
|
||||
*/
|
||||
protected ?Language $lang2;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $fullName;
|
||||
|
||||
public function setLang1($lang1)
|
||||
{
|
||||
$this->lang1 = $lang1;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setLang2($lang2)
|
||||
{
|
||||
$this->lang2 = $lang2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
65
app/model/Database/Entity/Language.php
Executable file
65
app/model/Database/Entity/Language.php
Executable file
@@ -0,0 +1,65 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use App\Model\Database\Entity\Attributes\TId;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\LanguageRepository")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @property int $id
|
||||
* @property String $name
|
||||
* @property String $shortName
|
||||
* @property Dictionary $dictionaries1
|
||||
* @property Dictionary $dictionaries2
|
||||
*
|
||||
*/
|
||||
class Language extends AbstractEntity
|
||||
{
|
||||
|
||||
use Tid;
|
||||
|
||||
public function __construct($shortname,$name)
|
||||
{
|
||||
$this->shortName = $shortname;
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string",length=2, unique=true, options={"fixed" = true})
|
||||
*/
|
||||
protected $shortName;
|
||||
|
||||
public function getShortName()
|
||||
{
|
||||
return $this->shortName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string",length=32)
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/*
|
||||
* @var Collection&iterable<Dictionary>
|
||||
* @ORM\OneToMany(targetEntity="Dictionary", mappedBy="language")
|
||||
*/
|
||||
protected Collection $dictionaries1;
|
||||
|
||||
/*
|
||||
* @var Collection&iterable<Dictionary>
|
||||
* @ORM\OneToMany(targetEntity="Dictionary", mappedBy="language")
|
||||
*/
|
||||
protected Collection $dictionaries2;
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
85
app/model/Database/Entity/Pronunciation.php
Executable file
85
app/model/Database/Entity/Pronunciation.php
Executable file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use App\Model\Database\Entity\Attributes\TId;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\PronunciationRepository")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @property int $id
|
||||
* @property Term $terms
|
||||
* @property PronunciationType $type
|
||||
* @property String $ipa
|
||||
* @property String $filename
|
||||
*/
|
||||
class Pronunciation extends AbstractEntity
|
||||
{
|
||||
|
||||
use Tid;
|
||||
|
||||
public function __construct($type,$ipa,$filename=null)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->ipa = $ipa;
|
||||
$this->filename = $filename;
|
||||
$this->terms = new \Doctrine\Common\Collections\ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Term", mappedBy="pronunciations")
|
||||
*/
|
||||
private $terms;
|
||||
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="PronunciationType", inversedBy="pronunciations")
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string",nullable=true)
|
||||
*/
|
||||
protected $ipa;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
*/
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* Get the value of filename
|
||||
*/
|
||||
public function getFilename()
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of terms
|
||||
*/
|
||||
public function getTerms()
|
||||
{
|
||||
return $this->terms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of ipa
|
||||
*/
|
||||
public function getIpa()
|
||||
{
|
||||
return $this->ipa;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of type
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
37
app/model/Database/Entity/PronunciationType.php
Executable file
37
app/model/Database/Entity/PronunciationType.php
Executable file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use App\Model\Database\Entity\Attributes\Tid;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\PronunciationTypeRepository")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @property int $id
|
||||
* @property String $name
|
||||
* @property String $fullName
|
||||
*/
|
||||
class PronunciationType extends AbstractEntity
|
||||
{
|
||||
use Tid;
|
||||
|
||||
public function __construct($name,$fullName)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->fullName = $fullName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $fullName;
|
||||
}
|
||||
|
||||
?>
|
||||
36
app/model/Database/Entity/Suffix.php
Executable file
36
app/model/Database/Entity/Suffix.php
Executable file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use App\Model\Database\Entity\Attributes\TId;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\SuffixRepository")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @property int $id
|
||||
* @property String $text
|
||||
*/
|
||||
class Suffix extends AbstractEntity
|
||||
{
|
||||
use Tid;
|
||||
|
||||
public function __construct($text)
|
||||
{
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $text;
|
||||
|
||||
|
||||
public function getText()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
231
app/model/Database/Entity/Term.php
Executable file
231
app/model/Database/Entity/Term.php
Executable file
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use App\Model\Database\Entity\Attributes\TId;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Common\Proxy\Proxy;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\TermRepository")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
* @ORM\Table(indexes={@ORM\Index(columns={"string1"}, flags={"fulltext"}),@ORM\Index(columns={"string2"}, flags={"fulltext"})})
|
||||
*
|
||||
* @property int $id
|
||||
* @property String $string1
|
||||
* @property String $string2
|
||||
* @property Dictionary $dictionary
|
||||
* @property mixed $pronunciations
|
||||
* @property Suffix $suffix1
|
||||
* @property Suffix $suffix2
|
||||
* @property DictType $type
|
||||
* @property int $order2
|
||||
* @property String $member
|
||||
*/
|
||||
class Term extends AbstractEntity
|
||||
{
|
||||
|
||||
use Tid;
|
||||
|
||||
public function __construct(Dictionary $dictionary, $string)
|
||||
{
|
||||
$this->dictionary = $dictionary;
|
||||
$this->string1 = $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="\App\Model\Database\Entity\Dictionary", inversedBy="terms",cascade={"persist", "remove" })
|
||||
*/
|
||||
protected $dictionary;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $string1;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $string2;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Suffix")
|
||||
*/
|
||||
protected $suffix1;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Suffix")
|
||||
*/
|
||||
protected $suffix2;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="DictType")
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Pronunciation", inversedBy="terms")
|
||||
* @ORM\JoinTable(name="terms_pronunciations")
|
||||
* @var Collection&iterable<Pronunciation>
|
||||
*/
|
||||
protected Collection $pronunciations;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string",nullable=true)
|
||||
*/
|
||||
protected $member;
|
||||
|
||||
public function setMember($member)
|
||||
{
|
||||
$this->member = $member;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMember()
|
||||
{
|
||||
return $this->member;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="smallint",nullable=true)
|
||||
*/
|
||||
protected $order2;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json_array",nullable=true)
|
||||
*/
|
||||
protected $flags;
|
||||
|
||||
public function getFlags()
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function setFlags($flags)
|
||||
{
|
||||
$this->flags = $flags;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOrder2()
|
||||
{
|
||||
return $this->order2;
|
||||
}
|
||||
|
||||
public function setOrder2($order2)
|
||||
{
|
||||
$this->order2 = $order2;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of string1
|
||||
*/
|
||||
public function getString1()
|
||||
{
|
||||
return $this->string1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of string1
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setString1($string1)
|
||||
{
|
||||
$this->string1 = $string1;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of string2
|
||||
*/
|
||||
public function getString2()
|
||||
{
|
||||
return $this->string2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of string2
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setString2($string2)
|
||||
{
|
||||
$this->string2 = $string2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of suffix1
|
||||
*/
|
||||
public function getSuffix1()
|
||||
{
|
||||
return $this->suffix1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of suffix1
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setSuffix1($suffix1)
|
||||
{
|
||||
$this->suffix1 = $suffix1;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of suffix2
|
||||
*/
|
||||
public function getSuffix2()
|
||||
{
|
||||
return $this->suffix2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of suffix2
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setSuffix2($suffix2)
|
||||
{
|
||||
$this->suffix2 = $suffix2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of type
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of type
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of pronunciations
|
||||
*
|
||||
* @return Collection&iterable<Pronunciation>
|
||||
*/
|
||||
public function getPronunciations()
|
||||
{
|
||||
return $this->pronunciations;
|
||||
}
|
||||
}
|
||||
97
app/model/Database/Entity/TermFlag.php
Executable file
97
app/model/Database/Entity/TermFlag.php
Executable file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use App\Model\Database\Entity\Attributes\TId;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\TermFlagRepository")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @property int $id
|
||||
* @property WordClass $class
|
||||
* @property Language $language
|
||||
* @property String $code
|
||||
* @property String $description
|
||||
*/
|
||||
class TermFlag extends AbstractEntity
|
||||
{
|
||||
|
||||
use Tid;
|
||||
|
||||
public function __construct($id,$class,$language,$code,$description)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->class = $class;
|
||||
$this->language = $language;
|
||||
$this->code = $code;
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="WordClass", inversedBy="flags")
|
||||
*/
|
||||
protected $class;
|
||||
|
||||
public function getClass()
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
public function setClass($class)
|
||||
{
|
||||
$this->class = $class;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Language", inversedBy="flags")
|
||||
*/
|
||||
protected $language;
|
||||
|
||||
public function getLanguage()
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
|
||||
public function setLanguage($language)
|
||||
{
|
||||
$this->language = $language;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $code;
|
||||
|
||||
public function getCode()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function setCode($code)
|
||||
{
|
||||
$this->code = $code;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
87
app/model/Database/Entity/Translation.php
Executable file
87
app/model/Database/Entity/Translation.php
Executable file
@@ -0,0 +1,87 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use App\Model\Database\Entity\Attributes\TId;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\TranslationRepository")
|
||||
* @ORM\Table(name="`translation`")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @property int $id
|
||||
* @property Dictionary $dictionary
|
||||
* @property Language $lang1
|
||||
* @property Language $lang2
|
||||
* @property int $direction
|
||||
*/
|
||||
class Translation extends AbstractEntity
|
||||
{
|
||||
|
||||
use Tid;
|
||||
|
||||
public function __construct($dictionary,$lang1,$lang2,$lang_name1,$lang_name2,$direction)
|
||||
{
|
||||
$this->dictionary = $dictionary;
|
||||
$this->lang1 = $lang1;
|
||||
$this->lang2 = $lang2;
|
||||
$this->lang_name1 = $lang_name1;
|
||||
$this->lang_name2 = $lang_name2;
|
||||
$this->direction = $direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Model\Database\Entity\Dictionary", inversedBy="translations")
|
||||
*/
|
||||
protected $dictionary;
|
||||
|
||||
public function getDictionary()
|
||||
{
|
||||
return $this->dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Model\Database\Entity\Language", inversedBy="translations1")
|
||||
*/
|
||||
protected $lang1;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Model\Database\Entity\Language", inversedBy="translations2")
|
||||
*/
|
||||
protected $lang2;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $lang_name1;
|
||||
|
||||
public function getLangName1(): String
|
||||
{
|
||||
return $this->lang_name1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $lang_name2;
|
||||
|
||||
public function getLangName2(): String
|
||||
{
|
||||
return $this->lang_name2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
protected $direction;
|
||||
|
||||
public function getDirection() : int
|
||||
{
|
||||
return $this->direction;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
214
app/model/Database/Entity/User.php
Executable file
214
app/model/Database/Entity/User.php
Executable file
@@ -0,0 +1,214 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use App\Model\Database\Entity\Attributes\TCreatedAt;
|
||||
use App\Model\Database\Entity\Attributes\TId;
|
||||
use App\Model\Database\Entity\Attributes\TUpdatedAt;
|
||||
use App\Model\Exception\Logic\InvalidArgumentException;
|
||||
use App\Model\Security\Identity;
|
||||
use App\Model\Utils\DateTime;
|
||||
use App\Model\Utils\Strings;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\UserRepository")
|
||||
* @ORM\Table(name="`user`")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @property int $id
|
||||
* @property String $name
|
||||
* @property String $surname
|
||||
* @property String $email
|
||||
* @property String $password
|
||||
* @property String $role
|
||||
* @property int $state
|
||||
*/
|
||||
class User extends AbstractEntity
|
||||
{
|
||||
|
||||
public const ROLE_ADMIN = 'admin';
|
||||
public const ROLE_USER = 'user';
|
||||
|
||||
public const STATE_FRESH = 1;
|
||||
public const STATE_ACTIVATED = 2;
|
||||
public const STATE_BLOCKED = 3;
|
||||
|
||||
public const STATES = [self::STATE_FRESH, self::STATE_BLOCKED, self::STATE_ACTIVATED];
|
||||
|
||||
use TId;
|
||||
use TCreatedAt;
|
||||
use TUpdatedAt;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @ORM\Column(type="string", length=255, nullable=FALSE, unique=false)
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @ORM\Column(type="string", length=255, nullable=FALSE, unique=false)
|
||||
*/
|
||||
private $surname;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @ORM\Column(type="string", length=255, nullable=FALSE, unique=TRUE)
|
||||
*/
|
||||
private $email;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @ORM\Column(type="string", length=255, nullable=FALSE, unique=TRUE)
|
||||
*/
|
||||
private $username;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="integer", length=10, nullable=FALSE)
|
||||
*/
|
||||
private $state;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @ORM\Column(type="string", length=255, nullable=FALSE)
|
||||
*/
|
||||
private $password;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @ORM\Column(type="string", length=255, nullable=FALSE)
|
||||
*/
|
||||
private $role;
|
||||
|
||||
/**
|
||||
* @var DateTime|NULL
|
||||
* @ORM\Column(type="datetime", nullable=TRUE)
|
||||
*/
|
||||
private $lastLoggedAt;
|
||||
|
||||
public function __construct(string $name, string $surname, string $email, string $username, string $passwordHash)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->surname = $surname;
|
||||
$this->email = $email;
|
||||
$this->username = $username;
|
||||
$this->password = $passwordHash;
|
||||
|
||||
$this->role = self::ROLE_USER;
|
||||
$this->state = self::STATE_FRESH;
|
||||
}
|
||||
|
||||
public function changeLoggedAt(): void
|
||||
{
|
||||
$this->lastLoggedAt = new DateTime();
|
||||
}
|
||||
|
||||
public function getEmail(): string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function getUsername(): string
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function changeUsername(string $username): void
|
||||
{
|
||||
$this->username = $username;
|
||||
}
|
||||
|
||||
public function getLastLoggedAt(): ?DateTime
|
||||
{
|
||||
return $this->lastLoggedAt;
|
||||
}
|
||||
|
||||
public function getRole(): string
|
||||
{
|
||||
return $this->role;
|
||||
}
|
||||
|
||||
public function setRole(string $role): void
|
||||
{
|
||||
$this->role = $role;
|
||||
}
|
||||
|
||||
public function getPasswordHash(): string
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function changePasswordHash(string $password): void
|
||||
{
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
public function block(): void
|
||||
{
|
||||
$this->state = self::STATE_BLOCKED;
|
||||
}
|
||||
|
||||
public function activate(): void
|
||||
{
|
||||
$this->state = self::STATE_ACTIVATED;
|
||||
}
|
||||
|
||||
public function isActivated(): bool
|
||||
{
|
||||
return $this->state === self::STATE_ACTIVATED;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getSurname(): string
|
||||
{
|
||||
return $this->surname;
|
||||
}
|
||||
|
||||
public function getFullname(): string
|
||||
{
|
||||
return $this->name . ' ' . $this->surname;
|
||||
}
|
||||
|
||||
public function rename(string $name, string $surname): void
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->surname = $surname;
|
||||
}
|
||||
|
||||
public function getState(): int
|
||||
{
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
public function setState(int $state): void
|
||||
{
|
||||
if (!in_array($state, self::STATES)) {
|
||||
throw new InvalidArgumentException(sprintf('Unsupported state %s', $state));
|
||||
}
|
||||
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
public function getGravatar(): string
|
||||
{
|
||||
return 'https://www.gravatar.com/avatar/' . md5($this->email);
|
||||
}
|
||||
|
||||
public function toIdentity(): Identity
|
||||
{
|
||||
return new Identity($this->getId(), [$this->role], [
|
||||
'email' => $this->email,
|
||||
'name' => $this->name,
|
||||
'surname' => $this->surname,
|
||||
'state' => $this->state,
|
||||
'gravatar' => $this->getGravatar(),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
43
app/model/Database/Entity/WordClass.php
Executable file
43
app/model/Database/Entity/WordClass.php
Executable file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Database\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use App\Model\Database\Entity\Attributes\TId;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Model\Database\Repository\WordClassRepository")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @property int $id
|
||||
* @property String $name
|
||||
*
|
||||
*/
|
||||
class WordClass extends AbstractEntity
|
||||
{
|
||||
|
||||
use Tid;
|
||||
|
||||
public function __construct($id,$name)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
28
app/model/Database/EntityManager.php
Executable file
28
app/model/Database/EntityManager.php
Executable file
@@ -0,0 +1,28 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database;
|
||||
|
||||
use App\Model\Database\Repository\AbstractRepository;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
use Nettrine\ORM\EntityManagerDecorator;
|
||||
|
||||
class EntityManager extends EntityManagerDecorator
|
||||
{
|
||||
|
||||
use TRepositories;
|
||||
|
||||
/**
|
||||
* @param string $entityName
|
||||
* @return AbstractRepository<T>|ObjectRepository<T>
|
||||
* @internal
|
||||
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
|
||||
* @phpstan-template T of object
|
||||
* @phpstan-param class-string<T> $entityName
|
||||
* @phpstan-return ObjectRepository<T>
|
||||
*/
|
||||
public function getRepository($entityName): ObjectRepository
|
||||
{
|
||||
return parent::getRepository($entityName);
|
||||
}
|
||||
|
||||
}
|
||||
124
app/model/Database/Facade/TermFacade.php
Executable file
124
app/model/Database/Facade/TermFacade.php
Executable file
@@ -0,0 +1,124 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Facade;
|
||||
|
||||
use App\Model\Database\Entity\Dictionary;
|
||||
use App\Model\Database\Entity\Term;
|
||||
use App\Model\Database\Entity\Translation;
|
||||
use App\Model\Database\EntityManager;
|
||||
|
||||
|
||||
class TermFacade
|
||||
{
|
||||
|
||||
/** @var EntityManager */
|
||||
private $em;
|
||||
private $direction;
|
||||
|
||||
public function __construct(
|
||||
EntityManager $em
|
||||
)
|
||||
{
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function setDirection(int $direction)
|
||||
{
|
||||
$this->direction = $direction;
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $data
|
||||
*/
|
||||
public function findByString(String $term,Dictionary $d,String $clen = null)
|
||||
{
|
||||
$query = $this->em->createQueryBuilder('t')->select('t')
|
||||
->addSelect('s1')
|
||||
->addSelect('s2')
|
||||
->from(Term::class,'t')
|
||||
->leftJoin('t.suffix1','s1')
|
||||
->leftJoin('t.suffix2','s2');
|
||||
if ($this->direction == 1) {
|
||||
$query->where('t.string1 LIKE :str')->setParameter('str', $term."%");
|
||||
$query->orderBy('t.string1,t.id','ASC');
|
||||
} else if ($this->direction == 2) {
|
||||
$query->where('t.string2 LIKE :str')->setParameter('str', $term."%");
|
||||
$query->orderBy('t.string2','ASC');
|
||||
$query->addOrderBy('t.order2','ASC');
|
||||
}
|
||||
$query->andWhere('t.dictionary = :dict')->setParameter(':dict',$d->id);
|
||||
if ($clen)
|
||||
$query->andWhere('t.member LIKE :clen')->setParameter('clen','%'.$clen.'%');
|
||||
|
||||
return $query->getQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $data
|
||||
*/
|
||||
public function findByStringQuick(String $string, Dictionary $d, String $clen = null)
|
||||
{
|
||||
$query = $this->em->createQueryBuilder('t')->select('DISTINCT t.string1 AS str')->from(Term::class,'t');
|
||||
if ($this->direction == 1) {
|
||||
$query->where('t.string1 LIKE :str')->setParameter('str',$string."%");
|
||||
$query->orderBy('t.string1','ASC');
|
||||
} else if ($this->direction == 2) {
|
||||
$query->where('t.string2 LIKE :str')->setParameter('str', $string."%");
|
||||
$query->orderBy('t.string2','ASC');
|
||||
}
|
||||
$query->andWhere('t.dictionary = :dict')->setParameter(':dict',$d->id);
|
||||
|
||||
return $query->getQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $data
|
||||
*/
|
||||
public function findByStringFull(String $string, Dictionary $d, String $clen = null, $like = true)
|
||||
{
|
||||
|
||||
$search = $string;
|
||||
if ($like) $search = $search . "%";
|
||||
|
||||
$query = $this->em->createQueryBuilder('t')->select('t')
|
||||
->addSelect('s1')
|
||||
->addSelect('s2')
|
||||
->addSelect('p')
|
||||
->from(Term::class,'t')
|
||||
->leftJoin('t.suffix1','s1')
|
||||
->leftJoin('t.suffix2','s2')
|
||||
->leftJoin('t.pronunciations','p');
|
||||
if ($this->direction == 1) {
|
||||
$query->where('t.string1 LIKE :str')->setParameter('str',$search);
|
||||
$query->orderBy('t.id','ASC');
|
||||
$query->addOrderBy('p.id','ASC');
|
||||
} else if ($this->direction == 2) {
|
||||
$query->where('t.string2 LIKE :str')->setParameter('str', $search);
|
||||
$query->orderBy('t.string2','ASC');
|
||||
$query->addOrderBy('t.order2','ASC');
|
||||
}
|
||||
$query->andWhere('t.dictionary = :dict')->setParameter(':dict',$d->id);
|
||||
if ($clen)
|
||||
$query->andWhere('t.member LIKE :clen')->setParameter('clen','%'.$clen.'%');
|
||||
|
||||
return $query->getQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $data
|
||||
*/
|
||||
public function findByStringSimple(String $string, Dictionary $d, String $clen = null)
|
||||
{
|
||||
$query = $this->em->createQueryBuilder('t')->select('t')->from(Term::class,'t');
|
||||
if ($this->direction == 1) {
|
||||
$query->where('t.string1 LIKE :str')->setParameter('str',$string."%");
|
||||
$query->orderBy('t.id','ASC');
|
||||
} else if ($this->direction == 2) {
|
||||
$query->where('t.string2 LIKE :str')->setParameter('str', $string."%");
|
||||
$query->orderBy('t.string2','ASC');
|
||||
$query->addOrderBy('t.order2','ASC');
|
||||
}
|
||||
$query->andWhere('t.dictionary = :dict')->setParameter(':dict',$d->id);
|
||||
|
||||
return $query->getQuery();
|
||||
}
|
||||
}
|
||||
86
app/model/Database/Repository/AbstractRepository.php
Executable file
86
app/model/Database/Repository/AbstractRepository.php
Executable file
@@ -0,0 +1,86 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
/**
|
||||
* @phpstan-template TEntityClass of object
|
||||
* @phpstan-extends EntityRepository<TEntityClass>
|
||||
*/
|
||||
abstract class AbstractRepository extends EntityRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* Fetches all records like $key => $value pairs
|
||||
*
|
||||
* @param mixed[] $criteria
|
||||
* @param mixed[] $orderBy
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function findPairs(?string $key, string $value, array $criteria = [], array $orderBy = []): array
|
||||
{
|
||||
if ($key === null) {
|
||||
$key = $this->getClassMetadata()->getSingleIdentifierFieldName();
|
||||
}
|
||||
|
||||
$qb = $this->createQueryBuilder('e')
|
||||
->select(['e.' . $value, 'e.' . $key])
|
||||
->resetDQLPart('from')
|
||||
->from($this->getEntityName(), 'e', 'e.' . $key);
|
||||
|
||||
foreach ($criteria as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$qb->andWhere(sprintf('e.%s IN(:%s)', $k, $k))->setParameter($k, array_values($v));
|
||||
} else {
|
||||
$qb->andWhere(sprintf('e.%s = :%s', $k, $k))->setParameter($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($orderBy as $column => $order) {
|
||||
$qb->addOrderBy($column, $order);
|
||||
}
|
||||
|
||||
return array_map(function ($row) {
|
||||
return reset($row);
|
||||
}, $qb->getQuery()->getArrayResult());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all records and returns an associative array indexed by key
|
||||
*
|
||||
* @param array $criteria
|
||||
* @param string $key
|
||||
*
|
||||
* @throws \Exception|QueryException
|
||||
* @return array
|
||||
*/
|
||||
public function findAssoc(array $criteria = [],String $key = NULL)
|
||||
{
|
||||
if (!is_array($criteria)) {
|
||||
$key = $criteria;
|
||||
$criteria = [];
|
||||
}
|
||||
|
||||
$qb = $this->createQueryBuilder('e')
|
||||
->resetDQLPart('from')->from($this->getEntityName(), 'e', 'e.' . $key);
|
||||
|
||||
foreach ($criteria as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$qb->andWhere(sprintf('e.%s IN(:%s)', $k, $k))->setParameter($k, array_values($v));
|
||||
} else {
|
||||
$qb->andWhere(sprintf('e.%s = :%s', $k, $k))->setParameter($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return $qb->getQuery()->getResult();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
throw $this->handleException($e, $qb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
18
app/model/Database/Repository/DictTypeRepository.php
Executable file
18
app/model/Database/Repository/DictTypeRepository.php
Executable file
@@ -0,0 +1,18 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Repository;
|
||||
|
||||
use App\Model\Database\Entity\DictType;
|
||||
|
||||
/**
|
||||
* @method DictType|NULL find($id, ?int $lockMode = NULL, ?int $lockVersion = NULL)
|
||||
* @method DictType|NULL findOneBy(array $criteria, array $orderBy = NULL)
|
||||
* @method DictType[] findAll()
|
||||
* @method DictType[] findBy(array $criteria, array $orderBy = NULL, ?int $limit = NULL, ?int $offset = NULL)
|
||||
* @extends AbstractRepository<DictType>
|
||||
*/
|
||||
class DictTypeRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
18
app/model/Database/Repository/DictionaryRepository.php
Executable file
18
app/model/Database/Repository/DictionaryRepository.php
Executable file
@@ -0,0 +1,18 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Repository;
|
||||
|
||||
use App\Model\Database\Entity\Dictionary;
|
||||
|
||||
/**
|
||||
* @method Dictionary|NULL find($id, ?int $lockMode = NULL, ?int $lockVersion = NULL)
|
||||
* @method Dictionary|NULL findOneBy(array $criteria, array $orderBy = NULL)
|
||||
* @method Dictionary[] findAll()
|
||||
* @method Dictionary[] findBy(array $criteria, array $orderBy = NULL, ?int $limit = NULL, ?int $offset = NULL)
|
||||
* @extends AbstractRepository<Dictionary>
|
||||
*/
|
||||
class DictionaryRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
16
app/model/Database/Repository/PronunciationRepository.php
Executable file
16
app/model/Database/Repository/PronunciationRepository.php
Executable file
@@ -0,0 +1,16 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Repository;
|
||||
|
||||
use App\Model\Database\Entity\Pronunciation;
|
||||
/**
|
||||
* @method Pronunciation|NULL find($id, ?int $lockMode = NULL, ?int $lockVersion = NULL)
|
||||
* @method Pronunciation|NULL findOneBy(array $criteria, array $orderBy = NULL)
|
||||
* @method Pronunciation[] findAll()
|
||||
* @method Pronunciation[] findBy(array $criteria, array $orderBy = NULL, ?int $limit = NULL, ?int $offset = NULL)
|
||||
* @extends AbstractRepository<Pronunciation>
|
||||
*/
|
||||
class PronunciationRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
}
|
||||
18
app/model/Database/Repository/TermFlagRepository.php
Executable file
18
app/model/Database/Repository/TermFlagRepository.php
Executable file
@@ -0,0 +1,18 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Repository;
|
||||
|
||||
use App\Model\Database\Entity\TermFlag;
|
||||
|
||||
/**
|
||||
* @method TermFlag|NULL find($id, ?int $lockMode = NULL, ?int $lockVersion = NULL)
|
||||
* @method TermFlag|NULL findOneBy(array $criteria, array $orderBy = NULL)
|
||||
* @method TermFlag[] findAll()
|
||||
* @method TermFlag[] findBy(array $criteria, array $orderBy = NULL, ?int $limit = NULL, ?int $offset = NULL)
|
||||
* @extends AbstractRepository<TermFlag>
|
||||
*/
|
||||
class TermFlagRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
18
app/model/Database/Repository/TermRepository.php
Executable file
18
app/model/Database/Repository/TermRepository.php
Executable file
@@ -0,0 +1,18 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Repository;
|
||||
|
||||
use App\Model\Database\Entity\Term;
|
||||
|
||||
/**
|
||||
* @method Term|NULL find($id, ?int $lockMode = NULL, ?int $lockVersion = NULL)
|
||||
* @method Term|NULL findOneBy(array $criteria, array $orderBy = NULL)
|
||||
* @method Term[] findAll()
|
||||
* @method Term[] findBy(array $criteria, array $orderBy = NULL, ?int $limit = NULL, ?int $offset = NULL)
|
||||
* @extends AbstractRepository<Term>
|
||||
*/
|
||||
class TermRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
57
app/model/Database/Repository/TermsQuery.php
Executable file
57
app/model/Database/Repository/TermsQuery.php
Executable file
@@ -0,0 +1,57 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use App\Model\Database\Entity\Dictionary;
|
||||
|
||||
class TermsQuery extends EntityRepository
|
||||
{
|
||||
|
||||
private Dictionary $dictionary;
|
||||
private String $string;
|
||||
private Int $direction;
|
||||
private String $clen;
|
||||
|
||||
public function __construct(Dictionary $dict,String $string,Int $direction = 1)
|
||||
{
|
||||
$this->dictionary = $dict;
|
||||
$this->string = $string;
|
||||
$this->direction = $direction;
|
||||
}
|
||||
|
||||
public function withClen(String $clen)
|
||||
{
|
||||
if ($clen != null && $clen != '')
|
||||
$this->clen = $clen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all records like $key => $value pairs
|
||||
*
|
||||
* @param mixed[] $criteria
|
||||
* @param mixed[] $orderBy
|
||||
* @return mixed[]
|
||||
*/
|
||||
protected function doCreateQuery()
|
||||
{
|
||||
$query = $this->createQueryBuilder('t')->select('t')
|
||||
->addSelect('s1')
|
||||
->addSelect('s2')
|
||||
->leftJoin('t.suffix1','s1')
|
||||
->leftJoin('t.suffix2','s2');
|
||||
if ($this->direction == 1) {
|
||||
$query->where('t.string1 LIKE :str')->setParameter('str',$this->string."%");
|
||||
$query->orderBy('t.string1,t.id','ASC');
|
||||
} else if ($this->direction == 2) {
|
||||
$query->where('t.string2 LIKE :str')->setParameter('str', $this->string."%");
|
||||
$query->orderBy('t.string2','ASC');
|
||||
$query->addOrderBy('t.order2','ASC');
|
||||
}
|
||||
$query->andWhere('t.dictionary = :dict')->setParameter(':dict',$this->dictionary->id);
|
||||
if ($this->clen)
|
||||
$query->andWhere('t.member LIKE :clen')->setParameter('clen','%'.$this->clen.'%');
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
20
app/model/Database/Repository/TranslationRepository.php
Executable file
20
app/model/Database/Repository/TranslationRepository.php
Executable file
@@ -0,0 +1,20 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Repository;
|
||||
|
||||
use App\Model\Database\Entity\Translation;
|
||||
|
||||
/**
|
||||
* @method Translation|NULL find($id, ?int $lockMode = NULL, ?int $lockVersion = NULL)
|
||||
* @method Translation|NULL findOneBy(array $criteria, array $orderBy = NULL)
|
||||
* @method Translation[] findAll()
|
||||
* @method Translation[] findBy(array $criteria, array $orderBy = NULL, ?int $limit = NULL, ?int $offset = NULL)
|
||||
* @extends AbstractRepository<Translation>
|
||||
*/
|
||||
class TranslationRepository extends AbstractRepository
|
||||
{
|
||||
public function findOneByEmail(string $email): ?Translation
|
||||
{
|
||||
return $this->findOneBy(['email' => $email]);
|
||||
}
|
||||
}
|
||||
22
app/model/Database/Repository/UserRepository.php
Executable file
22
app/model/Database/Repository/UserRepository.php
Executable file
@@ -0,0 +1,22 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database\Repository;
|
||||
|
||||
use App\Model\Database\Entity\User;
|
||||
|
||||
/**
|
||||
* @method User|NULL find($id, ?int $lockMode = NULL, ?int $lockVersion = NULL)
|
||||
* @method User|NULL findOneBy(array $criteria, array $orderBy = NULL)
|
||||
* @method User[] findAll()
|
||||
* @method User[] findBy(array $criteria, array $orderBy = NULL, ?int $limit = NULL, ?int $offset = NULL)
|
||||
* @extends AbstractRepository<User>
|
||||
*/
|
||||
class UserRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
public function findOneByEmail(string $email): ?User
|
||||
{
|
||||
return $this->findOneBy(['email' => $email]);
|
||||
}
|
||||
|
||||
}
|
||||
61
app/model/Database/TRepositories.php
Executable file
61
app/model/Database/TRepositories.php
Executable file
@@ -0,0 +1,61 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Database;
|
||||
|
||||
use App\Model\Database\Entity\User;
|
||||
use App\Model\Database\Entity\Translation;
|
||||
use App\Model\Database\Entity\Term;
|
||||
use App\Model\Database\Entity\TermFlag;
|
||||
use App\Model\Database\Entity\Pronunciation;
|
||||
use App\Model\Database\Entity\DictType;
|
||||
use App\Model\Database\Entity\Dictionary;
|
||||
use App\Model\Database\Repository\UserRepository;
|
||||
use App\Model\Database\Repository\TranslationRepository;
|
||||
use App\Model\Database\Repository\TermRepository;
|
||||
use App\Model\Database\Repository\TermFlagRepository;
|
||||
use App\Model\Database\Repository\PronunciationRepository;
|
||||
use App\Model\Database\Repository\DictTypeRepository;
|
||||
use App\Model\Database\Repository\DictionaryRepository;
|
||||
|
||||
/**
|
||||
* @mixin EntityManager
|
||||
*/
|
||||
trait TRepositories
|
||||
{
|
||||
|
||||
public function getUserRepository(): UserRepository
|
||||
{
|
||||
return $this->getRepository(User::class);
|
||||
}
|
||||
|
||||
public function getTranslationRepository(): TranslationRepository
|
||||
{
|
||||
return $this->getRepository(Translation::class);
|
||||
}
|
||||
|
||||
public function getTermRepository(): TermRepository
|
||||
{
|
||||
return $this->getRepository(Term::class);
|
||||
}
|
||||
|
||||
public function getTermFlagRepository(): TermFlagRepository
|
||||
{
|
||||
return $this->getRepository(TermFlag::class);
|
||||
}
|
||||
|
||||
public function getPronunciationRepository(): PronunciationRepository
|
||||
{
|
||||
return $this->getRepository(Pronunciation::class);
|
||||
}
|
||||
|
||||
public function getDictTypeRepository(): DictTypeRepository
|
||||
{
|
||||
return $this->getRepository(DictType::class);
|
||||
}
|
||||
|
||||
public function getDictionaryRepository(): DictionaryRepository
|
||||
{
|
||||
return $this->getRepository(Dictionary::class);
|
||||
}
|
||||
|
||||
}
|
||||
10
app/model/Exception/Logic/InvalidArgumentException.php
Executable file
10
app/model/Exception/Logic/InvalidArgumentException.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Exception\Logic;
|
||||
|
||||
use App\Model\Exception\LogicException;
|
||||
|
||||
final class InvalidArgumentException extends LogicException
|
||||
{
|
||||
|
||||
}
|
||||
8
app/model/Exception/LogicException.php
Executable file
8
app/model/Exception/LogicException.php
Executable file
@@ -0,0 +1,8 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Exception;
|
||||
|
||||
class LogicException extends \LogicException
|
||||
{
|
||||
|
||||
}
|
||||
10
app/model/Exception/Runtime/AuthenticationException.php
Executable file
10
app/model/Exception/Runtime/AuthenticationException.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Exception\Runtime;
|
||||
|
||||
use Nette\Security\AuthenticationException as NetteAuthenticationException;
|
||||
|
||||
final class AuthenticationException extends NetteAuthenticationException
|
||||
{
|
||||
|
||||
}
|
||||
10
app/model/Exception/Runtime/IOException.php
Executable file
10
app/model/Exception/Runtime/IOException.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Exception\Runtime;
|
||||
|
||||
use App\Model\Exception\RuntimeException;
|
||||
|
||||
final class IOException extends RuntimeException
|
||||
{
|
||||
|
||||
}
|
||||
10
app/model/Exception/Runtime/InvalidStateException.php
Executable file
10
app/model/Exception/Runtime/InvalidStateException.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Exception\Runtime;
|
||||
|
||||
use App\Model\Exception\RuntimeException;
|
||||
|
||||
final class InvalidStateException extends RuntimeException
|
||||
{
|
||||
|
||||
}
|
||||
8
app/model/Exception/RuntimeException.php
Executable file
8
app/model/Exception/RuntimeException.php
Executable file
@@ -0,0 +1,8 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Exception;
|
||||
|
||||
class RuntimeException extends \RuntimeException
|
||||
{
|
||||
|
||||
}
|
||||
35
app/model/Latte/FilterExecutor.php
Executable file
35
app/model/Latte/FilterExecutor.php
Executable file
@@ -0,0 +1,35 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Latte;
|
||||
|
||||
use Latte\Engine;
|
||||
|
||||
final class FilterExecutor
|
||||
{
|
||||
|
||||
/** @var Engine */
|
||||
private $latte;
|
||||
|
||||
public function __construct(Engine $latte)
|
||||
{
|
||||
$this->latte = $latte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $args
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call(string $name, array $args)
|
||||
{
|
||||
return $this->latte->invokeFilter($name, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
return $this->latte->invokeFilter($name, []);
|
||||
}
|
||||
|
||||
}
|
||||
30
app/model/Latte/Filters.php
Executable file
30
app/model/Latte/Filters.php
Executable file
@@ -0,0 +1,30 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Latte;
|
||||
|
||||
use Nette\Neon\Neon;
|
||||
use Nette\StaticClass;
|
||||
use Nette\Utils\Json;
|
||||
|
||||
final class Filters
|
||||
{
|
||||
|
||||
use StaticClass;
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function neon($value): string
|
||||
{
|
||||
return Neon::encode($value, Neon::BLOCK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function json($value): string
|
||||
{
|
||||
return Json::encode($value);
|
||||
}
|
||||
|
||||
}
|
||||
16
app/model/Latte/Macros.php
Executable file
16
app/model/Latte/Macros.php
Executable file
@@ -0,0 +1,16 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Latte;
|
||||
|
||||
use Latte\Compiler;
|
||||
use Latte\Macros\MacroSet;
|
||||
|
||||
final class Macros extends MacroSet
|
||||
{
|
||||
|
||||
public static function register(Compiler $compiler): void
|
||||
{
|
||||
$compiler = new static($compiler);
|
||||
}
|
||||
|
||||
}
|
||||
51
app/model/Latte/TemplateFactory.php
Executable file
51
app/model/Latte/TemplateFactory.php
Executable file
@@ -0,0 +1,51 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Latte;
|
||||
|
||||
use App\Model\Security\SecurityUser;
|
||||
use Nette\Application\UI\Control;
|
||||
use Nette\Bridges\ApplicationLatte\LatteFactory;
|
||||
use Nette\Bridges\ApplicationLatte\Template;
|
||||
use Nette\Bridges\ApplicationLatte\TemplateFactory as NetteTemplateFactory;
|
||||
use Nette\Caching\IStorage;
|
||||
use Nette\Http\IRequest;
|
||||
|
||||
final class TemplateFactory extends NetteTemplateFactory
|
||||
{
|
||||
|
||||
/** @var LatteFactory */
|
||||
private $latteFactory;
|
||||
|
||||
/** @var SecurityUser */
|
||||
private $user;
|
||||
|
||||
public function __construct(
|
||||
LatteFactory $latteFactory,
|
||||
IRequest $httpRequest,
|
||||
SecurityUser $user,
|
||||
IStorage $cacheStorage,
|
||||
string $templateClass = null
|
||||
)
|
||||
{
|
||||
parent::__construct($latteFactory, $httpRequest, $user, $cacheStorage, $templateClass);
|
||||
$this->latteFactory = $latteFactory;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function createTemplate(Control $control = null, string $class = null): Template
|
||||
{
|
||||
/** @var Template $template */
|
||||
$template = parent::createTemplate($control);
|
||||
|
||||
// Remove default $template->user for prevent misused
|
||||
unset($template->user);
|
||||
|
||||
// Assign new variables
|
||||
$template->_user = $this->user;
|
||||
$template->_template = $template;
|
||||
$template->_filters = new FilterExecutor($this->latteFactory->create());
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
}
|
||||
20
app/model/Latte/TemplateProperty.php
Executable file
20
app/model/Latte/TemplateProperty.php
Executable file
@@ -0,0 +1,20 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Latte;
|
||||
|
||||
use App\Model\Security\SecurityUser;
|
||||
use App\Modules\Base\BasePresenter;
|
||||
use App\UI\Control\BaseControl;
|
||||
use Nette\Bridges\ApplicationLatte\Template;
|
||||
|
||||
/**
|
||||
* @property-read SecurityUser $_user
|
||||
* @property-read BasePresenter $presenter
|
||||
* @property-read BaseControl $control
|
||||
* @property-read string $baseUri
|
||||
* @property-read string $basePath
|
||||
* @property-read array $flashes
|
||||
*/
|
||||
final class TemplateProperty extends Template
|
||||
{
|
||||
}
|
||||
64
app/model/Router/RouterFactory.php
Executable file
64
app/model/Router/RouterFactory.php
Executable file
@@ -0,0 +1,64 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Router;
|
||||
|
||||
use Nette\Application\Routers\Route;
|
||||
use Nette\Application\Routers\RouteList;
|
||||
use Nette\Routing\RouteList as RoutingRouteList;
|
||||
|
||||
final class RouterFactory
|
||||
{
|
||||
|
||||
public function create(): RouteList
|
||||
{
|
||||
$router = new RouteList();
|
||||
|
||||
$this->buildApi($router);
|
||||
$this->buildMailing($router);
|
||||
$this->buildPdf($router);
|
||||
$this->buildAdmin($router);
|
||||
$this->buildFront($router);
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
protected function buildAdmin(RouteList $router): RouteList
|
||||
{
|
||||
$router[] = $list = new RouteList('Admin');
|
||||
$list[] = new Route('admin/<presenter>/<action>[/<id>]', 'Home:default');
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
protected function buildFront(RouteList $router): RouteList
|
||||
{
|
||||
$router[] = $list = new RouteList('Front');
|
||||
$list[] = new Route('<presenter>/<action>[/<id>]', 'Home:default');
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
protected function buildMailing(RouteList $router): RouteList
|
||||
{
|
||||
$router[] = $list = new RouteList('Mailing');
|
||||
$list[] = new Route('mailing/<presenter>/<action>[/<id>]', 'Home:default');
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
protected function buildPdf(RouteList $router): RouteList
|
||||
{
|
||||
$router[] = $list = new RouteList('Pdf');
|
||||
$list[] = new Route('pdf/<presenter>/<action>[/<id>]', 'Home:default');
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
protected function buildApi(RouteList $router): RouteList
|
||||
{
|
||||
$router[] = $list = new RouteList('Api');
|
||||
$list[] = new Route('/api/v<version>/<package>[/<apiAction>][/<params>]', 'Api:default');
|
||||
|
||||
return $router;
|
||||
}
|
||||
}
|
||||
57
app/model/Security/Authenticator/UserAuthenticator.php
Executable file
57
app/model/Security/Authenticator/UserAuthenticator.php
Executable file
@@ -0,0 +1,57 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Security\Authenticator;
|
||||
|
||||
use App\Model\Database\Entity\User;
|
||||
use App\Model\Database\EntityManager;
|
||||
use App\Model\Exception\Runtime\AuthenticationException;
|
||||
use App\Model\Security\Passwords;
|
||||
use Nette\Security\Authenticator;
|
||||
use Nette\Security\IIdentity;
|
||||
|
||||
final class UserAuthenticator implements Authenticator
|
||||
{
|
||||
|
||||
/** @var EntityManager */
|
||||
private $em;
|
||||
|
||||
/** @var Passwords */
|
||||
private $passwords;
|
||||
|
||||
public function __construct(EntityManager $em, Passwords $passwords)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->passwords = $passwords;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public function authenticate(string $username, string $password): IIdentity
|
||||
{
|
||||
$user = $this->em->getUserRepository()->findOneBy(['email' => $username]);
|
||||
|
||||
if (!$user) {
|
||||
throw new AuthenticationException('The username is incorrect.', self::IDENTITY_NOT_FOUND);
|
||||
} elseif (!$user->isActivated()) {
|
||||
throw new AuthenticationException('The user is not active.', self::INVALID_CREDENTIAL);
|
||||
} elseif (!$this->passwords->verify($password, $user->getPasswordHash())) {
|
||||
throw new AuthenticationException('The password is incorrect.', self::INVALID_CREDENTIAL);
|
||||
}
|
||||
|
||||
$user->changeLoggedAt();
|
||||
$this->em->flush();
|
||||
|
||||
return $this->createIdentity($user);
|
||||
}
|
||||
|
||||
protected function createIdentity(User $user): IIdentity
|
||||
{
|
||||
$this->em->flush();
|
||||
|
||||
return $user->toIdentity();
|
||||
}
|
||||
|
||||
}
|
||||
47
app/model/Security/Authorizator/StaticAuthorizator.php
Executable file
47
app/model/Security/Authorizator/StaticAuthorizator.php
Executable file
@@ -0,0 +1,47 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Security\Authorizator;
|
||||
|
||||
use App\Model\Database\Entity\User;
|
||||
use Nette\Security\Permission;
|
||||
|
||||
final class StaticAuthorizator extends Permission
|
||||
{
|
||||
|
||||
/**
|
||||
* Create ACL
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->addRoles();
|
||||
$this->addResources();
|
||||
$this->addPermissions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup roles
|
||||
*/
|
||||
protected function addRoles(): void
|
||||
{
|
||||
$this->addRole(User::ROLE_ADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup resources
|
||||
*/
|
||||
protected function addResources(): void
|
||||
{
|
||||
$this->addResource('Admin:Home');
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup ACL
|
||||
*/
|
||||
protected function addPermissions(): void
|
||||
{
|
||||
$this->allow(User::ROLE_ADMIN, [
|
||||
'Admin:Home',
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
15
app/model/Security/Identity.php
Executable file
15
app/model/Security/Identity.php
Executable file
@@ -0,0 +1,15 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Security;
|
||||
|
||||
use Nette\Security\SimpleIdentity as NetteIdentity;
|
||||
|
||||
class Identity extends NetteIdentity
|
||||
{
|
||||
|
||||
public function getFullname(): string
|
||||
{
|
||||
return sprintf('%s %s', $this->data['name'] ?? '', $this->data['surname'] ?? '');
|
||||
}
|
||||
|
||||
}
|
||||
15
app/model/Security/Passwords.php
Executable file
15
app/model/Security/Passwords.php
Executable file
@@ -0,0 +1,15 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Security;
|
||||
|
||||
use Nette\Security\Passwords as NettePasswords;
|
||||
|
||||
final class Passwords extends NettePasswords
|
||||
{
|
||||
|
||||
public static function create(): Passwords
|
||||
{
|
||||
return new Passwords();
|
||||
}
|
||||
|
||||
}
|
||||
19
app/model/Security/SecurityUser.php
Executable file
19
app/model/Security/SecurityUser.php
Executable file
@@ -0,0 +1,19 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Security;
|
||||
|
||||
use App\Model\Database\Entity\User;
|
||||
use Nette\Security\User as NetteUser;
|
||||
|
||||
/**
|
||||
* @method Identity getIdentity()
|
||||
*/
|
||||
final class SecurityUser extends NetteUser
|
||||
{
|
||||
|
||||
public function isAdmin(): bool
|
||||
{
|
||||
return $this->isInRole(User::ROLE_ADMIN);
|
||||
}
|
||||
|
||||
}
|
||||
10
app/model/Utils/Arrays.php
Executable file
10
app/model/Utils/Arrays.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Utils;
|
||||
|
||||
use Nette\Utils\Arrays as NetteArrays;
|
||||
|
||||
final class Arrays extends NetteArrays
|
||||
{
|
||||
|
||||
}
|
||||
13
app/model/Utils/DateTime.php
Executable file
13
app/model/Utils/DateTime.php
Executable file
@@ -0,0 +1,13 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Utils;
|
||||
|
||||
use Nette\Utils\DateTime as ContributteDateTime;
|
||||
|
||||
/**
|
||||
* @method DateTime modifyClone(string $modify = '')
|
||||
*/
|
||||
final class DateTime extends ContributteDateTime
|
||||
{
|
||||
|
||||
}
|
||||
10
app/model/Utils/FileSystem.php
Executable file
10
app/model/Utils/FileSystem.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Utils;
|
||||
|
||||
use Contributte\Utils\FileSystem as ContributteFileSystem;
|
||||
|
||||
final class FileSystem extends ContributteFileSystem
|
||||
{
|
||||
|
||||
}
|
||||
10
app/model/Utils/Html.php
Executable file
10
app/model/Utils/Html.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Utils;
|
||||
|
||||
use Nette\Utils\Html as NetteHtml;
|
||||
|
||||
final class Html extends NetteHtml
|
||||
{
|
||||
|
||||
}
|
||||
10
app/model/Utils/Image.php
Executable file
10
app/model/Utils/Image.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Utils;
|
||||
|
||||
use Nette\Utils\Image as NetteImage;
|
||||
|
||||
class Image extends NetteImage
|
||||
{
|
||||
|
||||
}
|
||||
10
app/model/Utils/Strings.php
Executable file
10
app/model/Utils/Strings.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Utils;
|
||||
|
||||
use Contributte\Utils\Strings as ContributteStrings;
|
||||
|
||||
final class Strings extends ContributteStrings
|
||||
{
|
||||
|
||||
}
|
||||
10
app/model/Utils/Validators.php
Executable file
10
app/model/Utils/Validators.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Model\Utils;
|
||||
|
||||
use Contributte\Utils\Validators as ContributteValidators;
|
||||
|
||||
final class Validators extends ContributteValidators
|
||||
{
|
||||
|
||||
}
|
||||
26
app/modules/Admin/BaseAdminPresenter.php
Executable file
26
app/modules/Admin/BaseAdminPresenter.php
Executable file
@@ -0,0 +1,26 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Admin;
|
||||
|
||||
use App\Model\App;
|
||||
use App\Modules\Base\SecuredPresenter;
|
||||
use Nette\Application\UI\ComponentReflection;
|
||||
|
||||
abstract class BaseAdminPresenter extends SecuredPresenter
|
||||
{
|
||||
|
||||
/**
|
||||
* @param ComponentReflection|mixed $element
|
||||
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
|
||||
*/
|
||||
public function checkRequirements($element): void
|
||||
{
|
||||
parent::checkRequirements($element);
|
||||
|
||||
if (!$this->user->isAllowed('Admin:Home')) {
|
||||
$this->flashError('You cannot access this with user role');
|
||||
$this->redirect(App::DESTINATION_FRONT_HOMEPAGE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
31
app/modules/Admin/Home/HomePresenter.php
Executable file
31
app/modules/Admin/Home/HomePresenter.php
Executable file
@@ -0,0 +1,31 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Admin\Home;
|
||||
|
||||
use App\Domain\Order\Event\OrderCreated;
|
||||
use App\Modules\Admin\BaseAdminPresenter;
|
||||
use Nette\Application\UI\Form;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
final class HomePresenter extends BaseAdminPresenter
|
||||
{
|
||||
|
||||
/** @var EventDispatcherInterface @inject */
|
||||
public $dispatcher;
|
||||
|
||||
protected function createComponentOrderForm(): Form
|
||||
{
|
||||
$form = new Form();
|
||||
|
||||
$form->addText('order', 'Order name')
|
||||
->setRequired(true);
|
||||
$form->addSubmit('send', 'OK');
|
||||
|
||||
$form->onSuccess[] = function (Form $form): void {
|
||||
$this->dispatcher->dispatch(new OrderCreated($form->values->order), OrderCreated::NAME);
|
||||
};
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
8
app/modules/Admin/Home/templates/default.latte
Executable file
8
app/modules/Admin/Home/templates/default.latte
Executable file
@@ -0,0 +1,8 @@
|
||||
{block #content}
|
||||
<h1>SECRET PAGE!</h1>
|
||||
<a n:href="Sign:out" class="btn btn-danger">Logout</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Orders</h2>
|
||||
{control orderForm}
|
||||
75
app/modules/Admin/Sign/SignPresenter.php
Executable file
75
app/modules/Admin/Sign/SignPresenter.php
Executable file
@@ -0,0 +1,75 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Admin\Sign;
|
||||
|
||||
use App\Model\App;
|
||||
use App\Model\Exception\Runtime\AuthenticationException;
|
||||
use App\Modules\Admin\BaseAdminPresenter;
|
||||
use App\UI\Form\BaseForm;
|
||||
use App\UI\Form\FormFactory;
|
||||
use Nette\Application\UI\ComponentReflection;
|
||||
|
||||
final class SignPresenter extends BaseAdminPresenter
|
||||
{
|
||||
|
||||
/** @var string @persistent */
|
||||
public $backlink;
|
||||
|
||||
/** @var FormFactory @inject */
|
||||
public $formFactory;
|
||||
|
||||
/**
|
||||
* @param ComponentReflection|mixed $element
|
||||
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
|
||||
*/
|
||||
public function checkRequirements($element): void
|
||||
{
|
||||
}
|
||||
|
||||
public function actionIn(): void
|
||||
{
|
||||
if ($this->user->isLoggedIn()) {
|
||||
$this->redirect(App::DESTINATION_AFTER_SIGN_IN);
|
||||
}
|
||||
}
|
||||
|
||||
public function actionOut(): void
|
||||
{
|
||||
if ($this->user->isLoggedIn()) {
|
||||
$this->user->logout();
|
||||
$this->flashSuccess('_front.sign.out.success');
|
||||
}
|
||||
|
||||
$this->redirect(App::DESTINATION_AFTER_SIGN_OUT);
|
||||
}
|
||||
|
||||
protected function createComponentLoginForm(): BaseForm
|
||||
{
|
||||
$form = $this->formFactory->forBackend();
|
||||
$form->addEmail('email')
|
||||
->setRequired(true);
|
||||
$form->addPassword('password')
|
||||
->setRequired(true);
|
||||
$form->addCheckbox('remember')
|
||||
->setDefaultValue(true);
|
||||
$form->addSubmit('submit');
|
||||
$form->onSuccess[] = [$this, 'processLoginForm'];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function processLoginForm(BaseForm $form): void
|
||||
{
|
||||
try {
|
||||
$this->user->setExpiration($form->values->remember ? '14 days' : '20 minutes');
|
||||
$this->user->login($form->values->email, $form->values->password);
|
||||
} catch (AuthenticationException $e) {
|
||||
$form->addError('Invalid username or password');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->redirect(App::DESTINATION_AFTER_SIGN_IN);
|
||||
}
|
||||
|
||||
}
|
||||
29
app/modules/Admin/Sign/templates/in.latte
Executable file
29
app/modules/Admin/Sign/templates/in.latte
Executable file
@@ -0,0 +1,29 @@
|
||||
{block #content}
|
||||
<form n:name="loginForm" class="form-signin">
|
||||
<div class="text-center mb-4">
|
||||
<img class="mb-4" src="https://avatars0.githubusercontent.com/u/99965?s=200&v=4" alt="" width="72" height="72">
|
||||
<h1 class="h3 mb-3 font-weight-normal">Webapp Skeleton Admin</h1>
|
||||
</div>
|
||||
|
||||
<div n:foreach="$form->errors as $error" class="alert alert-danger" role="alert">
|
||||
{$error}
|
||||
</div>
|
||||
|
||||
<div class="form-label-group">
|
||||
<input type="email" n:name="email" class="form-control" placeholder="Email address" required autofocus>
|
||||
<label n:name="email">Email address</label>
|
||||
</div>
|
||||
|
||||
<div class="form-label-group">
|
||||
<input type="password" n:name="password" class="form-control" placeholder="Password" required>
|
||||
<label n:name="password">Password</label>
|
||||
</div>
|
||||
|
||||
<div class="checkbox mb-3">
|
||||
<label>
|
||||
<input n:name="remember" type="checkbox"> Remember me
|
||||
</label>
|
||||
</div>
|
||||
<button n:name="submit" class="btn btn-lg btn-primary btn-block">Sign in</button>
|
||||
<p class="mt-5 mb-3 text-muted text-center">© {=date('Y')}</p>
|
||||
</form>
|
||||
7
app/modules/Admin/templates/@layout.latte
Executable file
7
app/modules/Admin/templates/@layout.latte
Executable file
@@ -0,0 +1,7 @@
|
||||
{layout '../../Base/templates/@layout.latte'}
|
||||
|
||||
{block #head}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" defer />
|
||||
<link rel="stylesheet" href="{$basePath}/assets/admin.css" defer />
|
||||
<script src="{$basePath}/assets/admin.js" defer></script>
|
||||
{/block}
|
||||
44
app/modules/Base/BaseError4xxPresenter.php
Executable file
44
app/modules/Base/BaseError4xxPresenter.php
Executable file
@@ -0,0 +1,44 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Base;
|
||||
|
||||
use App\Model\Exception\Runtime\InvalidStateException;
|
||||
use Nette\Application\BadRequestException;
|
||||
use Nette\Application\Request;
|
||||
use Nette\Application\UI\ComponentReflection;
|
||||
|
||||
abstract class BaseError4xxPresenter extends SecuredPresenter
|
||||
{
|
||||
|
||||
/**
|
||||
* Common presenter method
|
||||
*/
|
||||
public function startup(): void
|
||||
{
|
||||
parent::startup();
|
||||
|
||||
if ($this->getRequest() !== null && $this->getRequest()->isMethod(Request::FORWARD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->error();
|
||||
}
|
||||
|
||||
public function renderDefault(BadRequestException $exception): void
|
||||
{
|
||||
$rf1 = new ComponentReflection(static::class);
|
||||
$fileName = $rf1->getFileName();
|
||||
|
||||
// Validate if class is not in PHP core
|
||||
if ($fileName === false) {
|
||||
throw new InvalidStateException('Class is defined in the PHP core or in a PHP extension');
|
||||
}
|
||||
|
||||
$dir = dirname($fileName);
|
||||
|
||||
// Load template 403.latte or 404.latte or ... 4xx.latte
|
||||
$file = $dir . '/templates/' . $exception->getCode() . '.latte';
|
||||
$this->template->setFile(is_file($file) ? $file : $dir . '/templates/4xx.latte');
|
||||
}
|
||||
|
||||
}
|
||||
57
app/modules/Base/BaseErrorPresenter.php
Executable file
57
app/modules/Base/BaseErrorPresenter.php
Executable file
@@ -0,0 +1,57 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Base;
|
||||
|
||||
use Nette\Application\BadRequestException;
|
||||
use Nette\Application\Helpers;
|
||||
use Nette\Application\IResponse as AppResponse;
|
||||
use Nette\Application\Request;
|
||||
use Nette\Application\Responses\CallbackResponse;
|
||||
use Nette\Application\Responses\ForwardResponse;
|
||||
use Nette\Http\IRequest;
|
||||
use Nette\Http\IResponse;
|
||||
use Psr\Log\LogLevel;
|
||||
use Throwable;
|
||||
use Tracy\Debugger;
|
||||
use Tracy\ILogger;
|
||||
|
||||
abstract class BaseErrorPresenter extends SecuredPresenter
|
||||
{
|
||||
|
||||
/**
|
||||
* @return ForwardResponse|CallbackResponse
|
||||
*/
|
||||
public function run(Request $request): AppResponse
|
||||
{
|
||||
$e = $request->getParameter('exception');
|
||||
|
||||
if ($e instanceof Throwable) {
|
||||
$code = $e->getCode();
|
||||
$level = ($code >= 400 && $code <= 499) ? LogLevel::WARNING : LogLevel::ERROR;
|
||||
|
||||
Debugger::log(sprintf(
|
||||
'Code %s: %s in %s:%s',
|
||||
$code,
|
||||
$e->getMessage(),
|
||||
$e->getFile(),
|
||||
$e->getLine()
|
||||
), $level);
|
||||
|
||||
Debugger::log($e, ILogger::EXCEPTION);
|
||||
}
|
||||
|
||||
if ($e instanceof BadRequestException) {
|
||||
[$module, , $sep] = Helpers::splitName($request->getPresenterName());
|
||||
|
||||
return new ForwardResponse($request->setPresenterName($module . $sep . 'Error4xx'));
|
||||
}
|
||||
|
||||
return new CallbackResponse(function (IRequest $httpRequest, IResponse $httpResponse): void {
|
||||
$header = $httpResponse->getHeader('Content-Type');
|
||||
if ($header !== null && preg_match('#^text/html(?:;|$)#', $header)) {
|
||||
require __DIR__ . '/templates/500.phtml';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
23
app/modules/Base/BasePresenter.php
Executable file
23
app/modules/Base/BasePresenter.php
Executable file
@@ -0,0 +1,23 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Base;
|
||||
|
||||
use App\Model\Latte\TemplateProperty;
|
||||
use App\Model\Security\SecurityUser;
|
||||
use App\UI\Control\TFlashMessage;
|
||||
use App\UI\Control\TModuleUtils;
|
||||
use Contributte\Application\UI\Presenter\StructuredTemplates;
|
||||
use Nette\Application\UI\Presenter;
|
||||
|
||||
/**
|
||||
* @property-read TemplateProperty $template
|
||||
* @property-read SecurityUser $user
|
||||
*/
|
||||
abstract class BasePresenter extends Presenter
|
||||
{
|
||||
|
||||
use StructuredTemplates;
|
||||
use TFlashMessage;
|
||||
use TModuleUtils;
|
||||
|
||||
}
|
||||
30
app/modules/Base/SecuredPresenter.php
Executable file
30
app/modules/Base/SecuredPresenter.php
Executable file
@@ -0,0 +1,30 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Base;
|
||||
|
||||
use App\Model\App;
|
||||
use Nette\Application\UI\ComponentReflection;
|
||||
use Nette\Security\IUserStorage;
|
||||
|
||||
abstract class SecuredPresenter extends BasePresenter
|
||||
{
|
||||
|
||||
/**
|
||||
* @param ComponentReflection|mixed $element
|
||||
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
|
||||
*/
|
||||
public function checkRequirements($element): void
|
||||
{
|
||||
if (!$this->user->isLoggedIn()) {
|
||||
if ($this->user->getLogoutReason() === IUserStorage::INACTIVITY) {
|
||||
$this->flashInfo('You have been logged out for inactivity');
|
||||
}
|
||||
|
||||
$this->redirect(
|
||||
App::DESTINATION_SIGN_IN,
|
||||
['backlink' => $this->storeRequest()]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
8
app/modules/Base/UnsecuredPresenter.php
Executable file
8
app/modules/Base/UnsecuredPresenter.php
Executable file
@@ -0,0 +1,8 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Base;
|
||||
|
||||
abstract class UnsecuredPresenter extends BasePresenter
|
||||
{
|
||||
|
||||
}
|
||||
27
app/modules/Base/templates/500.phtml
Executable file
27
app/modules/Base/templates/500.phtml
Executable file
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html><!-- "' --></textarea></script></style></pre></xmp></a></audio></button></canvas></datalist></details></dialog></iframe></listing></meter></noembed></noframes></noscript></optgroup></option></progress></rp></select></table></template></title></video>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex">
|
||||
<title>Server Error</title>
|
||||
|
||||
<style>
|
||||
#nette-error { all: initial; position: absolute; top: 0; left: 0; right: 0; height: 70vh; min-height: 400px; display: flex; align-items: center; justify-content: center; z-index: 1000 }
|
||||
#nette-error div { all: initial; max-width: 550px; background: white; color: #333; display: block }
|
||||
#nette-error h1 { all: initial; font: bold 50px/1.1 sans-serif; display: block; margin: 40px }
|
||||
#nette-error p { all: initial; font: 20px/1.4 sans-serif; margin: 40px; display: block }
|
||||
#nette-error small { color: gray }
|
||||
</style>
|
||||
|
||||
<div id=nette-error>
|
||||
<div>
|
||||
<h1>Server Error</h1>
|
||||
|
||||
<p>We're sorry! The server encountered an internal error and
|
||||
was unable to complete your request. Please try again later.</p>
|
||||
|
||||
<p><small>error 500</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.body.insertBefore(document.getElementById('nette-error'), document.body.firstChild);
|
||||
</script>
|
||||
65
app/modules/Base/templates/@layout.latte
Executable file
65
app/modules/Base/templates/@layout.latte
Executable file
@@ -0,0 +1,65 @@
|
||||
{**
|
||||
* @param string $basePath web base path
|
||||
* @param array $flashes flash messages
|
||||
*}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>{ifset title}{include title|striptags} | {/ifset}Nette Sandbox</title>
|
||||
|
||||
<link rel="stylesheet" href="{$basePath}/css/style.css">
|
||||
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
|
||||
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
|
||||
{block head}{/block}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<hgroup>
|
||||
<h1>My Dictionary</h1>
|
||||
<h2>multilanguage dictionary with pronunciations</h2>
|
||||
</hgroup>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="{link Homepage:default}">Jednoduchý</a></li>
|
||||
<li><a href="{link Homepage:ipa}">s výslovnosťou</a></li>
|
||||
<li><a href="{link Homepage:interactive}">Interaktívny</a></li>
|
||||
<li><a href="{link Homepage:alphabet}">Abeceda</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<a href="#" title="Jaro's Solutions homepage"><img src="logo.gif" alt="Jaro's Solutions" /></a>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<h1 n:ifset="$title">{$title}</h1>
|
||||
|
||||
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">{$flash->message}</div>
|
||||
|
||||
{include content}
|
||||
</article>
|
||||
|
||||
<section>
|
||||
<h1>Slovníky</h1>
|
||||
<ul>
|
||||
{foreach $translations as $tr}
|
||||
<li><a href="{link Homepage:select $tr["slug"] }">{$tr["lang"]}</a></li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<p>© 2016 Jaro's Solutions - <a href="#">Sitemap</a> </p>
|
||||
</footer>
|
||||
|
||||
{block scripts}
|
||||
<script src="https://nette.github.io/resources/js/netteForms.min.js"></script>
|
||||
<script src="{$basePath}/js/nette.ajax.js"></script>
|
||||
<script src="{$basePath}/js/main.js"></script>
|
||||
{/block}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,8 +1,6 @@
|
||||
<?php
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Presenters;
|
||||
namespace App\Modules\Front;
|
||||
|
||||
use Nette;
|
||||
use Vite;
|
||||
@@ -11,7 +9,7 @@ use Vite;
|
||||
/**
|
||||
* Base presenter for all application presenters.
|
||||
*/
|
||||
abstract class BasePresenter extends Nette\Application\UI\Presenter
|
||||
abstract class BaseFrontPresenter extends Nette\Application\UI\Presenter
|
||||
{
|
||||
public function __construct(
|
||||
private Vite $vite,
|
||||
10
app/modules/Front/Error/ErrorPresenter.php
Executable file
10
app/modules/Front/Error/ErrorPresenter.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Front\Error;
|
||||
|
||||
use App\Modules\Base\BaseErrorPresenter;
|
||||
|
||||
final class ErrorPresenter extends BaseErrorPresenter
|
||||
{
|
||||
|
||||
}
|
||||
10
app/modules/Front/Error4xx/Error4xxPresenter.php
Executable file
10
app/modules/Front/Error4xx/Error4xxPresenter.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Front\Error4xx;
|
||||
|
||||
use App\Modules\Base\BaseError4xxPresenter;
|
||||
|
||||
final class Error4xxPresenter extends BaseError4xxPresenter
|
||||
{
|
||||
|
||||
}
|
||||
7
app/modules/Front/Error4xx/templates/403.latte
Executable file
7
app/modules/Front/Error4xx/templates/403.latte
Executable file
@@ -0,0 +1,7 @@
|
||||
{block #content}
|
||||
<h1 n:block=title>Access Denied</h1>
|
||||
|
||||
<p>You do not have permission to view this page. Please try contact the web
|
||||
site administrator if you believe you should be able to view this page.</p>
|
||||
|
||||
<p><small>error 403</small></p>
|
||||
8
app/modules/Front/Error4xx/templates/404.latte
Executable file
8
app/modules/Front/Error4xx/templates/404.latte
Executable file
@@ -0,0 +1,8 @@
|
||||
{block #content}
|
||||
<h1 n:block=title>Page Not Found</h1>
|
||||
|
||||
<p>The page you requested could not be found. It is possible that the address is
|
||||
incorrect, or that the page no longer exists. Please use a search engine to find
|
||||
what you are looking for.</p>
|
||||
|
||||
<p><small>error 404</small></p>
|
||||
6
app/modules/Front/Error4xx/templates/405.latte
Executable file
6
app/modules/Front/Error4xx/templates/405.latte
Executable file
@@ -0,0 +1,6 @@
|
||||
{block #content}
|
||||
<h1 n:block=title>Method Not Allowed</h1>
|
||||
|
||||
<p>The requested method is not allowed for the URL.</p>
|
||||
|
||||
<p><small>error 405</small></p>
|
||||
6
app/modules/Front/Error4xx/templates/410.latte
Executable file
6
app/modules/Front/Error4xx/templates/410.latte
Executable file
@@ -0,0 +1,6 @@
|
||||
{block #content}
|
||||
<h1 n:block=title>Page Not Found</h1>
|
||||
|
||||
<p>The page you requested has been taken off the site. We apologize for the inconvenience.</p>
|
||||
|
||||
<p><small>error 410</small></p>
|
||||
4
app/modules/Front/Error4xx/templates/4xx.latte
Executable file
4
app/modules/Front/Error4xx/templates/4xx.latte
Executable file
@@ -0,0 +1,4 @@
|
||||
{block #content}
|
||||
<h1 n:block=title>Oops...</h1>
|
||||
|
||||
<p>Your browser sent a request that this server could not understand or process.</p>
|
||||
10
app/modules/Front/Home/HomePresenter.php
Executable file
10
app/modules/Front/Home/HomePresenter.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php //declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Front\Home;
|
||||
use App\Modules\Front\BaseFrontPresenter;
|
||||
use Nette;
|
||||
|
||||
final class HomePresenter extends BaseFrontPresenter
|
||||
{
|
||||
}
|
||||
|
||||
35
app/modules/Mailing/Home/HomePresenter.php
Executable file
35
app/modules/Mailing/Home/HomePresenter.php
Executable file
@@ -0,0 +1,35 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace App\Modules\Mailing\Home;
|
||||
|
||||
use Contributte\Mailing\IMailBuilderFactory;
|
||||
use Nette\Application\UI\Presenter;
|
||||
|
||||
class HomePresenter extends Presenter
|
||||
{
|
||||
|
||||
/** @var IMailBuilderFactory */
|
||||
private $mailBuilderFactory;
|
||||
|
||||
public function __construct(IMailBuilderFactory $mailBuilderFactory)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->mailBuilderFactory = $mailBuilderFactory;
|
||||
}
|
||||
|
||||
public function actionDefault(): void
|
||||
{
|
||||
$mail = $this->mailBuilderFactory->create();
|
||||
$mail->setSubject('Example');
|
||||
$mail->addTo('foo@example.com');
|
||||
|
||||
$mail->setTemplateFile(__DIR__ . '/templates/Emails/email.latte');
|
||||
$mail->setParameters([
|
||||
'title' => 'Title',
|
||||
'content' => 'Lorem ipsum dolor sit amet',
|
||||
]);
|
||||
|
||||
$mail->send();
|
||||
}
|
||||
|
||||
}
|
||||
19
app/modules/Mailing/Home/templates/@layout.latte
Executable file
19
app/modules/Mailing/Home/templates/@layout.latte
Executable file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>{ifset title}{include title|stripHtml} | {/ifset}Nette Web</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">{$flash->message}</div>
|
||||
|
||||
{include content}
|
||||
|
||||
{block scripts}
|
||||
<script src="https://nette.github.io/resources/js/netteForms.min.js"></script>
|
||||
{/block}
|
||||
</body>
|
||||
</html>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user