Skip to content

Commit 50bf0a1

Browse files
committed
Merge branch 'develop'
2 parents 491a4b7 + 3d40c7f commit 50bf0a1

34 files changed

+1252
-214
lines changed

config/dependencies.php

+19
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
declare(strict_types=1);
44

5+
use App\Adapter\Repository\Database\DbLongUrlRepository;
6+
use App\Domain\Repository\LongUrlRepository;
7+
use App\Shared\Adapter\Contracts\DatabaseOrm;
8+
use App\Shared\Adapter\Contracts\UuidGenerator;
9+
use App\Shared\Infra\PdoOrm;
10+
use App\Shared\Infra\RamseyUiidAdapter;
511
use DI\ContainerBuilder;
612
use Odan\Session\Middleware\SessionMiddleware;
713
use Odan\Session\PhpSession;
@@ -24,5 +30,18 @@
2430
$storage = [];
2531
return new Messages($storage);
2632
},
33+
DatabaseOrm::class => function (ContainerInterface $c) {
34+
return new PdoOrm($c->get('db'));
35+
},
36+
UuidGenerator::class => function (ContainerInterface $c) {
37+
return new RamseyUiidAdapter();
38+
},
39+
LongUrlRepository::class => function (ContainerInterface $c) {
40+
return new DbLongUrlRepository(
41+
$c->get(DatabaseOrm::class),
42+
$c->get(RamseyUiidAdapter::class),
43+
$c->get('config')
44+
);
45+
},
2746
]);
2847
};

config/middleware.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
declare(strict_types=1);
44

55
use Slim\App;
6-
use App\Middleware\SessionMiddleware;
6+
use App\Adapter\Middleware\SessionMiddleware;
77
use Slim\Views\TwigMiddleware;
88

