Add BackPRO News theme and update database schema for article tracking

- Introduced a new WordPress theme "BackPRO News" with a lightweight magazine-style design.
- Added columns for tracking retry attempts and timestamps for unpublished/generated articles in the articles table.
- Included remote service metadata fields in the sites table for better management.
- Created log files for image replacements, installer actions, OpenAI article generation, and publishing processes.
- Implemented a dashboard template for site management, including permalink settings and theme installation options.
This commit is contained in:
2026-02-17 20:08:02 +01:00
parent b653cea252
commit 4d5e220b3c
41 changed files with 4229 additions and 239 deletions

View File

@@ -5,9 +5,11 @@ namespace App\Controllers;
use App\Core\Auth;
use App\Core\Controller;
use App\Helpers\Validator;
use App\Models\Article;
use App\Models\Site;
use App\Models\Topic;
use App\Models\GlobalTopic;
use App\Services\InstallerService;
use App\Services\WordPressService;
class SiteController extends Controller
@@ -21,6 +23,13 @@ class SiteController extends Controller
// Attach topic count for each site
foreach ($sites as &$site) {
$site['topic_count'] = Topic::count('site_id = :sid', ['sid' => $site['id']]);
$site['published_article_count'] = Article::count(
'site_id = :sid AND status = :status',
[
'sid' => $site['id'],
'status' => 'published',
]
);
}
$this->view('sites/index', ['sites' => $sites]);
@@ -175,4 +184,130 @@ class SiteController extends Controller
$this->json($result);
}
public function dashboard(string $id): void
{
Auth::requireLogin();
$site = Site::find((int) $id);
if (!$site) {
$this->flash('danger', 'Strona nie znaleziona.');
$this->redirect('/sites');
return;
}
$wp = new WordPressService();
$permalinkStatus = $wp->getPermalinkSettings($site);
$remoteServiceStatus = $wp->getRemoteServiceStatus($site);
$this->view('sites/dashboard', [
'site' => $site,
'permalinkStatus' => $permalinkStatus,
'remoteServiceStatus' => $remoteServiceStatus,
]);
}
public function enablePrettyPermalinks(string $id): void
{
Auth::requireLogin();
$site = Site::find((int) $id);
if (!$site) {
$this->flash('danger', 'Strona nie znaleziona.');
$this->redirect('/sites');
return;
}
$wp = new WordPressService();
$result = $wp->enablePrettyPermalinks($site);
if (!empty($result['success'])) {
$this->flash('success', (string) ($result['message'] ?? 'Zaktualizowano strukture linkow permanentnych.'));
} else {
$this->flash('danger', (string) ($result['message'] ?? 'Nie udalo sie zaktualizowac linkow permanentnych.'));
}
$this->redirect("/sites/{$id}/dashboard");
}
public function updateRemoteService(string $id): void
{
Auth::requireLogin();
$site = Site::find((int) $id);
if (!$site) {
$this->flash('danger', 'Strona nie znaleziona.');
$this->redirect('/sites');
return;
}
$wp = new WordPressService();
$result = $wp->installBackproRemoteService($site);
$status = $wp->getRemoteServiceStatus($site);
if (!empty($result['success'])) {
$this->flash(
'success',
'Zaktualizowano plik serwisowy BackPRO. Lokalna: '
. ($status['local_version'] ?? '-')
. ', na serwerze: '
. ($status['remote_version'] ?? '-')
);
} else {
$this->flash(
'danger',
(string) ($result['message'] ?? 'Nie udalo sie zaktualizowac pliku serwisowego.')
);
}
$this->redirect("/sites/{$id}/dashboard");
}
public function installBackproNewsTheme(string $id): void
{
Auth::requireLogin();
$site = Site::find((int) $id);
if (!$site) {
$this->flash('danger', 'Strona nie znaleziona.');
$this->redirect('/sites');
return;
}
$wp = new WordPressService();
$result = $wp->installBackproNewsTheme($site);
if (!empty($result['success'])) {
$this->flash('success', (string) ($result['message'] ?? 'Zainstalowano motyw BackPRO News.'));
} else {
$this->flash('danger', (string) ($result['message'] ?? 'Nie udalo sie zainstalowac motywu.'));
}
$this->redirect("/sites/{$id}/dashboard");
}
public function reinstallWordPress(string $id): void
{
Auth::requireLogin();
$site = Site::find((int) $id);
if (!$site) {
$this->json(['success' => false, 'message' => 'Strona nie znaleziona.'], 404);
return;
}
$progressId = (string) $this->input('progress_id', '');
if ($progressId === '' || !preg_match('/^[a-zA-Z0-9]{10,30}$/', $progressId)) {
$this->json(['success' => false, 'message' => 'Nieprawidlowy identyfikator postepu.'], 422);
return;
}
$republish = (bool) ((int) $this->input('republish_articles', 1));
$installer = new InstallerService();
$result = $installer->reinstallSite($site, $republish, $progressId);
InstallerService::cleanupProgress($progressId);
$this->json($result, !empty($result['success']) ? 200 : 500);
}
}