| 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_admin_role();
$webroot=dirname(__DIR__);
$backupRoot=$webroot.'/storage/v11-backups';
$error='';$result='';
function p11_patch_functions(string $s): string {
if(str_contains($s,'POLANA_V11_LANG_INSTALL'))return $s;
$needle='declare(strict_types=1);';
if(substr_count($s,$needle)!==1)throw new RuntimeException('Nie można rozpoznać początku includes/functions.php');
$s=str_replace($needle,$needle."\n/* POLANA_V11_LANG_INSTALL */\nrequire_once __DIR__.'/polana_v11_lang.php';",$s);
$headStart=strpos($s,'function render_public_head(');
$headEnd=strpos($s,'function render_public_header(',$headStart===false?0:$headStart);
if($headStart===false||$headEnd===false)throw new RuntimeException('Nie znaleziono publicznego nagłówka strony.');
$head=substr($s,$headStart,$headEnd-$headStart);
$replacement=<<<'CODE'
$v11CurrentLang = p11_lang();
$canonical = site_url(p11_path($canonicalPath,$v11CurrentLang));
if ($v11CurrentLang !== 'pl') {
$v11Meta=p11_meta($canonicalPath,$v11CurrentLang);
if ($v11Meta) { $title=$v11Meta['title']; $description=$v11Meta['description']; }
if (!p11_page_ready($canonicalPath,$v11CurrentLang)) $robots = 'noindex,follow';
}
CODE;
$pattern='~\$canonical\s*=\s*site_url\([^;\n]*\);~';
if(preg_match_all($pattern,$head)!==1)throw new RuntimeException('Nie rozpoznano pojedynczego canonical w publicznym nagłówku PHP.');
$head=preg_replace_callback($pattern,static fn($m)=>$replacement,$head,1);
if(str_contains($head,'<html lang="pl">')) {
$head=str_replace('<html lang="pl">','<html lang="<?= e(p11_lang()) ?>">',$head);
} elseif(!preg_match('~<html\s+lang=~',$head)) {
throw new RuntimeException('Nie znaleziono znacznika HTML lang w publicznym nagłówku.');
}
$needle='<link rel="canonical" href="<?= e($canonical) ?>">';
if(!str_contains($head,$needle))throw new RuntimeException('Nie rozpoznano canonical link w publicznym nagłówku');
if(!str_contains($head,'p11_hreflang(')){
$head=str_replace($needle,$needle."\n <?php foreach(p11_hreflang(\$canonicalPath) as \$v11Code=>\$v11Url): ?><link rel=\"alternate\" hreflang=\"<?= e(\$v11Code) ?>\" href=\"<?= e(\$v11Url) ?>\"><?php endforeach; ?>",$head);
}
$s=substr($s,0,$headStart).$head.substr($s,$headEnd);
$needle="<link rel=\"stylesheet\" href=\"<?= e(asset_v('css/polana-heritage.css')) ?>\">";
if(!str_contains($s,$needle))throw new RuntimeException('Nie znaleziono bazowego CSS w publicznym nagłówku.');
$s=str_replace($needle,$needle . "\n <link rel=\"stylesheet\" href=\"/assets/css/polana-v11-flags.css?v=11\">",$s);
$from=strpos($s,'id="main-nav"');
if($from===false)throw new RuntimeException('Brak menu nawigacji main-nav');
$end=strpos($s,'</nav>',$from);
if($end===false)throw new RuntimeException('Brak końca nawigacji main-nav');
$s=substr_replace($s," <?php p11_render_switcher(); ?>\n ",$end,0);
// Main nav/footer links are server-rendered in the chosen language for SEO.
$headerStart=strpos($s,'function render_public_header(');
$adminStart=strpos($s,'function render_admin_header(',$headerStart===false?0:$headerStart);
if($headerStart===false||$adminStart===false)throw new RuntimeException('Nie rozpoznano sekcji publicznych nawigacji.');
$section=substr($s,$headerStart,$adminStart-$headerStart);
foreach(['/','/andrzej-polan','/menu','/rezerwacja','/galeria','/blog','/wspolpraca','/kontakt','/alergeny','/polityka-prywatnosci'] as $url){
$section=str_replace('href="'.$url.'"','href="<?= e(p11_path(\''.$url.'\',p11_lang())) ?>"',$section);
}
$needle='<!-- POLANA_HERITAGE_JS_V2 -->';
if(!str_contains($section,$needle))throw new RuntimeException('Nie znaleziono końca publicznego szablonu JS.');
$section=str_replace($needle,'<script src="/assets/js/polana-v11-links.js?v=11" defer></script>'."\n".$needle,$section);
$s=substr($s,0,$headerStart).$section.substr($s,$adminStart);
return $s;
}
function p11_patch_htaccess(string $s): string {
if(str_contains($s,'POLANA_V11_DE_ES_ROUTES'))return $s;
$needle='RewriteEngine On';
if(substr_count($s,$needle)!==1)throw new RuntimeException('Nie rozpoznano RewriteEngine w .htaccess');
$rules=<<<'RULES'
# POLANA_V11_DE_ES_ROUTES — static aliases follow established EN patterns
RewriteRule ^(de|es)/?$ index.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/menu/?$ menu.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/menu-seo/?$ menu-seo.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/menu-druk/?$ menu-druk.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/menu-karta\.svg$ menu-karta.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/chef/?$ andrzej-polan.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/contact/?$ kontakt.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/reservation/?$ rezerwacja.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/privacy/?$ polityka-prywatnosci.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/allergens/?$ alergeny.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/gallery/?$ galeria.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/blog/([a-z0-9-]+)/?$ blog-post.php?slug=$2&lang=$1 [L,QSA]
RewriteRule ^(de|es)/blog/?$ blog.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/cooperation/?$ wspolpraca.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/newsletter/?$ newsletter.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/reviews/?$ opinie.php?lang=$1 [L,QSA]
RewriteRule ^(de|es)/review/?$ opinia.php?lang=$1 [L,QSA]
# END POLANA_V11_DE_ES_ROUTES
RULES;
return str_replace($needle,$needle.$rules,$s);
}
function p11_patch_sitemap(string $s): string {
if(str_contains($s,'POLANA_V11_SITEMAP_READY'))return $s;
$start=strpos($s,'$urls=[];');
$end=strpos($s,"echo '<?xml",$start===false?0:$start);
if($start===false||$end===false||$end<=$start)throw new RuntimeException('Nie rozpoznano generatora sitemap.xml');
$replacement=<<<'CODE'
/* POLANA_V11_SITEMAP_READY: expose only languages with verified content. */
$urls=[];
foreach ($pages as $page) {
$path=$page['path'];
$urlsByLang=['pl'=>site_url(p11_path($path,'pl'))];
foreach(['en','de','es'] as $lang){
if(p11_page_ready($path,$lang))$urlsByLang[$lang]=site_url(p11_path($path,$lang));
}
foreach($urlsByLang as $lang=>$url){
$urls[]=['loc'=>$url,'alternates'=>$urlsByLang,'lastmod'=>$page['lastmod']??null,
'priority'=>$page['priority'],'changefreq'=>$page['freq']];
}
}
CODE;
return substr($s,0,$start).$replacement.substr($s,$end);
}
if($_SERVER['REQUEST_METHOD']==='POST'){
verify_csrf();
try {
$action=(string)($_POST['action']??'');
if(!in_array($action,['install','rollback'],true))throw new RuntimeException('Nieznana operacja');
$manifest=$backupRoot.'/latest.json';
if($action==='rollback'){
if(!is_file($manifest))throw new RuntimeException('Brak manifestu kopii V11');
$data=json_decode((string)file_get_contents($manifest),true,512,JSON_THROW_ON_ERROR);
foreach($data['backups'] as $entry){
if(!is_file($entry['backup']))throw new RuntimeException('Brak pliku backupu: '.basename($entry['backup']));
}
foreach($data['backups'] as $entry){
if(file_put_contents($entry['target'],file_get_contents($entry['backup']),LOCK_EX)===false)throw new RuntimeException('Nie udało się przywrócić '.$entry['target']);
}
unlink($manifest);$result='Przywrócono poprzednie wersje functions.php, sitemap.php i .htaccess. Nowe pliki V11 możesz zostawić — będą nieaktywne.';
}else{
if(is_file($manifest))throw new RuntimeException('V11 ma aktywną kopię instalacji. Najpierw użyj rollback lub usuń zgodnie z instrukcją.');
$targets=[
$webroot.'/includes/functions.php'=>'p11_patch_functions',
$webroot.'/.htaccess'=>'p11_patch_htaccess',
$webroot.'/sitemap.php'=>'p11_patch_sitemap'
];
$planned=[];
foreach($targets as $path=>$fn){
if(!is_file($path)||!is_readable($path)||!is_writable($path))throw new RuntimeException('Brak uprawnień do: '.basename($path));
$original=file_get_contents($path);
if($original===false)throw new RuntimeException('Odczyt nieudany: '.$path);
$modified=$fn($original);
if($original===$modified)throw new RuntimeException('Patch już jest aktywny: '.basename($path));
$planned[]=['target'=>$path,'original'=>$original,'modified'=>$modified];
}
if(!is_dir($backupRoot)&&!mkdir($backupRoot,0700,true))throw new RuntimeException('Nie można utworzyć katalogu kopii');
file_put_contents($backupRoot.'/.htaccess',"Require all denied\n",LOCK_EX);
$stamp=date('Ymd_His');$copyDir=$backupRoot.'/v11_'.$stamp;
if(!mkdir($copyDir,0700))throw new RuntimeException('Nie można utworzyć katalogu kopii V11');
$entries=[];
foreach($planned as $index=>$entry){
$back=$copyDir.'/'.$index.'_'.basename($entry['target']).'.bak';
if(file_put_contents($back,$entry['original'],LOCK_EX)===false)throw new RuntimeException('Nie udało się zapisać backupu');
$entries[]=['target'=>$entry['target'],'backup'=>$back];
}
$written=[];
try{
foreach($planned as $entry){
if(file_put_contents($entry['target'],$entry['modified'],LOCK_EX)===false)throw new RuntimeException('Błąd zapisu: '.$entry['target']);
$written[]=$entry['target'];
}
file_put_contents($manifest,json_encode(['backups'=>$entries],JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES),LOCK_EX);
}catch(Throwable $e){
foreach($entries as $entry)if(in_array($entry['target'],$written,true))@copy($entry['backup'],$entry['target']);
throw $e;
}
admin_log('polana_v11_install','Dodano flagi, trasy DE/ES i kontrolę hreflang');
$result='Instalacja V11 zakończona. Sprawdź /en/, /de/, /es/, /sitemap.xml i przyciski flag.';
}
}catch(Throwable $e){$error=$e->getMessage();error_log('P11 INSTALL: '.$error);}
}
render_admin_header('V11 — instalacja flag i SEO');
?>
<div style="max-width:850px;margin:22px auto;padding:20px;background:#fff;border:1px solid #ddd;border-radius:16px">
<h1>POLANA V11 — instalator języków</h1>
<p>Uruchom po wgraniu katalogów <code>admin/</code>, <code>includes/</code>, <code>assets/</code>. Modyfikuje tylko <code>includes/functions.php</code>, <code>.htaccess</code> i <code>sitemap.php</code>; robi kopie i umożliwia wycofanie.</p>
<?php if($error): ?><p style="color:#b22"><b>Błąd:</b> <?= e($error) ?></p><?php endif; ?>
<?php if($result): ?><p style="color:#176a2c"><b><?= e($result) ?></b></p><?php endif; ?>
<form method="post" style="margin:15px 0"><?= csrf_field() ?><button class="btn btn-primary" name="action" value="install" onclick="return confirm('Wykonać backup i wpiąć V11 do publicznej strony?')">Zainstaluj V11</button></form>
<form method="post" style="margin:15px 0"><?= csrf_field() ?><button class="btn btn-light" name="action" value="rollback" onclick="return confirm('Przywrócić 3 pliki z backupu sprzed V11?')">Rollback V11</button></form>
<p>Po poprawnym teście usuń plik <code>admin/polana-v11-instalator.php</code> z serwera; kopie zostają w chronionym katalogu <code>storage/v11-backups/</code>.</p>
<p><a href="/admin/polana-v11-podstrony.php">Kontrola podstron i SEO →</a> · <a href="/admin/polana-v11-harmonogram.php">Losowy harmonogram bloga →</a></p>
</div>
<?php render_admin_footer(); ?>