<?php

  # set globals
  global $TABLE_PREFIX, $menu, $tableName, $escapedTableName, $schema, $action;
  $menu             = @$FORM['menu'];
  $tableName        = @$FORM['menu'];
  $escapedTableName = mysql_real_escape_string( $TABLE_PREFIX . $tableName );
  $schema           = loadSchema($tableName);

  // redirect for custom menus
  $customMenu = file_exists("lib/menus/$menu/actionHandler.php");
  if ($customMenu) {
    include "lib/menus/$menu/actionHandler.php";
    exit;
  }

  // display error for unknown menu names
  if (!@$schema['menuType']) {
    alert("Unknown menu '" . htmlspecialchars($menu) . "'");
    showInterface('');
  }

  // display alerts
  if (@$FORM['saved']) { alert("Record saved."); }

  ### Limit access to menu
  global $CURRENT_USER, $hasAdminAccess, $hasUserAccess;
  $hasAdminAccess = @$CURRENT_USER['accessList']['all']['accessLevel'] >= 9 || @$CURRENT_USER['accessList'][$tableName]['accessLevel'] >= 9;
  $hasUserAccess  = @$CURRENT_USER['accessList']['all']['accessLevel'] >= 6 || @$CURRENT_USER['accessList'][$tableName]['accessLevel'] >= 6;
  if (!$hasAdminAccess && !$hasUserAccess) {
    alert("You don't have permissions to access this menu.");
    showInterface('');
  }
  if (!$hasAdminAccess && !@$schema['createdByUserNum']) {
    alert("This section isn't configured to allow 'regular' user access.<br/>\n");
    alert("Ask the webmaster to give you 'Admin' access to this section or create a field called 'createdByUserNum'.");
    showInterface('');
  }

  ### Limit access to records
  if (!$hasAdminAccess && @$FORM['num'] && @$schema['createdByUserNum'] && @$schema['menuType'] != 'single') {
    $query  = "SELECT * FROM `$escapedTableName` WHERE num = '".mysql_real_escape_string($FORM['num'])."'";
    $result = mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
    $record = mysql_fetch_assoc($result);

    if ($record['createdByUserNum'] && $CURRENT_USER['num'] != $record['createdByUserNum']) {
      alert("You don't have permission to access this record.");
      showInterface('');
      exit;
    }
  }

  ### Dispatch actions
  $defaultAction = (@$schema['menuType'] == 'single') ? 'edit' : 'list';
  $action        = getRequestedAction($defaultAction);
  if     ($action == 'list')                 { include('lib/menus/default/list.php'); }
  elseif ($action == 'listDragSort')         { listDragSort(); }
  elseif ($action == 'add')                  { showMaxRecordsError(); showInterface('default/edit.php'); }
  elseif ($action == 'edit')                 { showInterface('default/edit.php'); }
  elseif ($action == 'erase')                { eraseRecord(); }
  elseif ($action == 'save')                 { include('lib/menus/default/save.php');  }
  elseif ($action == 'uploadList')           { include('lib/menus/default/uploadList.php');  }
  elseif ($action == 'uploadListReOrder')    { uploadListReOrder();  }
  elseif ($action == 'uploadForm')           { include('lib/menus/default/uploadForm.php');  }
  elseif ($action == 'uploadModify')         { include('lib/menus/default/uploadModify.php');  }
  elseif ($action == 'uploadErase')          { eraseUpload(); }
  elseif ($action == 'wysiwygUploads')       { include('lib/menus/default/wysiwygUploads.php');  }

  elseif ($action == 'ajaxGetUsersAsPulldown') { ajaxGetUsersAsPulldown(); }
  elseif ($action == 'categoryMove')           { categoryMove();  }


#  elseif ($action == 'uploadModify')         { include('lib/menus/default/uploadModify.php');  }
  else {
    alert("Unknown action '" . htmlspecialchars($action) . "'");
    showInterface('');
    exit;
  }

