| Server IP : 188.114.96.3 / Your IP : 216.73.216.143 Web Server : Apache System : Linux sv058.home.net.pl 6.8.2 husak_dirty_pages_fix #1 SMP PREEMPT_DYNAMIC Tue Apr 2 22:06:51 CEST 2024 x86_64 User : ( 3194769) PHP Version : 8.5.12 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /polana/admin/ |
Upload File : |
<?php
declare(strict_types=1);
require_once dirname(__DIR__).'/includes/functions.php';
require_blog_manager();
$root=dirname(__DIR__);
$backupDir=$root.'/storage/polana_blog_v10_backup';
$targets=['editor'=>$root.'/admin/blog-edit.php','links'=>$root.'/blog-post.php'];
function pbi_safe_backup(string $file,string $backupDir): void {
if(!is_dir($backupDir)&&!mkdir($backupDir,0700,true)&&!is_dir($backupDir))throw new RuntimeException('Nie mogę utworzyć katalogu kopii.');
file_put_contents($backupDir.'/.htaccess',"Require all denied\nDeny from all\n");
$dest=$backupDir.'/'.basename($file).'.original';
if(!is_file($dest)&&!copy($file,$dest))throw new RuntimeException('Nie mogę zrobić kopii: '.basename($file));
}
function pbi_patch(string $key,string $root,string $backupDir): string {
$file=$key==='editor'?$root.'/admin/blog-edit.php':$root.'/blog-post.php';
if(!is_file($file)||!is_readable($file)||!is_writable($file))throw new RuntimeException('Plik wymaga praw zapisu: '.basename($file));
$s=file_get_contents($file);if(!is_string($s))throw new RuntimeException('Nie można odczytać pliku.');
$marker=$key==='editor'?'V10_BLOG_AUTO_QUEUE':'V10_BLOG_INTERNAL_LINKS';
if(str_contains($s,$marker))return 'Moduł '.$key.' jest już podłączony.';
if($key==='editor'){
if(str_contains($s,'v9_enqueue_blog_post('))return 'Edytor już dodaje zadania tłumaczenia V9 — bez zmian.';
$anchor=" redirect('/admin/blog-edit.php?id='.$id);";
$replacement=<<<'PATCH'
// V10_BLOG_AUTO_QUEUE — dodanie do kolejki po udanym zapisie, bez blokowania edytora
try {
$module=dirname(__DIR__) . '/includes/tklm_v9.php';
if (is_file($module)) {
require_once $module;
v9_init();
v9_enqueue_blog_post((int)$id);
}
} catch (Throwable $translateError) {
error_log('Polana blog translation enqueue: '.$translateError->getMessage());
}
PATCH;
if(substr_count($s,$anchor)!==1)throw new RuntimeException('Nieznana wersja edytora. Przerwano bez zmian.');
$s=str_replace($anchor,$replacement."\n".$anchor,$s);
}else{
$anchor='<div class="blog-back"><a href="/blog">';
$replacement=<<<'PATCH'
<?php /* V10_BLOG_INTERNAL_LINKS */
$v10Lang=function_exists('polana_lang')?polana_lang():'pl';
$v10Copy=[
'pl'=>['menu'=>'Zobacz aktualne menu','reserve'=>'Rezerwacja stolika'],
'en'=>['menu'=>'Explore our menu','reserve'=>'Book a table'],
'de'=>['menu'=>'Speisekarte ansehen','reserve'=>'Tisch reservieren'],
'es'=>['menu'=>'Ver la carta','reserve'=>'Reservar mesa'],
][$v10Lang]??['menu'=>'Zobacz menu','reserve'=>'Rezerwacja'];
$v10Menu=function_exists('polana_local_path')?polana_local_path('/menu',$v10Lang):'/menu';
$v10Reserve=function_exists('polana_local_path')?polana_local_path('/rezerwacja',$v10Lang):'/rezerwacja';
?>
<nav aria-label="Menu i rezerwacje" style="margin:30px 0;display:flex;gap:12px;flex-wrap:wrap">
<a class="btn btn-green" href="<?= e($v10Menu) ?>"><?= e($v10Copy['menu']) ?></a>
<a class="btn btn-light" href="<?= e($v10Reserve) ?>"><?= e($v10Copy['reserve']) ?></a>
</nav>
PATCH;
if(substr_count($s,$anchor)!==1)throw new RuntimeException('Nieznany szablon artykułu. Przerwano bez zmian.');
$s=str_replace($anchor,$replacement."\n ".$anchor,$s);
}
pbi_safe_backup($file,$backupDir);
$temp=$file.'.v10-new';
if(file_put_contents($temp,$s,LOCK_EX)===false)throw new RuntimeException('Nie mogę zapisać zmodyfikowanego pliku.');
@chmod($temp,fileperms($file)&0777);
if(!rename($temp,$file)){@unlink($temp);throw new RuntimeException('Nie udało się podmienić pliku.');}
return 'Zintegrowano: '.basename($file);
}
$message='';$error='';
if($_SERVER['REQUEST_METHOD']==='POST'){
verify_csrf();
try{
$action=(string)($_POST['action']??'');
$target=(string)($_POST['target']??'');
if(!in_array($target,['editor','links'],true))throw new RuntimeException('Nieprawidłowy cel.');
if($action==='install')$message=pbi_patch($target,$root,$backupDir);
elseif($action==='rollback'){
$file=$targets[$target];$back=$backupDir.'/'.basename($file).'.original';
if(!is_file($back))throw new RuntimeException('Brak kopii do przywrócenia.');
if(!copy($back,$file))throw new RuntimeException('Nie można odtworzyć pliku.');
$message='Przywrócono wcześniejszą wersję '.basename($file);
}else throw new RuntimeException('Nieznana operacja.');
}catch(Throwable $e){$error=$e->getMessage();}
}
render_admin_header('Polana Blog — integracja V10');
?>
<main style="max-width:900px;margin:24px auto;padding:18px"><h1>Blog V10 — integracja bez nadpisywania całego serwisu</h1>
<p>Łączy istniejący edytor z kolejką tłumaczeń V9 i dodaje linki Menu / Rezerwacja do wpisów. Przed każdą zmianą kopiuje oryginalny plik. Nie ingeruje w bazę ani prywatne klucze.</p>
<?php if($message): ?><p style="padding:12px;background:#e8f7e8"><?= e($message) ?></p><?php endif; ?>
<?php if($error): ?><p style="padding:12px;background:#ffe8e8"><?= e($error) ?></p><?php endif; ?>
<?php foreach(['editor'=>['Edytor: automatyczna kolejka tłumaczeń po zapisie','blog-edit.php'],'links'=>['Artykuły: linki do menu i rezerwacji','blog-post.php']] as $key=>$info): ?>
<section style="border:1px solid #ddd;padding:18px;margin:12px 0;border-radius:12px"><h2><?= e($info[0]) ?></h2>
<p>Plik: <?= e($info[1]) ?>. Weryfikacja struktury przed wprowadzeniem zmian; jeśli wzorzec nie pasuje, nic nie będzie zapisane.</p>
<form method="post" style="display:flex;gap:14px;flex-wrap:wrap"><?= csrf_field() ?>
<input type="hidden" name="target" value="<?= e($key) ?>">
<button type="submit" name="action" value="install">Zainstaluj</button>
<button type="submit" name="action" value="rollback" onclick="return confirm('Przywrócić oryginalny plik i utracić inne zmiany wprowadzone od instalacji?')">Rollback</button>
</form></section>
<?php endforeach; ?>
<p><b>Po instalacji i testach usuń ten instalator z serwera.</b> Kopie znajdują się w chronionym katalogu storage.</p>
<p><a href="/admin/polana-blog-40.php">← Przejdź do importu 40 wpisów</a></p></main>
<?php render_admin_footer(); ?>