view admajax.php @ 385:8b8b0a83233b

Add compo entry show position buttons to individual compos.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 05 Dec 2013 07:24:12 +0200
parents ea68c1b081b2
children 3257ae94ba1c
line wrap: on
line source

<?
//
// FAPWeb Simple Demoparty System
// Party administration page AJAX backend module
// (C) Copyright 2012-2013 Tecnic Software productions (TNSP)
//
$sessionType = "admin";
require_once "mconfig.inc.php";
require_once "msite.inc.php";
require_once "msession.inc.php";


function stValidateRequestCompoData($full)
{
  if (!stChkRequestItem("name", $fake,
      array(CHK_ISGT, VT_STR, 0, "Compo name too short"),
      array(CHK_LTEQ, VT_STR, SET_LEN_COMPO_NAME, "Compo name too long.")) ||
    !stChkRequestItem("description", $fake,
      array(CHK_ISGT, VT_STR, 10, "Compo description too short"),
      array(CHK_LTEQ, VT_STR, SET_LEN_COMPO_DESC, "Compo description too long.")))
    return FALSE;
  
  if (!$full)
    return TRUE;

  return
    stChkRequestItem("visible", $fake,
      array(CHK_TYPE, VT_BOOL, "Invalid data.")
    ) &&
    stChkRequestItem("voting", $fake,
      array(CHK_TYPE, VT_BOOL, "Invalid data.")
    ) &&
    stChkRequestItem("showAuthors", $fake,
      array(CHK_TYPE, VT_BOOL, "Invalid data.")
    );
}


function stValidateRequestEntryData(&$compo_id)
{
  return
    stChkRequestItem("name", $fake,
      array(CHK_ISGT, VT_STR, 0, "Entry name too short."),
      array(CHK_LTEQ, VT_STR, SET_LEN_ENTRY_NAME, "Entry name too long.")
    ) &&
    stChkRequestItem("author", $fake,
      array(CHK_ISGT, VT_STR, 0, "Author name not set."),
      array(CHK_LTEQ, VT_STR, SET_LEN_ENTRY_AUTHOR, "Entry author too long.")
    ) &&
    stChkRequestItem("filename", $fake,
      array(CHK_TYPE, VT_TEXT, "Invalid data."),
      array(CHK_LTEQ, VT_STR, SET_LEN_ENTRY_FILENAME, "Entry filename too long.")
    ) &&
    stChkRequestItem("info", $fake,
      array(CHK_TYPE, VT_TEXT, "Invalid data."),
      array(CHK_LTEQ, VT_STR, SET_LEN_ENTRY_INFO, "Entry info too long.")
    ) &&
    stChkRequestItem("compo_id", $compo_id,
      array(CHK_TYPE, VT_INT, "Invalid compo ID.")
    );
}


function stValidateRequestNewsData()
{
  return
    stChkRequestItem("text", $fake,
      array(CHK_ISGT, VT_STR, 0, "News text too short."),
      array(CHK_LTEQ, VT_STR, SET_LEN_NEWS_TEXT, "News text too long.")
    ) &&
    stChkRequestItem("author", $fake,
      array(CHK_ISGT, VT_STR, 0, "News author name too short."),
      array(CHK_LTEQ, VT_STR, SET_LEN_NEWS_AUTHOR, "News author name too long.")
    ) &&
    stChkRequestItem("title", $fake,
      array(CHK_ISGT, VT_STR, 0, "News title too short."),
      array(CHK_LTEQ, VT_STR, SET_LEN_NEWS_TITLE, "News title too long.")
    );
}


function stGetCompoData($id, $item, $prefix)
{
  return
    "  <h2>#".$id." - ".chentities($item["name"])."</h2>\n".
    "  ".stGetFormTextInput(40, SET_LEN_COMPO_NAME, "name", $id, $prefix, $item["name"])."\n".
    "  ".stGetFormCheckBoxInput("visible", $id, $prefix, $item["visible"], "Visible")."\n".
    "  ".stGetFormCheckBoxInput("showAuthors", $id, $prefix, $item["showAuthors"], "Show authors")."\n".
    "  ".stGetFormCheckBoxInput("voting", $id, $prefix, $item["voting"], "Enable voting")."<br />\n".
    "  ".stGetFormTextArea(5, 60, "description", $id, $prefix, $item["description"])."\n<br />\n".
    "  ".stGetFormButtonInput("update", $id, $prefix, "Update", "updateCompo(".$id.")")."\n";
}


