<?php
/**
 * Public runtime injector.
 *
 * Loaded by every page as <script src="/inc/inject.php" defer></script>.
 * Reads the code saved from the admin panel and applies it to the page in
 * real time. Always served uncached so panel edits appear immediately.
 */

header('Content-Type: application/javascript; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('X-Robots-Tag: noindex, nofollow');

$fields = ['head' => '', 'body_top' => '', 'body_bottom' => '', 'css' => '', 'js' => ''];
$file = __DIR__ . '/data/inject.json';
if (is_file($file)) {
    $json = json_decode((string)@file_get_contents($file), true);
    if (is_array($json)) {
        foreach ($fields as $k => $v) {
            if (isset($json[$k]) && is_string($json[$k])) {
                $fields[$k] = $json[$k];
            }
        }
    }
}

$enc = function ($s) {
    return json_encode($s, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
};
?>
(function () {
  var HEAD = <?php echo $enc($fields['head']); ?>;
  var BODY_TOP = <?php echo $enc($fields['body_top']); ?>;
  var BODY_BOTTOM = <?php echo $enc($fields['body_bottom']); ?>;
  var CSS = <?php echo $enc($fields['css']); ?>;
  var JS = <?php echo $enc($fields['js']); ?>;

  function makeScript(node) {
    var s = document.createElement("script");
    var attrs = node.attributes || [];
    for (var i = 0; i < attrs.length; i++) {
      s.setAttribute(attrs[i].name, attrs[i].value);
    }
    s.text = node.textContent || "";
    (document.head || document.documentElement).appendChild(s);
  }

  function makeStyle(node) {
    var l = document.createElement("link");
    var attrs = node.attributes || [];
    for (var i = 0; i < attrs.length; i++) {
      l.setAttribute(attrs[i].name, attrs[i].value);
    }
    (document.head || document.documentElement).appendChild(l);
  }

  function inject(html, where) {
    if (!html) return;
    var tpl = document.createElement("template");
    tpl.innerHTML = html;
    var frag = document.createDocumentFragment();
    var nodes = [].slice.call(tpl.content.childNodes);
    for (var i = 0; i < nodes.length; i++) {
      var n = nodes[i];
      if (n.nodeName === "SCRIPT") {
        makeScript(n);
      } else if (n.nodeName === "LINK" && n.getAttribute("rel") === "stylesheet") {
        makeStyle(n);
      } else {
        frag.appendChild(n);
      }
    }
    if (where === "head") {
      document.head.appendChild(frag);
      return;
    }
    function place() {
      if (!document.body) return;
      if (where === "body_top") {
        document.body.insertBefore(frag, document.body.firstChild);
      } else {
        document.body.appendChild(frag);
      }
    }
    if (document.body) place();
    else document.addEventListener("DOMContentLoaded", place);
  }

  inject(HEAD, "head");

  if (CSS) {
    var style = document.createElement("style");
    style.setAttribute("data-jr-inject", "css");
    style.textContent = CSS;
    (document.head || document.documentElement).appendChild(style);
  }

  function runBody() {
    inject(BODY_TOP, "body_top");
    inject(BODY_BOTTOM, "body_bottom");
    if (JS) {
      var s = document.createElement("script");
      s.setAttribute("data-jr-inject", "js");
      s.text = JS;
      (document.head || document.documentElement).appendChild(s);
    }
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", runBody);
  } else {
    runBody();
  }

  window.__JR_INJECT__ = true;
})();