//
function ajaxGetUsersAsPulldown() {
  global $TABLE_PREFIX;
  if (!$GLOBALS['hasAdminAccess']) { return ''; } // must have section admin access

  $html  = "<select name='createdByUserNum'>\n";
  $html .= "<option value=''>&lt;select user&gt;</option>\n";

  //
  $query  = "SELECT * FROM `{$TABLE_PREFIX}accounts` ORDER BY fullname";
  $result = mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
  $options = "";
  while ($record = mysql_fetch_assoc($result)) {
    $html .= "<option value='{$record['num']}'>" .htmlspecialchars($record['fullname']). "</option>\n";
  }
  if (is_resource($result)) { mysql_free_result($result); }
  $html .= "</html>\n";

  print $html;
  exit;
}


//
function listDragSort() {
  global $FORM, $schema, $escapedTableName, $CURRENT_USER;

  // error checking
  $errors = "";
  if (!$FORM['recordNums'])                         { $errors .= "No 'recordNums' specified!\n"; }
  if (preg_match("/[^\d\,]/", $FORM['recordNums'])) { $errors .= "'recordNums' contains invalid chars! ('" .htmlspecialchars($FORM['recordNums']). "')\n"; }
  if (!@$schema['dragSortOrder'])                   { $errors .= "No 'dragSortOrder' field specified in table schema!\n"; }
  if ($errors) { die($errors); }


  // assign default value to new dragSortOrder fields
  // NOTE: This copies the existing order by using the schema listPageOrder to Order By
  mysql_query("SET @count = 0") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
  mysql_query("UPDATE `$escapedTableName` SET `dragSortOrder` = (SELECT @count := @count + 1) WHERE dragSortOrder = 0 ORDER BY {$schema['listPageOrder']}") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");

  // re-order dragSortOrder field
  // NOTE: this re-numbers all the field values to make sure we don't have duplicates, etc
  mysql_query("UPDATE `$escapedTableName` SET `dragSortOrder` = (SELECT @count := @count + 1) ORDER BY dragSortOrder") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");

  // get order values for selected records
  $numToOrder = array();
  $result = mysql_query("SELECT num, dragSortOrder FROM `$escapedTableName`
                          WHERE num IN ({$FORM['recordNums']})
                          ORDER BY {$schema['listPageOrder']}") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
  while ($row = mysql_fetch_assoc($result)) {
    $orderValues[] = $row['dragSortOrder'];
  }

  // re-assign same order values to records in new order
  $recordNums    = preg_split("/\,/", $FORM['recordNums']); // new record order
  $whereOwner   = ""; // restrict re-order access if not admin
  if (!$GLOBALS['hasAdminAccess'] && @$schema['createdByUserNum']) {
    $whereOwner = "AND createdByUserNum = '{$CURRENT_USER['num']}'";
  }

  foreach ($recordNums as $num) {  // apply old order sequence to re-ordered record numbers
    if (!$num) { die("No num found in 'recordNums!'\n"); }

    $newOrder     = array_shift($orderValues);
    $escapedOrder = mysql_real_escape_string($newOrder);
    $escapedNum   = mysql_real_escape_string($num);

    $query = "UPDATE `$escapedTableName` SET dragSortOrder = '$escapedOrder' WHERE num = '$escapedNum' $whereOwner\n";
    mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
  }

}


//
function eraseRecord() {
  global $FORM, $escapedTableName, $schema;
  $num  = (int) $FORM['num'];

  // error checking
  if (!$num) { die("no record number specified!"); }

  // erase record
  if (!@$schema['_disableErase']) {
    $query  = "DELETE FROM `$escapedTableName` WHERE num = ".mysql_real_escape_string($num)."";
    mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
  }

  //
  if     (@$schema['_disableErase']) { alert("Erasing records has been disabled for this section!"); }
  elseif (mysql_affected_rows())     { alert("Record erased!"); }
  else                               { alert("Couldn't erase record (record no longer exists)!"); }

  include('lib/menus/default/list.php');
}


//
function eraseUpload() {
  global $TABLE_PREFIX, $FORM, $tableName, $escapedTableName;

  // error checking
  if (!array_key_exists('fieldName', $FORM))     { die("no 'fieldName' value specified!"); }
  if (!array_key_exists('uploadNum', $FORM))     { die("no 'uploadNum' value specified!"); }

  // create where query
  $whereQuery = " WHERE ";
  if      ($FORM['num'])           { $whereQuery .= "recordNum     = '".mysql_real_escape_string( $FORM['num'] )."' AND "; }
  else if ($FORM['preSaveTempId']) { $whereQuery .= "preSaveTempId = '".mysql_real_escape_string( $FORM['preSaveTempId'] )."' AND "; }
  else                             { die("No value specified for 'num' or 'preSaveTempId'!"); }
  $whereQuery .= "num       = '".mysql_real_escape_string($FORM['uploadNum'])."' AND ";
  $whereQuery .= "tableName = '".mysql_real_escape_string($tableName)."' AND ";
  $whereQuery .= "fieldName = '".mysql_real_escape_string($FORM['fieldName'])."'";

  // load upload record
  $result = mysql_query("SELECT * FROM {$TABLE_PREFIX}uploads $whereQuery") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
  $count  = 0;
  while ($row = mysql_fetch_assoc($result)) {
    $count++;

    // remove uploads and thumbnails
    $files = array($row['filePath'], $row['thumbFilePath']);
    foreach ($files as $filepath) {
      if (!file_exists($filepath)) { continue; }
      if (!@unlink($filepath)) {
        $error  = "Unable to remove file '" .htmlspecialchars($filepath). "'\n\n";
        $error .= "Please ask your server administrator to check permissions on that file and directory.\n\n";
        $error .= "The PHP error message was: $php_errormsg\n";
        die($error);
      }
    }

    // remove record
    mysql_query("DELETE FROM {$TABLE_PREFIX}uploads WHERE num = {$row['num']}") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
  }

  //
  if ($count == 0) { die("Upload not found!"); }

  // this function is called via ajax, any output will be returns as errors with javascript alert
  exit;
}

//
function showUploadPreview($record, $previewWidth = 50) {

  //
  $isImage      = preg_match("/\.(gif|jpg|jpeg|png)$/i", $record['urlPath']);
  $hasThumbnail = $isImage && $record['thumbUrlPath'];
  $filename     = pathinfo($record['filePath'], PATHINFO_BASENAME);

  //
  $resizeRation = null;
  $previewHeight = null;
  if ($isImage) {
    $resizeRatio   = $record['width'] / $previewWidth;
    $previewHeight = ceil($record['height'] / $resizeRatio);
  }

  //
  if ($hasThumbnail) {
    print "<a href='{$record['urlPath']}' target='_BLANK'><img src='" .htmlspecialchars($record['thumbUrlPath']). "' border='0' width='$previewWidth' height='$previewHeight' alt='' title='Click to view " .htmlspecialchars($filename). "' /></a>\n";
  }
  elseif ($isImage) {
    print "<a href='{$record['urlPath']}' target='_BLANK'><img src='" .htmlspecialchars($record['urlPath']). "' border='0' width='$previewWidth' height='$previewHeight' alt='' title='Click to view " .htmlspecialchars($filename). "'  /></a>\n";
  }
  else {
    print "<a href='{$record['urlPath']}' target='_BLANK'>download</a>\n";
  }
}

//
function showMaxRecordsError($returnText = false) {
  global $CURRENT_USER, $tableName, $escapedTableName, $schema, $hasAdminAccess;
  $errors = "";

  // check section record limit
  if (@$schema['_maxRecords'] != "") {
    $result = mysql_query("SELECT COUNT(*) FROM $escapedTableName") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
    list($recordCount) = mysql_fetch_row($result);

    if ($recordCount >= $schema['_maxRecords']) {
      $errors .= "This section only allows a total of '{$schema['_maxRecords']}' records (section limit).<br/>\n";
    }
  }

  // check user records limit (regular users only)
  if (!$hasAdminAccess && @$schema['createdByUserNum']) {
    $result = mysql_query("SELECT COUNT(*) FROM $escapedTableName WHERE `createdByUserNum` = '{$CURRENT_USER['num']}'") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
    list($recordCount) = mysql_fetch_row($result);

    if (@$schema['_maxRecordsPerUser'] && $recordCount >= $schema['_maxRecordsPerUser']) {
      $errors .= "You are only allowed to have '{$schema['_maxRecordsPerUser']}' records in this section (Section Editor Limit).<br/>\n";
    }
    elseif (@$CURRENT_USER['accessList'][$tableName]['maxRecords'] && $recordCount >= $CURRENT_USER['accessList'][$tableName]['maxRecords']) {
      $errors .= "You are only allowed to have '{$CURRENT_USER['accessList'][$tableName]['maxRecords']}' records in this section (User Account Limit).<br/>\n";
    }
  }

  // display errors
  if ($errors) {
    if ($returnText) { return $errors; }
    else {
      alert($errors);
      include('lib/menus/default/list.php');
      exit;
    }
  }

}


//
function getUploadCount($tableName, $fieldName, $recordNum, $preSaveTempId) {
  global $TABLE_PREFIX;
  $uploadCount = 0;

  // create query
  $query  = "SELECT COUNT(*) FROM {$TABLE_PREFIX}uploads WHERE ";
  $query .= "tableName = '".mysql_real_escape_string( $tableName )."' AND ";
  $query .= "fieldName = '".mysql_real_escape_string( $fieldName )."' AND ";
  if      ($recordNum)     { $query .= "recordNum     = '".mysql_real_escape_string( $recordNum )."'"; }
  else if ($preSaveTempId) { $query .= "preSaveTempId = '".mysql_real_escape_string( $preSaveTempId )."'"; }
  else { die("You must specify either a record 'num' or 'preSaveTempId'!"); }

  // execute query
  $result = mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
  list($uploadCount) = mysql_fetch_row($result);

  //
  return $uploadCount;
}


//
function getUploads($tablename, $fieldname, $recordNum, $preSaveTempId, $uploadNums) {
  global $TABLE_PREFIX, $FORM;

  //
  $query  = "SELECT * FROM {$TABLE_PREFIX}uploads ";
  $query .= " WHERE tableName = '".mysql_real_escape_string( $tablename )."' AND ";
  $query .= "       fieldName = '".mysql_real_escape_string( $fieldname )."' AND ";

  if      ($recordNum)     { $query .= "recordNum     = '".mysql_real_escape_string( $recordNum )."' "; }
  else if ($preSaveTempId) { $query .= "preSaveTempId = '".mysql_real_escape_string( $preSaveTempId )."' "; }
  else                     { die("You must specify either a record 'num' or 'preSaveTempId'!"); }
  if ($uploadNums)         { $query .= " AND num IN(".mysql_real_escape_string( $uploadNums ).") "; }

  $query .= " ORDER BY `order`, num";
  $result = mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");

  //
  return $result;
}

// foreach (getUploadInfoFields($record) as $name => $label) { ...
function getUploadInfoFields($fieldname) {
  global $schema;
  $infoFields = array();

  //
  $fieldSchema = $schema[$fieldname];
  foreach ($fieldSchema as $name => $value) {
    if (!preg_match("/^infoField\d+$/", $name)) { continue; } // skip if not info field
    if (!$value)                                { continue; } // skip if no field label
    $fieldname = preg_replace("/Field/", "", $name);

    $infoFields[$fieldname] = $value;
  }

  return $infoFields;
}



// get mysql column names/types
function getMySqlColsAndType($escapedTableName) {
  $columns = array();
  $result  = mysql_query("SHOW COLUMNS FROM `$escapedTableName`") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
  while ($row = mysql_fetch_assoc($result)) {
    $columns[ $row['Field'] ] = $row['Type'];
  }

  return $columns;
}


// ajax function,
function uploadListReOrder() {
  global $FORM, $TABLE_PREFIX, $tableName;

  # error checking
  if (!array_key_exists('num', $FORM))           { die(__FUNCTION__ . ": no record 'num' specified!");  }
  if (!array_key_exists('preSaveTempId', $FORM)) { die(__FUNCTION__ . ": no record 'preSaveTempId' specified!");  }
  if (!@$FORM['fieldName'])                      { die(__FUNCTION__ . ": no 'fieldName' specified!"); }
  if (!@$FORM['newOrder'])                       { die(__FUNCTION__ . ": no 'newOrder' specified!"); }

  # get upload order
  preg_match_all("/(\d+)/", @$FORM['newOrder'], $matches);
  $orderedUploadNums = $matches[0];

  # re-order uploads
  $newOrder = 0;
  foreach ($orderedUploadNums as $uploadNumber) {
    $query  = "UPDATE {$TABLE_PREFIX}uploads\n";
    $query .= "   SET `order`='".mysql_real_escape_string( ++$newOrder )."'\n";
    $query .= " WHERE num       = '$uploadNumber' AND\n";
    $query .= "       tableName = '".mysql_real_escape_string($tableName)."' AND\n";
    $query .= "       fieldName = '".mysql_real_escape_string($FORM['fieldName'])."' AND\n";
    if      ($FORM['num'])           { $query .= "recordNum     = '".mysql_real_escape_string( $FORM['num'] )."'"; }
    else if ($FORM['preSaveTempId']) { $query .= "preSaveTempId = '".mysql_real_escape_string( $FORM['preSaveTempId'] )."'"; }
    else                             { die("No value specified for 'num' or 'preSaveTempId'!"); }
    mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
  }

}



function updateCategoryMetadata() {
  global $escapedTableName, $schema;

  if ($schema['menuType'] != 'category') { return; }

  // load categoriesByNum
  $categoriesByNum = array();
  $query = "SELECT * FROM $escapedTableName ORDER BY globalOrder";
  $result = mysql_query($query) or die("MySQL Error: " .mysql_error(). "\n");
  while ($row = mysql_fetch_assoc($result)) { $categoriesByNum[ $row['num'] ] = $row; }
  if (is_resource($result)) { mysql_free_result($result); }

  // get childNums for each parentNum
  $childNumsOfParentNum = array();
  foreach (array_keys($categoriesByNum) as $num) {
    $parentNum = (int) $categoriesByNum[$num]['parentNum'];
    $childNumsOfParentNum[$parentNum][] = $num;
  }

  // reset order
  _updateCategoryBranch(array(
    'branchParent' => 0,
    'records'      => &$categoriesByNum,
    'childNodes'   => $childNumsOfParentNum,
  ));


  // save new order
  foreach ($categoriesByNum as $num => $category) {
    $query = "UPDATE `$escapedTableName` SET ";
    $query .= "`globalOrder`  = '" .mysql_real_escape_string($category['globalOrder']). "', ";
    $query .= "`siblingOrder` = '" .mysql_real_escape_string($category['siblingOrder']). "', ";
    $query .= "`depth`        = '" .mysql_real_escape_string($category['depth']). "', ";
    $query .= "`lineage`      = '" .mysql_real_escape_string($category['lineage']). "', ";
    $query .= "`breadcrumb`   = '" .mysql_real_escape_string($category['breadcrumb']). "' ";
    $query .= "WHERE num = '{$category['num']}'";
    mysql_query($query) or die("There was an error updating the category metadata:\n\n". htmlspecialchars(mysql_error()) . "\n");
  }

}



function _updateCategoryBranch($args) {

  ## set defaults
  if (!@$args['globalOrder']) { $args['globalOrder'] = 0; }
  if (!@$args['depth'])       { $args['depth']       = 0; }
  if (!@$args['lineage'])     { $args['lineage']     = ":"; }

  # sort branch children
  $sortedChildren = array();
  foreach ($args['childNodes'][ $args['branchParent'] ] as $childNum) {
    $sortedChildren[$childNum] = &$args['records'][$childNum];
  }
  uasort($sortedChildren, '_sortCategoriesBySiblingOrder');

  # loop over branch children
  $siblingOrder = 0;
  foreach (array_keys($sortedChildren) as $childNum) {
    $childRecord = &$args['records'][$childNum];

    $childRecord['globalOrder']  = ++$args['globalOrder'];
    $childRecord['siblingOrder'] = ++$siblingOrder;
    $childRecord['depth']        = $args['depth'];
    $childRecord['lineage']      = $args['lineage'] . "$childNum:";
    $childRecord['breadcrumb']   = @$args['breadcrumb'] ? "{$args['breadcrumb']} : {$childRecord['name']}" : $childRecord['name'];

  # if child has children, loop over them
    if (@$args['childNodes'][$childNum]) {
      _updateCategoryBranch(array(
        'branchParent' => $childNum,
        'globalOrder'  => &$args['globalOrder'],
        'records'      => &$args['records'],
        'childNodes'   => $args['childNodes'],
        'depth'        => ($args['depth'] + 1),
        'lineage'      => $childRecord['lineage'],
        'breadcrumb'   => $childRecord['breadcrumb'],
      ));
    }
  }

}


// uasort($categoriesByNum, '__sortCategoriesBySiblingOrder');
function _sortCategoriesBySiblingOrder($arrayA, $arrayB) {
  if ($arrayA['siblingOrder'] < $arrayB['siblingOrder']) { return -1; }
  if ($arrayA['siblingOrder'] > $arrayB['siblingOrder']) { return 1; }
  return 0;
}

//
function categoryMove() {
  global $menu, $escapedTableName, $FORM;

  // load categoriesByNum
  $categoriesByNum = array();
  $query = "SELECT * FROM $escapedTableName ORDER BY globalOrder";
  $result = mysql_query($query) or die("MySQL Error: " .mysql_error(). "\n");
  while ($row = mysql_fetch_assoc($result)) {
    $categoriesByNum[ $row['num'] ] = $row;
    $categoriesByNum[ $row['num'] ]['oldSiblingOrder'] = $row['siblingOrder'];
  }
  if (is_resource($result)) { mysql_free_result($result); }

  // update order
  $parentNum = $categoriesByNum[ $FORM['num'] ]['parentNum'];
  foreach (array_keys($categoriesByNum) as $num) {
    $category = &$categoriesByNum[$num];
    if ($category['parentNum'] != $parentNum) { continue; } // only modify siblings on branch
    $category['siblingOrder'] = 2 + ($category['siblingOrder'] * 2); // double space entries
   }
  if ($FORM['direction'] == 'up')   { $categoriesByNum[ $FORM['num'] ]['siblingOrder'] -= 3; }
  if ($FORM['direction'] == 'down') { $categoriesByNum[ $FORM['num'] ]['siblingOrder'] += 3; }

  // save new order
  foreach ($categoriesByNum as $num => $category) {
    if ($category['oldSiblingOrder'] == $category['siblingOrder']) { continue; } // skip if order didn't change
    $query = "UPDATE `$escapedTableName` SET ";
    $query .= "`siblingOrder` = '" .mysql_real_escape_string($category['siblingOrder']). "' ";
    $query .= "WHERE num = '{$category['num']}'";
    mysql_query($query) or die("There was an error updating the category metadata:\n\n". htmlspecialchars(mysql_error()) . "\n");
  }

  // update global order, etc
  updateCategoryMetadata();

  // refresh page
  $url = $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . "?menu=$menu";
  header("Location: http://$url");
  exit;
}

?>