function stGetNewsItemData($id, $item, $prefix)
{
  return
    "  <h2>".chentities($item["title"])."</h2>\n".
    "  ".stGetFormTextInput(40, SET_LEN_NEWS_TITLE, "title", $id, $prefix, $item["title"]).
    " - posted ".date("d M Y / H:i", $item["utime"])."<br />\n".
    "  ".stGetFormTextArea(5, 60, "text", $id, $prefix, $item["text"])."<br />\n".
    "  ".stGetFormTextInput(20, SET_LEN_NEWS_AUTHOR, "author",  $id, $prefix, $item["author"])."\n".
    "  ".stGetFormButtonInput("", "upd".$id, $prefix, "Update", "updateNews(".$id.")")."\n".
    "  ".stGetFormButtonInput("", "del".$id, $prefix, "Delete", "deleteNews(".$id.")")."\n";
}


function stGetEntryItemData($eid, $item, $prefix)
{
  return
    "   <td>".($item["show_id"] > 0 ? $item["show_id"] : "-")."</td>\n".
    "   <td>".stGetFormTextInput(20, SET_LEN_ENTRY_NAME, "name", $eid, $prefix, $item["name"])."</td>\n".
    "   <td>".stGetFormTextInput(15, SET_LEN_ENTRY_AUTHOR, "author", $eid, $prefix, $item["author"])."</td>\n".
    "   <td>".stGetFormTextInput(20, SET_LEN_ENTRY_FILENAME, "filename", $eid, $prefix, $item["filename"])."</td>\n".
    "   <td>".stGetFormTextArea(2, 30, "info", $eid, $prefix, $item["info"])."</td>\n".
    "   <td>".
    stGetFormButtonInput("delete", $eid, $prefix, "Del", "deleteEntry(".$item["compo_id"].",".$eid.")").
    stGetFormTextInput(3, 3, "compo_id", $eid, $prefix, $item["compo_id"]).
    stGetFormButtonInput("update", $eid, $prefix, "Upd", "updateEntry(".$item["compo_id"].",".$eid.")").
    "</td>\n";
}


function stGetVoteKeyClass($item)
{
  global $voteKeyMode;
  
  switch ($voteKeyMode)
  {
    case VOTE_FREELY:
      $cond = 0;
      break;

    case VOTE_ACTIVATE:
      $cond = $item["active"];
      break;

    case VOTE_ASSIGN:
      $cond = $item["key_id"] > 0;
      break;
  }

  return "votekey ".($cond ? "vkeyActive" : "vkeyInactive");
}


function stGetVoteKeyItemData($id, $item, $prefix)
{
  global $voteKeyMode, $voteKeyLen;

  switch ($voteKeyMode)
  {
    case VOTE_FREELY:
    case VOTE_ACTIVATE:
      $str = sprintf(
        "<span class=\"keyid\">%03d</span>&nbsp;:&nbsp;".
        "<span class=\"keycode\">%s</span>",
        $id,
        str_repeat("&nbsp;", $voteKeyLen - strlen($item["key"])).$item["key"]);

      if ($voteKeyMode == VOTE_ACTIVATE)
      {
        $str .= stGetFormCheckBoxInput("active", $id, $prefix, $item["active"], FALSE,
          "class=\"keyactive\" onClick=\"voteKeySetActive(".$id.")\"", "");
      }
      
      return $str;

    case VOTE_ASSIGN:
      $str =
        "  <td class=\"name\">".chentities($item["name"])."</td>\n".
        "  <td class=\"groups\">".chentities($item["groups"])."</td>\n".
        "  <td class=\"vkeynum\">".
          stGetFormTextInput(5, 5, "key_id", $id, $prefix, $item["key_id"]).
          stGetFormButtonInput("assign", $id, $prefix, "Set", "voteKeyAssign(".$id.",1)");

        if ($item["key_id"] != 0)
          $str .= stGetFormButtonInput("clear", $id, $prefix, "Clear", "voteKeyAssign(".$id.",0)");
        
      $str .=
        "</td>\n".
        "  <td class=\"vkey\">";

      if ($item["key_id"] > 0)
        $str .= sprintf("<span class=\"keyid\">%03d</span>".
          "&nbsp;:&nbsp;<span class=\"keycode\">%s</span>",
          $item["key_id"], chentities($item["key"]));

      $str .= "</td>\n";
      return $str;
  }
}


