шаг 3 завершен
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once dirname(__DIR__, 2) . '/admin/index.php';
|
||||
@@ -10,6 +10,50 @@ body {
|
||||
background: #f7f8f4;
|
||||
}
|
||||
|
||||
.site-utility {
|
||||
width: min(1080px, calc(100% - 48px));
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
margin: 18px auto 0;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
appearance: none;
|
||||
border: 1px solid #cfd8c9;
|
||||
border-radius: 8px;
|
||||
padding: 10px 12px;
|
||||
font: inherit;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #1d5d3b;
|
||||
background: #ffffff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
border-color: #9fb194;
|
||||
background: #f5f8f1;
|
||||
}
|
||||
|
||||
.breadcrumbs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 7px;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
font-size: 14px;
|
||||
color: #687466;
|
||||
}
|
||||
|
||||
.breadcrumbs a {
|
||||
color: #1d5d3b;
|
||||
}
|
||||
|
||||
.breadcrumbs-separator {
|
||||
color: #a3ad9d;
|
||||
}
|
||||
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
display: grid;
|
||||
@@ -25,6 +69,10 @@ body {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.start-screen.wide {
|
||||
width: min(1080px, 100%);
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
margin: 0 0 8px;
|
||||
font-size: 14px;
|
||||
@@ -42,6 +90,25 @@ p {
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0 0 16px;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #1d5d3b;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.status-box {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
@@ -78,3 +145,195 @@ p {
|
||||
.primary-button:hover {
|
||||
background: #16492e;
|
||||
}
|
||||
|
||||
.content-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 18px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.panel {
|
||||
padding: 20px;
|
||||
border: 1px solid #dfe5da;
|
||||
border-radius: 8px;
|
||||
background: #fbfcf8;
|
||||
}
|
||||
|
||||
.products-panel {
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.section-heading .eyebrow,
|
||||
.section-heading h2 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.subtle-link {
|
||||
flex: 0 0 auto;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.muted {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
color: #687466;
|
||||
}
|
||||
|
||||
.category-list {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.category-list .category-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin: 8px 0 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.category-list li {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.category-list.depth-1 li {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.category-list.depth-2 {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.category-list.depth-2 li {
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.settings-list {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.settings-list div {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 12px;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.settings-list dt {
|
||||
color: #687466;
|
||||
}
|
||||
|
||||
.settings-list dd {
|
||||
margin: 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.product-grid,
|
||||
.admin-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.product-card,
|
||||
.admin-tile {
|
||||
min-height: 96px;
|
||||
padding: 16px;
|
||||
border: 1px solid #dfe5da;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.product-card p {
|
||||
margin: 0 0 10px;
|
||||
font-size: 14px;
|
||||
color: #687466;
|
||||
}
|
||||
|
||||
.product-card .product-category {
|
||||
margin-bottom: 8px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
color: #7a856f;
|
||||
}
|
||||
|
||||
.price-line {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
font-size: 14px;
|
||||
color: #2d372f;
|
||||
}
|
||||
|
||||
.price-tiers {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
margin: 12px 0 0;
|
||||
padding: 10px 0 0;
|
||||
border-top: 1px solid #e3e8de;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.price-tiers li {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 8px;
|
||||
align-items: baseline;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.price-tiers span {
|
||||
color: #687466;
|
||||
}
|
||||
|
||||
.price-tiers strong {
|
||||
color: #1d5d3b;
|
||||
}
|
||||
|
||||
.admin-tile {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
min-height: 72px;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.site-utility {
|
||||
width: calc(100% - 32px);
|
||||
display: grid;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.content-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.settings-list div {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
display: grid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Core\Database;
|
||||
|
||||
require_once dirname(__DIR__) . '/app/bootstrap.php';
|
||||
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
||||
|
||||
echo "RybStock diagnostic\n";
|
||||
echo "version: 2026-06-04-02\n";
|
||||
echo "file: " . __FILE__ . "\n";
|
||||
echo "base_path: " . base_path() . "\n";
|
||||
echo "db: " . app_env('DB_DATABASE', '') . "\n";
|
||||
echo "home_text_expected: Каталог открывается уже на главной странице\n";
|
||||
echo "schema_mtime: " . date('Y-m-d H:i:s', filemtime(base_path('database/schema.sql'))) . "\n";
|
||||
echo "seed_mtime: " . date('Y-m-d H:i:s', filemtime(base_path('database/seed.sql'))) . "\n";
|
||||
|
||||
try {
|
||||
$pdo = Database::pdo();
|
||||
echo "db_status: connected\n";
|
||||
|
||||
$tables = $pdo->query('SHOW TABLES')->fetchAll(PDO::FETCH_COLUMN);
|
||||
echo "tables_count: " . count($tables) . "\n";
|
||||
|
||||
if (in_array('categories', $tables, true)) {
|
||||
echo "categories_count: " . $pdo->query('SELECT COUNT(*) FROM categories')->fetchColumn() . "\n";
|
||||
echo "root_categories:\n";
|
||||
|
||||
$statement = $pdo->query('SELECT id, name, slug FROM categories WHERE parent_id IS NULL ORDER BY sort_order LIMIT 30');
|
||||
foreach ($statement->fetchAll() as $category) {
|
||||
echo "- {$category['name']} ({$category['slug']})\n";
|
||||
}
|
||||
} else {
|
||||
echo "categories_table: missing\n";
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
echo "db_status: error\n";
|
||||
echo "error: " . $exception->getMessage() . "\n";
|
||||
}
|
||||
+2
-16
@@ -2,22 +2,8 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Core\Database;
|
||||
use App\Controllers\HomeController;
|
||||
|
||||
require_once dirname(__DIR__) . '/app/bootstrap.php';
|
||||
|
||||
$dbStatus = 'not_checked';
|
||||
|
||||
try {
|
||||
Database::pdo()->query('SELECT 1');
|
||||
$dbStatus = 'connected';
|
||||
} catch (Throwable $exception) {
|
||||
$dbStatus = app_env('APP_DEBUG', 'false') === 'true'
|
||||
? 'error: ' . $exception->getMessage()
|
||||
: 'error';
|
||||
}
|
||||
|
||||
view('pages/home', [
|
||||
'title' => 'Рыбсток',
|
||||
'dbStatus' => $dbStatus,
|
||||
]);
|
||||
(new HomeController())->index();
|
||||
|
||||
@@ -12,6 +12,7 @@ $actualToken = $_GET['token'] ?? '';
|
||||
$canRun = $isLocal && $expectedToken !== '' && hash_equals($expectedToken, (string) $actualToken);
|
||||
$result = null;
|
||||
$error = null;
|
||||
$stats = install_stats();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (!$canRun) {
|
||||
@@ -22,6 +23,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$pdo = Database::pdo();
|
||||
run_sql_file($pdo, base_path('database/schema.sql'));
|
||||
run_sql_file($pdo, base_path('database/seed.sql'));
|
||||
$stats = install_stats();
|
||||
$result = 'База данных установлена. Таблицы и стартовые данные созданы.';
|
||||
} catch (Throwable $exception) {
|
||||
http_response_code(500);
|
||||
@@ -32,6 +34,33 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
}
|
||||
}
|
||||
|
||||
function install_stats(): array
|
||||
{
|
||||
try {
|
||||
$pdo = Database::pdo();
|
||||
$tables = $pdo->query('SHOW TABLES')->fetchAll(PDO::FETCH_COLUMN);
|
||||
$categoryCount = in_array('categories', $tables, true)
|
||||
? (int) $pdo->query('SELECT COUNT(*) FROM categories')->fetchColumn()
|
||||
: 0;
|
||||
$firstCategories = in_array('categories', $tables, true)
|
||||
? $pdo->query('SELECT name FROM categories WHERE parent_id IS NULL ORDER BY sort_order LIMIT 12')->fetchAll(PDO::FETCH_COLUMN)
|
||||
: [];
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'database' => app_env('DB_DATABASE', ''),
|
||||
'tables_count' => count($tables),
|
||||
'category_count' => $categoryCount,
|
||||
'first_categories' => $firstCategories,
|
||||
];
|
||||
} catch (Throwable $exception) {
|
||||
return [
|
||||
'ok' => false,
|
||||
'error' => $exception->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
function run_sql_file(PDO $pdo, string $path): void
|
||||
{
|
||||
if (!is_file($path)) {
|
||||
@@ -62,6 +91,39 @@ function run_sql_file(PDO $pdo, string $path): void
|
||||
<h1>Установка базы</h1>
|
||||
<p>Эта страница применяет `database/schema.sql` и `database/seed.sql`. Таблицы будут пересозданы.</p>
|
||||
|
||||
<div class="status-box">
|
||||
<span>Версия install.php:</span>
|
||||
<strong>2026-06-04-02</strong>
|
||||
</div>
|
||||
|
||||
<div class="status-box">
|
||||
<span>Файл:</span>
|
||||
<strong><?= htmlspecialchars(__FILE__, ENT_QUOTES, 'UTF-8') ?></strong>
|
||||
</div>
|
||||
|
||||
<?php if ($stats['ok'] ?? false): ?>
|
||||
<div class="status-box">
|
||||
<span>База:</span>
|
||||
<strong><?= htmlspecialchars((string) $stats['database'], ENT_QUOTES, 'UTF-8') ?></strong>
|
||||
</div>
|
||||
<div class="status-box">
|
||||
<span>Таблиц:</span>
|
||||
<strong><?= htmlspecialchars((string) $stats['tables_count'], ENT_QUOTES, 'UTF-8') ?></strong>
|
||||
</div>
|
||||
<div class="status-box">
|
||||
<span>Категорий:</span>
|
||||
<strong><?= htmlspecialchars((string) $stats['category_count'], ENT_QUOTES, 'UTF-8') ?></strong>
|
||||
</div>
|
||||
<?php if (!empty($stats['first_categories'])): ?>
|
||||
<div class="status-box">
|
||||
<span>Верхние категории:</span>
|
||||
<strong><?= htmlspecialchars(implode(', ', $stats['first_categories']), ENT_QUOTES, 'UTF-8') ?></strong>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<div class="status-box danger"><?= htmlspecialchars((string) ($stats['error'] ?? 'Нет статистики'), ENT_QUOTES, 'UTF-8') ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!$isLocal): ?>
|
||||
<div class="status-box danger">Установка доступна только при APP_ENV=local.</div>
|
||||
<?php elseif (!$canRun): ?>
|
||||
|
||||
Reference in New Issue
Block a user