99
return function (App $app) {

config/routes.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
declare(strict_types=1);
44

5-
use App\Controllers\AccessUrlController;
6-
use App\Controllers\HomeController;
7-
use App\Controllers\ShortenUrlController;
5+
use App\Adapter\Controllers\AccessUrlController;
6+
use App\Adapter\Controllers\HomeController;
7+
use App\Adapter\Controllers\ShortenUrlController;
88
use Slim\App;
99
use Slim\Routing\RouteCollectorProxy;
1010

public_html/js/script.js

+22-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@ $(document).ready(function () {
33

44
if (urlHistory) {
55
urlHistory = JSON.parse(urlHistory);
6+
7+
urlHistory = urlHistory.map(row => {
8+
if (!row.hasOwnProperty('huge')) return row;
9+
return {
10+
longUrl: row.huge,
11+
shortenedUrl: row.shortened,
12+
createdAt: row.created_at,
13+
economyRate: row.economyRate,
14+
};
15+
});
16+
17+
window.localStorage.setItem('url_history', JSON.stringify(urlHistory));
18+
619
for (let index in urlHistory) {
720
if (index === '5') break;
821
$('div.shortened-urls ul').append(getHistoryItemTemplate(urlHistory[index]));
@@ -58,7 +71,7 @@ $(document).ready(function () {
5871
$.ajax({
5972
url: `${baseUrl}/api/public/shorten`,
6073
type: 'post',
61-
data: { huge_url : $inputUrl.val() },
74+
data: { long_url : $inputUrl.val() },
6275
beforeSend : function() {
6376
$inputUrl.prop('disabled', true);
6477
$btnShorten.prop('disabled', true);
@@ -85,15 +98,15 @@ $(document).ready(function () {
8598

8699
const $divResult = $('div.shortened-url-result');
87100
$divResult.css('display', 'flex');
88-
$divResult.find('a').attr('href', payload.data.shortened);
89-
$divResult.find('a span.url-text').html(payload.data.shortened);
101+
$divResult.find('a').attr('href', payload.data.shortenedUrl);
102+
$divResult.find('a span.url-text').html(payload.data.shortenedUrl);
90103
$divResult.find('a span.badge').html(`-${payload.data.economyRate}%`);
91-
$divResult.find('button').attr('data-url', payload.data.shortened);
104+
$divResult.find('button').attr('data-url', payload.data.shortenedUrl);
92105
}).fail(function(jqXHR, textStatus, msg) {
93106
if (jqXHR.status === 400) {
94107
const payload = jqXHR.responseJSON;
95108
let message = '';
96-
switch (payload.data.huge_url) {
109+
switch (payload.data.longUrl) {
97110
case 'invalid-url':
98111
message = 'Insira ua URL válida com "http://" ou "https://" para poder encurtar.';
99112
break;
@@ -132,16 +145,16 @@ $(document).ready(function () {
132145
function getHistoryItemTemplate(data) {
133146
return `
134147
<li>
135-
<div class="long-url" title="${data.huge}">${data.huge.substring(0, 38)}...</div>
148+
<div class="long-url" title="${data.longUrl}">${data.longUrl.substring(0, 38)}...</div>
136149
<div class="short-url">
137150
<div class="link">
138-
<a href="${data.shortened}" target="_blank" title="URL encurtada de ${data.huge}">
139-
${data.shortened}
151+
<a href="${data.shortenedUrl}" target="_blank" title="URL encurtada de ${data.longUrl}">
152+
${data.shortenedUrl}
140153
</a>
141154
</div>
142155
<div class="copy">
143156
<div class="d-grid gap-2">
144-
<button data-url="${data.shortened}" class="btn btn-outline-primary copy-button">
157+
<button data-url="${data.shortenedUrl}" class="btn btn-outline-primary copy-button">
145158
<i class="far fa-copy"></i> Copiar
146159
</button>
147160
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Adapter\Controllers;
6+
7+
use App\Domain\Repository\LongUrlRepository;
8+
use Psr\Container\ContainerInterface;
9+
use Psr\Http\Message\RequestInterface as Request;
10+
use Psr\Http\Message\ResponseInterface as Response;
11+
use Slim\Views\Twig;
12+
13+
final class AccessUrlController
14+
{
15+
private Twig $view;
16+
private LongUrlRepository $longUrlRepo;
17+
18+
public function __construct(ContainerInterface $container)
19+
{
20+
$this->view = $container->get('view');
21+
$this->longUrlRepo = $container->get(LongUrlRepository::class);
22+
}
23+
24+
public function __invoke(Request $request, Response $response, array $args): Response
25+
{
26+
$url = $this->longUrlRepo->getUrlByPath($args['path']);
27+
28+
if (is_null($url)) {
29+
return $this->view->render($response, 'notfound.html.twig', []);
30+
}
31+
32+
$this->longUrlRepo->registerAccess($url, [
33+
'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'],
34+
'REMOTE_PORT' => $_SERVER['REMOTE_PORT'],
35+
'SERVER_NAME' => $_SERVER['SERVER_NAME'],
36+
'REQUEST_URI' => $_SERVER['REQUEST_URI'],
37+
'HTTP_HOST' => $_SERVER['HTTP_HOST'],
38+
'HTTP_USER_AGENT' => $_SERVER['HTTP_USER_AGENT']
39+
]);
40+
41+
$newResponse = $response
42+
->withHeader('Content-type', 'application/json')
43+
->withStatus(302)
44+
->withHeader('Location', $url->longUrl->value());
45+
46+
return $newResponse;
47+
}
48+
}

src/Controllers/HomeController.php src/Adapter/Controllers/HomeController.php

+6-17
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,29 @@
22

33
declare(strict_types=1);
44

5-
namespace App\Controllers;
5+
namespace App\Adapter\Controllers;
66

77
use PDO;
8+
use App\Domain\Repository\LongUrlRepository;
89
use Psr\Container\ContainerInterface;
910
use Psr\Http\Message\RequestInterface as Request;
1011
use Psr\Http\Message\ResponseInterface as Response;
1112
use Slim\Views\Twig;
1213

1314
final class HomeController
1415
{
15-
private PDO $db;
1616
private Twig $view;
17+
private LongUrlRepository $longUrlRepo;
1718

1819
public function __construct(ContainerInterface $container)
1920
{
20-
$this->db = $container->get('db');
2121
$this->view = $container->get('view');
22+
$this->longUrlRepo = $container->get(LongUrlRepository::class);
2223
}
2324

2425
public function __invoke(Request $request, Response $response, array $args): Response
2526
{
26-
$stmt = $this->db->prepare(trim("
27-
select count(*) as total_urls from urls
28-
union all
29-
select count(*) as total_clicks from urls_logs
30-
"));
31-
32-
$stmt->execute();
33-
34-
[$totalUrls, $totalClicks] = $stmt->fetchAll(PDO::FETCH_COLUMN);
35-
36-
return $this->view->render($response, 'index.html.twig', [
37-
'totalUrls' => ceil($totalUrls),
38-
'totalClicks' => ceil($totalClicks)
39-
]);
27+
$rows = $this->longUrlRepo->countUrlsAndClicks();
28+
return $this->view->render($response, 'index.html.twig', $rows);
4029
}
4130
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Adapter\Controllers;
6+
7+
use App\Domain\UseCase\ShortenUrl\InputData;
8+
use App\Domain\UseCase\ShortenUrl\ShortenUrl;
9+
use App\Domain\ValueObject\LongUrlType;
10+
use Psr\Container\ContainerInterface;
11+
use Psr\Http\Message\RequestInterface as Request;
12+
use Psr\Http\Message\ResponseInterface as Response;
13+
14+
final class ShortenUrlController
15+
{
16+
private array $config;
17+
private ShortenUrl $useCase;
18+
19+
public function __construct(ContainerInterface $container)
20+
{
21+
$this->config = $container->get('config');
22+
$this->useCase = $container->get(ShortenUrl::class);
23+
}
24+
25+
public function __invoke(Request $request, Response $response, array $args): Response
26+
{
27+
$contents = $request->getParsedBody();
28+
29+
if (empty($contents) || !array_key_exists('long_url', $contents)) {
30+
$newResponse = $response
31+
->withHeader('Content-type', 'application/json')
32+
->withStatus(400);
33+
34+
$newResponse->getBody()->write(json_encode([
35+
'status' => 'fail',
36+
'data' => ['long_url' => 'missing-param']
37+
]));
38+
39+
return $newResponse;
40+
}
41+
42+
if (empty($contents['long_url'])) {
43+
$newResponse = $response
44+
->withHeader('Content-type', 'application/json')
45+
->withStatus(400);
46+
47+
$newResponse->getBody()->write(json_encode([
48+
'status' => 'fail',
49+
'data' => ['long_url' => 'empty-value']
50+
]));
51+
52+
return $newResponse;
53+
}
54+
55+
$result = $this->useCase->execute(InputData::create([
56+
'longUrl' => $contents['long_url'],
57+
'type' => LongUrlType::TYPE_RANDOM,
58+
'baseUrl' => $this->config['baseUrl'],
59+
]));
60+
61+
$newResponse = $response
62+
->withHeader('Content-type', 'application/json')
63+
->withStatus(200);
64+
65+
$newResponse->getBody()->write(json_encode([
66+
'status' => 'success',
67+
'data' => $result->values()
68+
]));
69+
70+
return $newResponse;
71+
}
72+
}

src/Middleware/SessionMiddleware.php src/Adapter/Middleware/SessionMiddleware.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace App\Middleware;
5+
namespace App\Adapter\Middleware;
66

77
use Psr\Http\Message\ResponseInterface as Response;
88
use Psr\Http\Message\ServerRequestInterface as Request;

src/Middleware/SlimFlashMiddleware.php src/Adapter/Middleware/SlimFlashMiddleware.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace App\Middleware;
3+
namespace App\Adapter\Middleware;
44

55
use Odan\Session\SessionInterface;
66
use Psr\Http\Message\ResponseInterface;

0 commit comments

Comments
 (0)