function stGetSaveButton()
{
  return "<input type=\"submit\" value=\" Save \" />\n";
}


function stGetOptionList($id, $sql, $iname, $active, $onChange = "")
{
  $str =
    "<select class=\"selectBox\" id=\"".$id."\" size=\"10\"".
    ($onChange != "" ? " onChange=\"".$onChange."\"" : "").">\n";

  if (($res = stExecSQL($sql)) !== false)
  {
    foreach ($res as $item)
    {
      $str .= "<option value=\"".$item["id"]."\"".
        ($active == $item["id"] ? " selected=\"selected\"" : "").
        ">".chentities($item[$iname])."</option>\n";
    }
  }

  return $str."</select>\n";
}


function stGetShowModeButton($mode, $name, $cmode)
{
  return stGetFormRadioButtonInput(
    "showMode", "", "", $mode,
    $cmode == $mode,
    $name,
    "onClick=\"setDisplayVar('showMode',".$mode.")\"");
}


function stRandomizeCompoShowOrder($compo_id, $patch)
{
  $entries = stExecSQL("SELECT id,show_id FROM entries WHERE compo_id=".$compo_id);
  if ($entries !== FALSE)
  {
    $ncount = stFetchSQLColumn("SELECT COUNT(*) FROM entries WHERE compo_id=".$compo_id." AND show_id<>0");
    $final = array();

    if ($patch && $ncount > 0)
    {
      $index = -1;
      foreach ($entries as $entry)
      {
        if ($entry["show_id"] == 0)
          $final[] = $entry["id"];

        if ($entry["show_id"] > $index)
          $index = $entry["show_id"];
      }

      $index++;
    }
    else
    {
      foreach ($entries as $entry)
        $final[] = $entry["id"];

      shuffle($final);
      $index = 1;
    }

    foreach ($final as $entry)
    {
      $sql = stPrepareSQL("UPDATE entries SET show_id=%d WHERE id=%d", $index, $entry);
      if (stExecSQL($sql) === false)
      {
        stError("Error updating entry show positions.");
        break;
      }
      $index++;
    }
  }
}


//
// Check if we are allowed to execute
//
if (!stCheckHTTPS() || !stAdmSessionAuth() || !stCSRFCheck())
{
  stSetupCacheControl();

  stSessionEnd(SESS_ADMIN);

  header("Location: ".stGetSetting("defaultPage"));
  exit;
}


//
// Initialize
//
stSetupCacheControl();

if (!stConnectSQLDB())
  die("Could not connect to SQL database.");

stReloadSettings();
stReloadDisplayVars();


