Site Builder
Editing:
links.php
writable 0666
<?php /************************************************************************** * SOCIAL – LINKS EDITOR * ---------------------------------------------------------------------- * © 2025 BestDealOn – feel free to modify. * Requires PHP 8.1+ *************************************************************************/ /* ---------- locate the slug no matter how we were reached ------------- */ $slug = $_GET['user'] ?? ''; if ($slug===''){ if (isset($_SERVER['PATH_INFO'])) $slug = trim($_SERVER['PATH_INFO'],'/'); elseif (preg_match('~/links\.php/([^/?]+)~', $_SERVER['REQUEST_URI'],$m)) $slug=$m[1]; else $slug = basename(dirname(__FILE__)); // if copied into /social/<slug>/ } $slug = preg_replace('/[^a-z0-9_]/i','', $slug); $root = $_SERVER['DOCUMENT_ROOT']; $dir = "$root/social/$slug"; $file = "$dir/links.json"; if ($slug && !is_dir($dir)) $slug=''; // invalid slug path /* ---------- show lookup screen when no slug ---------------------------- */ function lookup($err=''){ ?><!DOCTYPE html><html><head><meta charset="utf-8"><title>Edit Links</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <style> body{font-family:system-ui,Arial,sans-serif;background:#f5f8fb;margin:0;color:#234} .wrap{max-width:480px;margin:3em auto;background:#fff;padding:2em;border-radius:18px; box-shadow:0 2px 18px #dde3fa55;text-align:center} h1{font-size:1.5em;margin-bottom:.9em} input{width:100%;padding:.7em;border:1.4px solid #b7c2df;border-radius:7px;font-size:1.05em} button{margin-top:1em;padding:.7em 1.6em;font-size:1.05em;background:#2357d7;color:#fff; font-weight:700;border:none;border-radius:8px;cursor:pointer} .err{color:#c00;margin-bottom:.8em} </style></head><body> <div class="wrap"> <h1>Look up Your Profile</h1> <?php if($err) echo "<div class='err'>$err</div>"; ?> <form method="get"> <input type="text" name="user" placeholder="@username" required> <button type="submit">Load Links</button> </form> </div></body></html><?php exit; } if ($slug==='') lookup(); /* ---------- load existing links (array) -------------------------------- */ $links = is_file($file) ? json_decode(file_get_contents($file), true, 512, JSON_THROW_ON_ERROR) : []; if (!is_array($links)) $links=[]; /* ---------- AJAX endpoints --------------------------------------------- */ if ($_SERVER['REQUEST_METHOD']==='POST'){ $raw = file_get_contents('php://input'); $arr = json_decode($raw,true); if (!is_array($arr)){ http_response_code(400); exit('Bad JSON'); } file_put_contents($file, json_encode($arr, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOCK_EX); echo '{"success":true}'; exit; } /* ---------- page ------------------------------------------------------- */ ?> <!doctype html><html lang="en"><head> <meta charset="utf-8"><title>Edit Links – @<?= htmlspecialchars($slug) ?></title> <meta name="viewport" content="width=device-width,initial-scale=1"> <style> :root{--bg:#f6f8fb;--fg:#234;--accent:#2357d7;--accent-dk:#1347c0;--warn:#c6262e} body{margin:0;font-family:system-ui,Arial,sans-serif;background:var(--bg);color:var(--fg)} .top{background:#eee;padding:.8em 1.2em;font-weight:900} h1{font-size:1.45rem;margin:0} .container{max-width:800px;margin:2rem auto;padding:0 1rem} button{cursor:pointer;border:none;font-weight:700;border-radius:8px} #list{list-style:none;padding:0;margin:0} .item{background:#fffbe6;border:2px solid #ffd973;padding:1rem;border-radius:12px; box-shadow:0 2px 12px #f5db9c40;margin-bottom:1rem;display:flex;flex-direction:column;gap:.5rem} .item.dragging{opacity:.55} .item input,.item textarea{width:100%;padding:.5em;border:1px solid #b7c2df;border-radius:6px;font-size:1rem} .row-btns{display:flex;gap:.6rem;margin-top:.3rem} .move{background:#aac8ff;color:#103e9d;padding:.4rem .7rem} .del{background:#ffd5d5;color:var(--warn);padding:.4rem .7rem} .add{background:var(--accent);color:#fff;padding:.55rem 1.2rem;font-size:1rem} .save{background:#ef8f13;color:#fff;padding:.6rem 1.6rem;font-size:1.05rem} #msg{margin-top:1rem;font-weight:600} </style> </head> <script src="/geo/geofence-guard.js" defer></script> <body> <div class="top"><a href="/" style="text-decoration:none;color:#2a3ca5">BestDealOn</a> » Edit Links</div> <div class="container"> <h1>Links for @<?= htmlspecialchars($slug) ?></h1> <ul id="list"></ul> <button id="addBtn" class="add">+ Add Link</button> <div style="margin-top:2rem;text-align:right"> <button id="saveBtn" class="save">Save Links</button> </div> <div id="msg"></div> </div> <script> /* ---------- initial data from PHP --------- */ const links = <?= json_encode($links, JSON_UNESCAPED_SLASHES) ?>; const list = document.getElementById('list'); /* ---------- helpers ----------------------- */ function makeItem(obj={title:'',url:'',excerpt:''}){ const li=document.createElement('li'); li.className='item'; li.draggable=true; li.innerHTML=` <input class="title" placeholder="Title" value="${escapeHtml(obj.title||'')}"> <input class="url" placeholder="https://example.com" value="${escapeHtml(obj.url||'')}"> <textarea class="ex" rows="2" placeholder="Short excerpt…">${escapeHtml(obj.excerpt||'')}</textarea> <div class="row-btns"> <button class="move up">↑</button> <button class="move down">↓</button> <button class="del">✖</button> </div>`; return li; } function escapeHtml(s){return s.replace(/[&<>"']/g,m=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[m]));} /* ---------- render initial list ----------- */ links.forEach(o=>list.appendChild(makeItem(o))); if(!links.length) list.appendChild(makeItem()); /* ---------- drag & drop re‑order ---------- */ let dragEl; list.addEventListener('dragstart',e=>{dragEl=e.target; dragEl.classList.add('dragging');}); list.addEventListener('dragend', e=>{dragEl.classList.remove('dragging'); dragEl=null;}); list.addEventListener('dragover', e=>{ e.preventDefault(); const after = [...list.querySelectorAll('.item:not(.dragging)')] .find(li=>e.clientY<li.getBoundingClientRect().top+li.offsetHeight/2); list.insertBefore(dragEl, after||null); }); /* ---------- button events (add/up/down/del) */ document.getElementById('addBtn').onclick=()=>list.appendChild(makeItem()); list.addEventListener('click',e=>{ const li=e.target.closest('.item'); if(!li) return; if(e.target.classList.contains('del')) li.remove(); if(e.target.classList.contains('up')) li.previousElementSibling&&list.insertBefore(li,li.previousElementSibling); if(e.target.classList.contains('down'))li.nextElementSibling&&list.insertBefore(li.nextElementSibling,li); }); /* ---------- save -------------------------- */ document.getElementById('saveBtn').onclick=async()=>{ const arr=[...list.children].map(li=>({ title :li.querySelector('.title').value.trim(), url :li.querySelector('.url').value.trim(), excerpt:li.querySelector('.ex').value.trim() })).filter(x=>x.title&&x.url); const r=await fetch(location.href,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(arr)}); const msg=document.getElementById('msg'); msg.textContent= r.ok? 'Saved!' : 'Error saving'; msg.style.color = r.ok? 'green':'red'; setTimeout(()=>msg.textContent='',2000); }; /* ---------- tiny util --------------------- */ function escapeHtml(s){return s.replace(/[&<>"']/g,c=>({ '&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));} </script> </body></html>
Save changes
Create folder
writable 0777
Create
Cancel