Compare commits

...

11 commits

10 changed files with 194 additions and 8 deletions

View file

@ -0,0 +1,108 @@
<?php
namespace App\Text;
use App\Text\Text;
use App\Text\CreateTextDto;
use App\Text\TextRepository;
class JsonTextRepository implements TextRepository
{
private string $filePath;
public function __construct()
{
$this->filePath = __DIR__.'/../../data/texts.json';
}
public function create(CreateTextDto $dto): Text
{
$texts = $this->readTexts();
$id = $this->getNextId($texts);
$text = new Text(id: $id, name: $dto->name);
$texts[] = ['id' => $id, 'name' => $dto->name];
$this->writeTexts($texts);
return $text;
}
public function find(int $id): ?Text
{
$texts = $this->readTexts();
foreach ($texts as $data) {
if ($data['id'] === $id) {
return new Text(
id: $data['id'],
name: $data['name'],
);
}
}
return null;
}
/**
* @return Text[]
*/
public function getAll(): array
{
$texts = $this->readTexts();
return array_map(
function (array $data) {
return new Text(
id: $data['id'],
name: $data['name'],
);
},
$texts
);
}
/**
* @return array
*/
private function readTexts(): array
{
if (!file_exists($this->filePath)) {
return [];
}
$content = file_get_contents($this->filePath);
return json_decode($content, true) ?? [];
}
/**
* @param array $texts
*/
private function writeTexts(array $texts): void
{
file_put_contents(
$this->filePath,
json_encode($texts, JSON_PRETTY_PRINT)
);
}
/**
* @param array $texts
*/
private function getNextId(array $texts): int
{
if (empty($texts)) {
return 1;
}
$maxId = 0;
foreach ($texts as $text) {
if ($text['id'] > $maxId) {
$maxId = $text['id'];
}
}
return $maxId + 1;
}
}

View file

@ -10,4 +10,9 @@ interface TextRepository
public function create(CreateTextDto $dto): Text;
public function find(int $id): ?Text;
/**
* @return Text[]
*/
public function getAll(): array;
}

View file

@ -2,10 +2,15 @@
namespace App\View;
use App\Text\TextRepository;
use Psr\Http\Message\ResponseInterface as Response;
class ViewController
{
public function __construct(
private TextRepository $textRepository,
) {}
public function admin(Response $response): Response
{
$html = file_get_contents(__DIR__.'/../../views/templates/admin.php', true);
@ -13,4 +18,20 @@ class ViewController
return $response;
}
public function texts(Response $response): Response
{
$texts = $this->textRepository->getAll();
$textsList = '';
foreach ($texts as $text) {
$textsList .= '<li>' . htmlspecialchars($text->getName()) . '</li>';
}
$html = file_get_contents(__DIR__.'/../../views/templates/texts.php', true);
$html = str_replace('{{texts}}', $textsList, $html);
$response->getBody()->write($html);
return $response;
}
}

View file

@ -12,5 +12,6 @@ $app = Bridge::create($container);
$app->addErrorMiddleware(true, true, true);
$app->get('/admin', [ViewController::class, 'admin']);
$app->get('/admin/texts', [ViewController::class, 'texts']);
return $app;

View file

@ -1,9 +1,12 @@
<?php
use DI;
use DI\Container;
use App\Text\TextRepository;
use App\Text\JsonTextRepository;
$container = new Container([
TextRepository::class => DI\create(JsonTextRepository::class),
]);
return $container;

View file

@ -1,7 +1,24 @@
describe('The admin page', () => {
it('successfully loads texts', () => {
cy.visit('/admin')
cy.get('#newTextname').type('new text')
cy.get('#submit').click()
beforeEach(() => {
cy.visit('/admin')
})
it('navigates to texts page', () => {
cy.get('#texts').click()
cy.url().should('include', '/admin/texts')
})
it('shows texts page with heading and form', () => {
cy.visit('/admin/texts')
cy.get('h1').should('contain', 'Texts')
cy.get('#newTextName').should('exist')
cy.get('#submit').should('exist')
})
it('creates a new text', () => {
cy.visit('/admin/texts')
cy.get('#newTextName').type('Test Text')
cy.get('#submit').click()
cy.contains('Test Text')
})
})

1
data/texts.json Normal file
View file

@ -0,0 +1 @@
[]

View file

@ -47,4 +47,20 @@ class FakeTextRepository implements TextRepository
{
return count($this->existingTexts);
}
/**
* @return Text[]
*/
public function getAll(): array
{
return array_map(
function (Text $text) {
return new Text(
id: $text->getId(),
name: $text->getName(),
);
},
$this->existingTexts
);
}
}

View file

@ -1,10 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>Daily Goals</title>
<title>Daily Goals - Admin</title>
</head>
<body>
<input id='newTextname'/>
<button id='submit'>submit</button>
<a href="/admin/texts" id="texts">Texts</a>
</body>
</html>

15
views/templates/texts.php Normal file
View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>Daily Goals - Texts</title>
</head>
<body>
<h1>Texts</h1>
<a href="/admin" id="back">Back to Admin</a>
<ul id="texts-list">
{{texts}}
</ul>
<input id="newTextName"/>
<button id="submit">submit</button>
</body>
</html>