$voteKeyMode = stGetSetting("voteKeyMode");
$voteKeyLen = stGetSetting("userKeyLength");
$type = stGetRequestItem("type", "");
switch (stGetRequestItem("action", ""))
{
  case "randomize":
    //
    // Randomize entries display order
    //
    $patch = intval(stGetRequestItem("patch", 1));
    if ($type == "all")
    {
      if (($compos = stExecSQL("SELECT id FROM compos")) === FALSE)
        stError("Eh? SQL error occured.");
      else
      foreach ($compos as $compo)
        stRandomizeCompoShowOrder($compo["id"], $patch);
    }
    else
    if ($type == "compo")
    {
      if (stChkRequestItem("id", $compo_id, array(CHK_TYPE, VT_INT, "Invalid data.")))
        stRandomizeCompoShowOrder($compo_id, $patch);
    }
    break;

  case "check":
    //
    // Perform systems check
    //
    $errors = 0;
    echo
      "<h1>Competitions / voting</h1>\n".
      "<ul>\n";
    
    echo "<li>".(stGetSetting("allowVoting") ? "Voting <b>IS ENABLED</b>." : "Voting is NOT enabled!")."</li>\n";

    if (($compos = stExecSQL("SELECT * FROM compos")) === FALSE)
      stError("Eh? SQL error occured.");
    else
    {
      foreach ($compos as $compo)
      {
        $nentries = stFetchSQLColumn("SELECT COUNT(*) FROM entries WHERE show_id=0 AND compo_id=".$compo["id"]);
        if ($nentries > 0)
        {
          echo "<li>Compo <b>#".$compo["id"]." - ".$compo["name"]."</b> has NO show order set for some entries.</li>\n";
          $errors++;
        }
      }
    }
    
    $nenabled = stFetchSQLColumn("SELECT COUNT(*) FROM compos WHERE visible<>0 AND voting<>0");
    if ($nenabled == 0)
      echo "<li>No competitions that are visible and enabled for voting.</li>\n";

    $nenabled = stFetchSQLColumn("SELECT COUNT(*) FROM compos WHERE visible=0 AND voting<>0");
    if ($nenabled > 0)
      echo "<li>".$nenabled." competitions that are NOT visible, but are enabled for voting?</li>\n";

    $entries = stFetchSQL("SELECT COUNT(*) AS nentries, COUNT(DISTINCT compo_id) AS ncompos FROM entries");
    if ($entries !== FALSE)
      echo "<li><b>".$entries["nentries"]."</b> compo entries in system in <b>".$entries["ncompos"]."</b> compos.</li>\n";
    
    if ($errors == 0)
      echo "<li>No errors/warnings detected.</li>\n";

    echo "</ul>\n";
    
    break;

  case "get":
    //
    // Get specific data
    //
    switch ($type)
    {
      case "infosys":
        $showMode = stGetDisplayVar("showMode");
        echo
          "<div id=\"ctrlGlobalControls\">\n".
          "<div>\n".
          "Active mode:\n".
          stGetShowModeButton(SMODE_ROTATE, "Slide rotation", $showMode)."\n".
          stGetShowModeButton(SMODE_COMPO, "Compo mode", $showMode)."\n".
          stGetFormButtonInput("syscheck", "", "", " Perform system check ", "performSystemCheck()")."\n".
          stGetFormButtonInput("generate", "", "", " Add missing show positions ", "generateEntryPositions(0, 1)")."\n".
          stGetFormButtonInput("regenerate", "", "", " ReGenerate ALL show positions ", "generateEntryPositions(0, 0)")."\n".
          "</div>\n".
          "<div>\n".
          "</div>\n".
          "</div>\n";
        break;

      case "news":
        echo
          "<form method=\"post\" action=\"\" onsubmit=\"return addNews()\">\n".
          "  ".stGetFormTextInput(40, SET_LEN_NEWS_TITLE, "", "nntitle", "", "")."<br />\n".
          "  ".stGetFormTextArea(5, 60, "", "nntext", "", "")."<br />\n".
          "  ".stGetFormTextInput(20, SET_LEN_NEWS_AUTHOR, "", "nnauthor", "", "orgaz")."\n".
          "  ".stGetFormSubmitInput("nnadd", "Add post")."\n".
          "  ".stGetFormButtonInput("", "", "", "Clear", "this.form.reset()")."\n".
          "</form>\n".
          "<hr />\n";

        $sql = "SELECT * FROM news ORDER BY utime DESC";
        foreach (stExecSQL($sql) as $item)
        {
          echo
            "<div id=\"news".$item["id"]."\">\n".
            stGetNewsItemData($item["id"], $item, "ne").
            "</div>\n".
            "<hr />\n";
        }
        break;

      case "newsitem":
        $res = stFetchSQL(stPrepareSQL("SELECT * FROM news WHERE id=%D", "id"));
        if ($res !== FALSE)
          echo stGetNewsItemData($res["id"], $res, "ne");
        break;

      case "attendees":
        echo
          "<div class=\"tabHeadersSub\">\n".
          "<a href=\"print.php?type=emails\" target=\"_blank\">Show plain list of e-mails</a>\n".
          "</div>\n";

        // For adding a new one
        $prefix = "ne";
        echo
          "<table>\n".
          " <tr>\n".
          "  <th>Name</th>\n".
          "  <th>Groups</th>\n".
          "  <th>Oneliner</th>\n".
          "  <th>E-mail</th>\n".
          "  <th>Actions</th>\n".
          " </tr>\n".
          " <tr>\n".
          "  <td>".stGetFormTextInput(20, SET_LEN_USERNAME, "name", "x", $prefix, "")."</td>\n".
          "  <td>".stGetFormTextInput(20, SET_LEN_GROUPS,   "groups", "x", $prefix, "")."</td>\n".
          "  <td>".stGetFormTextInput(30, SET_LEN_ONELINER, "oneliner", "x", $prefix, "")."</td>\n".
          "  <td>".stGetFormTextInput(20, SET_LEN_EMAIL,    "email", "x", $prefix, "")."</td>\n".
          "  <td>".stGetFormButtonInput("add", "", $prefix, " Add new ", "addAttendee()")."</td>\n".
          " </tr>\n".
          "</table>\n".
          "<hr />\n";

        // List of attendees
        echo
          "<table class=\"attendees\">\n".
          " <tr>\n".
          "  <th class=\"name\">Name</th>\n".
          "  <th class=\"groups\">Groups</th>\n".
          "  <th class=\"regtime\">Registered</th>\n".
          "  <th class=\"oneliner\">Oneliner</th>\n".
          "  <th class=\"email\">E-mail</th>\n".
          "  <th>Actions</th>\n".
          " </tr>\n";

        $sql = "SELECT * FROM attendees ORDER BY regtime DESC";
        $row = 0;
        foreach (stExecSQL($sql) as $item)
          stPrintAttendee($item, $row++, TRUE, TRUE, FALSE);

        echo
          "</table>\n";
        break;

      case "attendee":
        $res = stFetchSQL(stPrepareSQL("SELECT * FROM attendees WHERE id=%D", "id"));
        if ($res !== FALSE)
          stPrintAttendee($res, -1, FALSE, TRUE, stGetRequestItem("edit", FALSE));
        break;

      case "votekey":
      case "votekeyclass":
        switch ($voteKeyMode)
        {
          case VOTE_FREELY:
          case VOTE_ACTIVATE:
            $sql = stPrepareSQL("SELECT * FROM votekeys WHERE id=%D", "id");
            break;

          case VOTE_ASSIGN:
            $sql = stPrepareSQL("SELECT votekeys.key,attendees.* FROM attendees ".
              "LEFT JOIN votekeys ON votekeys.id=attendees.key_id ".
              "WHERE attendees.id=%D", "id");
              break;
        }
        if (($res = stFetchSQL($sql)) !== FALSE)
        {
          if ($type == "votekeyclass")
            echo stGetVoteKeyClass($res);
          else
            echo stGetVoteKeyItemData($res["id"], $res, "vk");
        }
        break;

      case "voters":
        // Generate vote keys, if needed
        $numVKeys = stFetchSQLColumn("SELECT COUNT(*) FROM votekeys");
        $numUsers = stFetchSQLColumn("SELECT COUNT(*) FROM attendees");
        while ($numVKeys < $numUsers)
        {
          if (($key = stGenerateUserKey()) !== false)
          {
            if (stExecSQL(stPrepareSQL("INSERT INTO votekeys (key) VALUES (%s)", $key)) !== false)
              $numVKeys++;
          }
        }

        // List of votekeys
        echo
          "<div class=\"info\"><b>Voting mode: ".$voteModeData[$voteKeyMode][0]."</b>. ".$voteModeData[$voteKeyMode][1]."</div>\n".
          "<div class=\"tabHeadersSub\">\n".
          "<a href=\"print.php?type=votekeys\" target=\"_blank\">Show printable key list</a>\n".
          "</div>\n";

        switch ($voteKeyMode)
        {
          case VOTE_FREELY:
          case VOTE_ACTIVATE:
            $sql = "SELECT * FROM votekeys ORDER BY votekeys.id ASC";

            foreach (stExecSQL($sql) as $item)
            {
              // This funny code is to ensure that the cells are of uniform width
              echo
                "<div class=\"".stGetVoteKeyClass($item).
                "\" id=\"vkey".$item["id"]."\">".
                stGetVoteKeyItemData($item["id"], $item, "vk").
                "</div>\n";
            }
            break;

          case VOTE_ASSIGN:
            $sql = "SELECT votekeys.key,attendees.* FROM attendees ".
              "LEFT JOIN votekeys ON votekeys.id=attendees.key_id ".
              "ORDER BY attendees.regtime DESC";

            echo
              "<table class=\"attendees\">\n".
              " <tr>\n".
              "  <th class=\"name\">Name</th>\n".
              "  <th class=\"groups\">Groups</th>\n".
              "  <th class=\"vkeynum\">Key #</th>\n".
              "  <th class=\"vkey\">Votekey</th>\n".
              " </tr>\n";

            $index = 0;
            foreach (stExecSQL($sql) as $item)
            {
              echo
                " <tr class=\"".stGetVoteKeyClass($item).
                "\" id=\"vkey".$item["id"]."\">\n".
                stGetVoteKeyItemData($item["id"], $item, "vk").
                " </tr>\n";
            }

            echo
              "</table>\n";
            break;
        }
        break;

      case "compos":
        echo
          "<form method=\"post\" action=\"\" onsubmit=\"return addCompo()\">\n".
          "  ".stGetFormTextInput(64, SET_LEN_COMPO_NAME, "", "ncname", "", "")."<br />\n".
          "  ".stGetFormTextArea(5, 60, "", "ncdescription", "", "")."<br />\n".
          "  ".stGetFormSubmitInput("nccompo", "Add compo")."\n".
          "  ".stGetFormButtonInput("", "", "", "Clear", "this.form.reset()")."\n".
          "</form>\n".
          "<hr />\n";

        $sql = "SELECT * FROM compos ORDER BY id DESC";
        foreach (stExecSQL($sql) as $item)
        {
          echo
            "<div id=\"compo".$item["id"]."\">\n".
            stGetCompoData($item["id"], $item, "co").
            "</div>\n".
            "<hr />\n";
        }
        break;

      case "compo":
        $res = stFetchSQL(stPrepareSQL("SELECT * FROM compos WHERE id=%D", "id"));
        if ($res !== FALSE)
          echo stGetCompoData($res["id"], $res, "co");
        break;


      case "settings":
        $prefix = "st";

        echo
        "<h1>Site settings</h1>\n".
        "<form method=\"post\" action=\"\" onsubmit=\"return updateSettings()\">\n".
        "<table>\n";
        foreach (stExecSQL("SELECT * FROM settings WHERE vtype<>".VT_TEXT) as $item)
        {
          echo
          " <tr>\n".
          "  <td>";
          $id = $item["key"];
          switch ($item["vtype"])
          {
            case VT_INT:
              echo stGetFormTextInput(10, 10, "", $id, $prefix, $item["vint"]);
              break;
            case VT_STR:
              echo stGetFormTextInput(40, 128, "", $id, $prefix, $item["vstr"]);
              break;
            case VT_BOOL:
              echo stGetFormCheckBoxInput("", $id, $prefix, $item["vint"], "");
              break;
          }
          echo "</td>\n".
          "  <td>".$item["desc"]."</td>\n".
          " </tr>\n";
        }
        echo "</table>\n".stGetSaveButton();

        foreach (stExecSQL("SELECT * FROM settings WHERE vtype=".VT_TEXT) as $item)
        {
          echo
            "<h2>".chentities($item["desc"])."</h2>\n".
            stGetFormTextArea(10, 60, "", $item["key"], $prefix, $item["vtext"]).
            "\n<br />\n".
            stGetSaveButton();
        }
        echo "</form>\n";
        break;
      
      case "compolist":
        $index = 0;
        foreach (stExecSQL("SELECT * FROM compos") as $compo)
        {
          if ($index++ > 0) echo ",";
          echo "\"".$compo["id"]."\":\"".chentities($compo["name"])."\"";
        }
        break;

      case "entry":
        $res = stFetchSQL(stPrepareSQL("SELECT * FROM entries WHERE id=%D", "id"));
        if ($res !== FALSE)
          echo stGetEntryItemData($res["id"], $res, "en");
        break;

      case "entries":
        $id = intval(stGetRequestItem("id", 0));
        if (($compo = stFetchSQL("SELECT * FROM compos WHERE id=".$id)) !== false)
        {
          $nentries = stFetchSQLColumn("SELECT COUNT(*) FROM entries WHERE compo_id=".$id);
          $prefix = "ne";
          echo
            "<h1 style=\"margin-bottom: 0px;\">#".$id." - ".chentities($compo["name"]).
            " (".$nentries." entries)</h1>\n";

          if ($nentries > 0)
          {
            echo
              stGetFormButtonInput("generate", "", "", " Add missing show positions ", "generateEntryPositions(".$id.", 1)")."\n".
              stGetFormButtonInput("regenerate", "", "", " ReGenerate show positions ", "generateEntryPositions(".$id.", 0)")."\n";
          }

          echo
            "<form>\n".
            " <table class=\"misc\">\n".
            "  <tr>\n".
            "   <th style=\"width:4%;\">S#</th>\n".
            "   <th>Name</th>\n".
            "   <th>Author(s)</th>\n".
            "   <th>Filename</th>\n".
            "   <th>Info</th>\n".
            "   <th>Actions</th>\n".
            "  </tr>\n".
            "  <tr>\n".
            "   <td></td>\n".
            "   <td>".stGetFormTextInput(20, SET_LEN_ENTRY_NAME, "name", $id, $prefix, "")."</td>\n".
            "   <td>".stGetFormTextInput(15, SET_LEN_ENTRY_AUTHOR, "author", $id, $prefix, "")."</td>\n".
            "   <td>".stGetFormTextInput(20, SET_LEN_ENTRY_FILENAME, "filename", $id, $prefix, "")."</td>\n".
//            "   <td>".stGetFormTextInput(20, SET_LEN_ENTRY_INFO, "info", $id, $prefix, "")."</td>\n".
            "   <td>".stGetFormTextArea(2, 30, "info", $id, $prefix, "")."</td>\n".
            "   <td>".stGetFormButtonInput("add", $id, $prefix, "Add new", "addEntry(".$id.")")."</td>\n".
            "  </tr>\n".
            "  <tr><td colspan=\"6\"><hr /></td></tr>\n";

          foreach (stExecSQL("SELECT * FROM entries WHERE compo_id=".$id) as $entry)
          {
            echo
              "  <tr id=\"entry".$entry["id"]."\">\n".
              stGetEntryItemData($entry["id"], $entry, "en").
              "  </tr>\n";
          }

          echo
            " </table>\n".
            "</form>\n";
        }
        break;
    }
    break;

  case "delete":
    //
    // Delete entry
    //
    if (stChkRequestItem("id", $id, array(CHK_TYPE, VT_INT, "Invalid data.")))
    {
      if ($type == "news")
      {
        $sql = stPrepareSQL("DELETE FROM news WHERE id=%d AND persist=0", $id);
        stExecSQLCond($sql, "OK, news item ".$id." deleted.");
      }
      else
      if ($type == "attendees")
      {
        // Attendees require some more work
        $sql = stPrepareSQL("SELECT * FROM attendees WHERE id=%d", $id);
        if (($attn = stFetchSQL($sql)) !== false)
        {
          $sql = stPrepareSQL("DELETE FROM attendees WHERE id=%d", $id);
          stExecSQLCond($sql, "OK, attendee ".$id." deleted.");

          // If assigned votekey mode, delete the key and votes as well
          if ($voteKeyMode == VOTE_ASSIGN && $attn["key_id"] != 0)
          {
            $sql = stPrepareSQL("DELETE FROM votekeys WHERE id=%d", $attn["key_id"]);
            stExecSQLCond($sql, "OK, attendee ".$id." votekey deleted.");

            $sql = stPrepareSQL("DELETE FROM votes WHERE key_id=%d", $attn["key_id"]);
            stExecSQLCond($sql, "OK, attendee ".$id." votes deleted.");
          }
        }
        else
          stError("No such attendee ID #".$id);
      }
      else
      if ($type == "entries")
      {
        // .. as do compo entries
        $sql = stPrepareSQL("DELETE FROM entries WHERE id=%d", $id);
        stExecSQLCond($sql, "OK, entry ".$id." deleted.");

        $sql = stPrepareSQL("DELETE FROM votes WHERE entry_id=%d", $id);
        stExecSQLCond($sql, "OK, entry ".$id." votes deleted.");
      }
    }
    else
    if ($type == "votekeys")
    {
      $sql = stPrepareSQL("DELETE FROM votekeys");
      stExecSQLCond($sql, "OK, all votekeys purged");
    }
    break;

  case "add":
    //
    // Add new entry
    //
    if ($type == "news" && stValidateRequestNewsData())
    {
      $sql = stPrepareSQL(
        "INSERT INTO news (utime,title,text,author) VALUES (%d,%S,%Q,%S)",
        time(), "title", "text", "author");

      stExecSQLCond($sql, "OK, news item added.");
    }
    else
    if ($type == "compo" && stValidateRequestCompoData(FALSE))
    {
      $sql = stPrepareSQL(
        "INSERT INTO compos (name,description,visible,voting,showAuthors) VALUES (%S,%Q,0,0,0)",
        "name", "description");

      stExecSQLCond($sql, "OK, compo added.");
    }
    else
    if ($type == "attendees" && stValidateRequestUserData(TRUE))
    {
      $sql = stPrepareSQL(
        "INSERT INTO attendees (regtime,name,groups,oneliner,email) VALUES (%d,%S,%S,%S,%S)",
        time(), "name", "groups", "oneliner", "email");

      stExecSQLCond($sql, "OK, attendee added.");
    }
    else
    if ($type == "entry" && stValidateRequestEntryData($fake))
    {
      if (stFetchSQLColumn(stPrepareSQL("SELECT id FROM compos WHERE id=%D", "compo_id")) === FALSE)
      {
        stError("No such compo ID.");
      }
      else
      {
        $sql = stPrepareSQL(
          "INSERT INTO entries (name,author,compo_id,filename,info) VALUES (%S,%S,%D,%S,%Q)",
          "name", "author", "compo_id", "filename", "info");

        stExecSQLCond($sql, "OK, entry added.");
      }
    }
    break;

  case "update":
    //
    // Update existing entry
    //
    if ($type == "settings")
    {
      foreach (stExecSQL("SELECT * FROM settings") as $item)
      if (($val = stGetRequestItem($item["key"], FALSE)) !== FALSE)
      {
        $sql = "UPDATE settings SET ".stGetSettingSQL($item, $val)." WHERE key=".$db->quote($item["key"]);
        stExecSQLCond($sql, "OK, setting updated.");
      }
    }
    else
    if (stChkRequestItem("id", $id, array(CHK_TYPE, VT_INT, "Invalid data.")))
    {
      if ($type == "attendees" && stValidateRequestUserData(TRUE))
      {
        $sql = stPrepareSQLUpdate("attendees",
          "WHERE id=".intval(stGetRequestItem("id")),
          array(
            "name" => "S",
            "groups" => "S",
            "email" => "S",
            "oneliner" => "S",
          ));

        stExecSQLCond($sql, "OK, attendee updated.");
      }
      else
      if ($type == "news" && stValidateRequestNewsData())
      {
        $sql = stPrepareSQLUpdate("news",
          "WHERE id=".intval(stGetRequestItem("id")),
          array(
            "title" => "S",
            "text" => "Q",
            "author" => "S"
          ));

        stExecSQLCond($sql, "OK, news item updated.");
      }
      else
      if ($type == "compo" && stValidateRequestCompoData(TRUE))
      {
        $sql = stPrepareSQLUpdate("compos",
          "WHERE id=".intval(stGetRequestItem("id")),
          array(
            "name" => "S",
            "description" => "Q",
            "visible" => "B",
            "voting" => "B",
            "showAuthors" => "B",
          ));

        stExecSQLCond($sql, "OK, compo updated.");
      }
      else
      if ($type == "entry" && stValidateRequestEntryData($compo_id))
      {
        if (stFetchSQLColumn("SELECT id FROM compos WHERE id=".$compo_id) === FALSE)
        {
          stError("No such compo ID.");
        }
        else
        {
          $sql = stPrepareSQLUpdate("entries",
            "WHERE id=".intval(stGetRequestItem("id")),
            array(
              "name" => "S",
              "author" => "S",
              "filename" => "S",
              "info" => "Q",
              "compo_id" => "D",
            ));

          stExecSQLCond($sql, "OK, entry updated.");
        }
      }
      else
      if ($type == "votekey")
      {
        switch (stGetRequestItem("mode"))
        {
          case "assign":
            // Check if already assigned to someone ..
            $key_id = intval(stGetRequestItem("key_id", 0));
            $sql = stPrepareSQL("SELECT * FROM votekeys WHERE id=%d", $key_id);
            if (stFetchSQL($sql) === false)
              stError("Invalid key ID #.");
            else
            {
              $sql = stPrepareSQL("SELECT * FROM attendees WHERE key_id=%d", $key_id);
              if (($attn = stFetchSQL($sql)) !== false && $attn["id"] != $id)
                stError("That key has already been assigned to another attendee!");
              else
              {
                // Assign ..
                $sql = stPrepareSQL("UPDATE attendees SET key_id=%d WHERE id=%d", $key_id, $id);
                stExecSQLCond($sql, "Assigned key updated.");
              }
            }
            break;

          case "clear":
            $sql = stPrepareSQL("UPDATE attendees SET key_id=NULL WHERE id=%D", "id");
            stExecSQLCond($sql, "Assigned key cleared.");
            break;
          
          case "active":
            // Autobots activate!
            $sql = stPrepareSQL("UPDATE votekeys SET active=%B WHERE id=%D", "active", "id");
            stExecSQLCond($sql, "Votekey status changed.");
            break;
        }
      }
    }
    break;

  default:
    stSetStatus(404, "Not Found");
    break;
}

if (!$errorSet)
  stSaveDisplayVars();

stDumpAJAXStatusErrors();
?>