diff --git a/composer.json b/composer.json index 9d6624a..e39c889 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ "slim/flash": "^0.4.0", "guzzlehttp/guzzle": "^7.0", "imangazaliev/didom": "^2.0", - "laravel/helpers": "^1.7" + "laravel/helpers": "^1.7", + "illuminate/support": "^10.43" }, "require-dev": { "squizlabs/php_codesniffer": "^3.7" diff --git a/composer.lock b/composer.lock index f245458..cc278fa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2a38d27e8f85809b1916f39805f5a1d0", + "content-hash": "8441320cd01d6f2aff976831605d7375", "packages": [ { "name": "carbonphp/carbon-doctrine-types", @@ -744,16 +744,16 @@ }, { "name": "illuminate/support", - "version": "v10.38.2", + "version": "v10.43.0", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "a9f486d76d5403b0c95b8532cd151a0a960f9565" + "reference": "6edb9350a0d13be5cea52718280e0025d3957895" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/a9f486d76d5403b0c95b8532cd151a0a960f9565", - "reference": "a9f486d76d5403b0c95b8532cd151a0a960f9565", + "url": "https://api.github.com/repos/illuminate/support/zipball/6edb9350a0d13be5cea52718280e0025d3957895", + "reference": "6edb9350a0d13be5cea52718280e0025d3957895", "shasum": "" }, "require": { @@ -811,7 +811,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-12-19T15:11:55+00:00" + "time": "2024-01-29T14:56:21+00:00" }, { "name": "imangazaliev/didom", diff --git a/public/index.php b/public/index.php index e6133a9..5a30adf 100644 --- a/public/index.php +++ b/public/index.php @@ -16,6 +16,8 @@ use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\TransferException; use DiDom\Document; +use Illuminate\Support\Collection; +use Illuminate\Support\Str; session_start(); @@ -41,17 +43,21 @@ $container->set('flash', function () { return new \Slim\Flash\Messages(); }); + $container->set('connection', function () { $conn = new App\Connection(); return $conn->connect(); }); + $container->set('renderer', function () use ($container) { $templateVariables = [ 'routeName' => $container->get('routeName'), 'router' => $container->get('router'), 'flash' => $container->get('flash')->getMessages() ]; - return new \Slim\Views\PhpRenderer(__DIR__ . '/../templates', $templateVariables); + $renderer = new \Slim\Views\PhpRenderer(__DIR__ . '/../templates', $templateVariables); + $renderer->setLayout('layout.phtml'); + return $renderer; }); $app->get('/', function ($request, $response) { @@ -59,11 +65,11 @@ })->setName('home'); $app->get('/urls', function ($request, $response) { - $allUrlsData = $this->get('connection') + $allUrls = $this->get('connection') ->query('SELECT id, name FROM urls ORDER BY id DESC') ->fetchAll(PDO::FETCH_ASSOC); - $lastChecksData = $this->get('connection') + $lastChecks = $this->get('connection') ->query('SELECT url_id, MAX(created_at) AS last_check_created_at, @@ -72,49 +78,47 @@ GROUP BY url_id, status_code') ->fetchAll(PDO::FETCH_ASSOC); - $data = array_map(function ($url) use ($lastChecksData) { - foreach ($lastChecksData as $check) { - if ($url['id'] === $check['url_id']) { - $url['last_check_created_at'] = $check['last_check_created_at']; - $url['status_code'] = $check['status_code']; - } - } - return $url; - }, $allUrlsData); + $urls = collect($allUrls); + $urlChecks = collect($lastChecks)->keyBy('url_id'); - $params = ['data' => $data]; - return $this->get('renderer')->render($response, 'urls/list.phtml', $params); -})->setName('urls'); + $data = $urls->map(function ($url) use ($urlChecks) { + $urlCheck = $urlChecks->firstWhere('url_id', $url['id']); -$app->get('/urls/{id}', function ($request, $response, $args) { - $id = $args['id']; + return [ + 'id' => $url['id'], + 'name' => $url['name'], + 'last_check_created_at' => $urlCheck['last_check_created_at'] ?? null, + 'status_code' => $urlCheck['status_code'] ?? null, + ]; + }); - $allIdData = $this->get('connection') - ->query('SELECT id FROM urls') - ->fetchAll(PDO::FETCH_COLUMN); + $params = ['data' => $data]; + return $this->get('renderer')->render($response, 'urls/index.phtml', $params); +})->setName('urls.index'); - if (!in_array($id, $allIdData)) { - return $this->get('renderer')->render($response->withStatus(404), 'error404.phtml'); - } +$app->get('/urls/{id:[0-9]+}', function ($request, $response, $args) { + $id = $args['id']; $urlDataQuery = 'SELECT * FROM urls WHERE id = :id'; $urlDataStmt = $this->get('connection')->prepare($urlDataQuery); $urlDataStmt->execute([':id' => $id]); $urlData = $urlDataStmt->fetch(); + if (empty($urlData)) { + return $this->get('renderer')->render($response->withStatus(404), 'error404.phtml'); + } + $urlChecksQuery = 'SELECT * FROM url_checks WHERE url_id = :id ORDER BY id DESC'; $urlChecksStmt = $this->get('connection')->prepare($urlChecksQuery); $urlChecksStmt->execute([':id' => $id]); $urlChecksData = $urlChecksStmt->fetchAll(); $params = [ - 'id' => $urlData['id'], - 'name' => $urlData['name'], - 'created_at' => $urlData['created_at'], + 'url' => $urlData, 'urlChecks' => $urlChecksData ]; return $this->get('renderer')->render($response, 'urls/show.phtml', $params); -})->setName('url'); +})->setName('urls.show'); $app->post('/urls', function ($request, $response) { $url = $request->getParsedBodyParam('url'); @@ -132,36 +136,34 @@ return $this->get('renderer')->render($response->withStatus(422), 'home.phtml', $params); } - $parsedUrl = parse_url(strtolower($url['name'])); - $name = "{$parsedUrl['scheme']}://{$parsedUrl['host']}"; + $parsedUrl = parse_url(Str::lower($url['name'])); + $urlName = "{$parsedUrl['scheme']}://{$parsedUrl['host']}"; $urlIdQuery = 'SELECT id FROM urls WHERE name = :name'; $urlIdStmt = $this->get('connection')->prepare($urlIdQuery); - $urlIdStmt->execute([':name' => $name]); + $urlIdStmt->execute([':name' => $urlName]); $urlId = $urlIdStmt->fetch(); if (!empty($urlId)) { $this->get('flash')->addMessage('success', 'Страница уже существует'); - return $response->withRedirect($this->get('router')->urlFor('url', ['id' => $urlId['id']])); + return $response->withRedirect($this->get('router')->urlFor('urls.show', ['id' => $urlId['id']])); } - $created_at = Carbon::now(); - $newUrlQuery = 'INSERT INTO urls(name, created_at) VALUES(:name, :created_at)'; $newUrlStmt = $this->get('connection')->prepare($newUrlQuery); - $newUrlStmt->execute([':name' => $name, ':created_at' => $created_at]); + $newUrlStmt->execute([':name' => $urlName, ':created_at' => Carbon::now()]); - $id = $this->get('connection')->lastInsertId(); + $lastInsertId = $this->get('connection')->lastInsertId(); $this->get('flash')->addMessage('success', 'Страница успешно добавлена'); - return $response->withRedirect($this->get('router')->urlFor('url', ['id' => $id])); -}); + return $response->withRedirect($this->get('router')->urlFor('urls.show', ['id' => $lastInsertId])); +})->setName('urls.store'); -$app->post('/urls/{url_id}/checks', function ($request, $response, $args) { - $url_id = $args['url_id']; +$app->post('/urls/{url_id:[0-9]+}/checks', function ($request, $response, $args) { + $urlId = $args['url_id']; $urlNameQuery = 'SELECT name FROM urls WHERE id = :id'; $urlNameStmt = $this->get('connection')->prepare($urlNameQuery); - $urlNameStmt->execute([':id' => $url_id]); + $urlNameStmt->execute([':id' => $urlId]); $urlName = $urlNameStmt->fetch(); $client = new Client(); @@ -172,29 +174,29 @@ } catch (ClientException $e) { $res = $e->getResponse(); $this->get('flash')->addMessage('warning', 'Проверка была выполнена успешно, но сервер ответил c ошибкой'); - return $response->withRedirect($this->get('router')->urlFor('url', ['id' => $url_id])); + return $response->withRedirect($this->get('router')->urlFor('urls.show', ['id' => $urlId])); } catch (ServerException $e) { $res = $e->getResponse(); $this->get('flash')->addMessage('warning', 'Проверка была выполнена успешно, но сервер ответил c ошибкой'); - return $response->withRedirect($this->get('router')->urlFor('url', ['id' => $url_id])); + return $response->withRedirect($this->get('router')->urlFor('urls.show', ['id' => $urlId])); } catch (ConnectException $e) { - $this->get('flash')->addMessage('failure', 'Произошла ошибка при проверке, не удалось подключиться'); - return $response->withRedirect($this->get('router')->urlFor('url', ['id' => $url_id])); + $this->get('flash')->addMessage('error', 'Произошла ошибка при проверке, не удалось подключиться'); + return $response->withRedirect($this->get('router')->urlFor('urls.show', ['id' => $urlId])); } catch (TransferException $e) { - $this->get('flash')->addMessage('failure', 'Упс что-то пошло не так'); - return $response->withRedirect($this->get('router')->urlFor('url', ['id' => $url_id])); + $this->get('flash')->addMessage('error', 'Упс что-то пошло не так'); + return $response->withRedirect($this->get('router')->urlFor('urls.show', ['id' => $urlId])); } - $status_code = $res->getStatusCode(); - - $document = new Document((string) $res->getBody()); - $h1 = $document->first('h1') ? mb_substr(optional($document->first('h1'))->text(), 0, 255) : ''; - $title = $document->first('title') ? mb_substr(optional($document->first('title'))->text(), 0, 255) : ''; - $description = $document->first('meta[name="description"]') - ? mb_substr(optional($document->first('meta[name="description"]'))->getAttribute('content'), 0, 255) - : ''; + $statusCode = $res->getStatusCode(); + $resBody = (string) $res->getBody(); - $check_created_at = Carbon::now(); + if (!empty($resBody)) { + $document = new Document($resBody); + $h1 = Str::limit(optional($document->first('h1'))->text(), 250, '(...)'); + $title = Str::limit(optional($document->first('title'))->text(), 250, '(...)'); + $description = Str::limit(optional($document->first('meta[name="description"]')) + ->getAttribute('content'), 250, '(...)'); + } $newCheckQuery = 'INSERT INTO url_checks( url_id, @@ -213,15 +215,15 @@ )'; $newCheckStmt = $this->get('connection')->prepare($newCheckQuery); $newCheckStmt->execute([ - ':url_id' => $url_id, - ':status_code' => $status_code, - ':h1' => $h1, - ':title' => $title, - ':description' => $description, - ':check_created_at' => $check_created_at + ':url_id' => $urlId, + ':status_code' => $statusCode ?? null, + ':h1' => $h1 ?? null, + ':title' => $title ?? null, + ':description' => $description ?? null, + ':check_created_at' => Carbon::now() ]); - return $response->withRedirect($this->get('router')->urlFor('url', ['id' => $url_id])); -}); + return $response->withRedirect($this->get('router')->urlFor('urls.show', ['id' => $urlId])); +})->setName('urls.check'); $app->run(); diff --git a/templates/home.phtml b/templates/home.phtml index c31c8c3..017fc05 100644 --- a/templates/home.phtml +++ b/templates/home.phtml @@ -1,11 +1,9 @@ - -

Анализатор страниц

Бесплатно проверяйте сайты на SEO пригодность

-
+
-
- - + \ No newline at end of file diff --git a/templates/header.phtml b/templates/layout.phtml similarity index 65% rename from templates/header.phtml rename to templates/layout.phtml index a257f78..88c8dad 100644 --- a/templates/header.phtml +++ b/templates/layout.phtml @@ -23,8 +23,8 @@ @@ -32,4 +32,22 @@ +
+ + + + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/templates/urls/list.phtml b/templates/urls/index.phtml similarity index 70% rename from templates/urls/list.phtml rename to templates/urls/index.phtml index 845fca4..b4ad16d 100644 --- a/templates/urls/list.phtml +++ b/templates/urls/index.phtml @@ -1,5 +1,3 @@ - -

Сайты

@@ -15,17 +13,15 @@ - + - - + +
-
- - + \ No newline at end of file diff --git a/templates/urls/show.phtml b/templates/urls/show.phtml index 65900f9..366f76c 100644 --- a/templates/urls/show.phtml +++ b/templates/urls/show.phtml @@ -1,41 +1,24 @@ - - -
- - - - - - - - - - - - - -
-

Сайт:

+

Сайт:

- + - + - +
ID
Имя
Дата создания

Проверки

- + @@ -51,16 +34,14 @@ - - - - + + + +
-
- - + \ No newline at end of file