<?php // Permalinks CMS Menu Functions

// plugin hooks
addAction('admin_postlogin',               'permalink_cms_onInstallCreateSchemas',  null, 0);
addFilter('record_preedit',                'permalink_cms_onEditShowFieldPrefix',   null, 2);
addAction('record_presave',                'permalink_cms_onPreSaveAutopopulate',   10,   3);
addAction('record_presave',                'permalink_cms_onPreSaveLowercase',      20,   3);
addAction('record_save_posterrorchecking', 'permalink_cms_onSaveErrorChecking',     null, 3);
addAction('record_save_posterrorchecking', 'permalinkDB_onSaveErrorChecking', null, 3);
addAction('record_postsave',               'permalink_cms_onSaveUpdatePermalinks',  null, 4);
addAction('record_posterase',              'permalink_cms_onEraseRemovePermalinks', null, 2);


// create permalink schema once plugin is installed
function permalink_cms_onInstallCreateSchemas() {
  global $TABLE_PREFIX;


  // v1.01 upgrade - remove old schema so it gets re-created with new schema below (mysql data won't change)
  $upgradeTo101 = !array_value(loadSchema('_permalinks'), 'old'); // check for lack of field 'old' in schema
  if ($upgradeTo101) {
    @unlink( DATA_DIR.'/schema/_permalinks.ini.php' );
  }

  // on install/upgrade - create schemas from ./pluginSchemas/
  plugin_createSchemas();

  // v1.01 upgrade - set old flag on all but the latest permalinks
  if ($upgradeTo101) {
    $allAsOldQuery = "UPDATE {$TABLE_PREFIX}_permalinks SET `old` = 1";
    mysql_query($allAsOldQuery) or die("MySQL Error: ". htmlencode(mysql_error()) . "\n");

    $latestAsNewQuery = "UPDATE {$TABLE_PREFIX}_permalinks p1
                           JOIN (SELECT recordNum, MAX(updatedDate) as updatedDate FROM {$TABLE_PREFIX}_permalinks GROUP BY tableName, recordNum) as p2
                             ON p1.recordNum = p2.recordNum AND p1.updatedDate = p2.updatedDate
                            SET old = 0";
    mysql_query($latestAsNewQuery) or die("MySQL Error: ". htmlencode(mysql_error()) . "\n");
  }

}

// dynamically modify permalink schema to so "http://HOSTNAME/" and "/" shows before and after permalink field
function permalink_cms_onEditShowFieldPrefix($tableName, $recordNum) {
  // for sections with a permalink field: 
  if (array_key_exists('permalink', $GLOBALS['schema'])) {
    // update permalink prefix/suffix to show current hostname (whatever that may be)
    $GLOBALS['schema']['permalink']['fieldPrefix'] = implode(' ', array($GLOBALS['schema']['permalink']['fieldPrefix'], "http://" . htmlencode( $_SERVER['HTTP_HOST'] ) . PREFIX_URL . '/'));
    $GLOBALS['schema']['permalink']['description'] = '/ &nbsp;'. $GLOBALS['schema']['permalink']['description'];
  }
  
  // not yet used
  //if ($tableName == '_permalinks' && array_key_exists('customSourceUrl', $GLOBALS['schema'])) {
  //  $GLOBALS['schema']['customSourceUrl']['fieldPrefix']  = $GLOBALS['SETTINGS']['webRootDir'];
  //}
  
}

// if users submits a blank permalink (or a permalink with prefix only) autopopulate it based on title,name,etc field content
function permalink_cms_onPreSaveAutopopulate($tableName, $isNewRecord, $oldRecord) {
  if (!$GLOBALS['PERMALINKS']['autopopulate'])            { return; } // don't auto-populate unless enabled
  if (!array_key_exists('permalink', $GLOBALS['schema'])) { return; } // skip for sections without permalink fields
  if ($tableName == '_permalinks')                        { return; } // skip when admin is directly editing permalinks table

  // is autopopulate needed?
  $permalinkText   = @$_REQUEST['permalink'];
  $permalinkPrefix = $GLOBALS['schema']['permalink']['defaultValue'];
  $doAutopopulate  = ($permalinkText == '' || $permalinkText == $permalinkPrefix);

  // auto-populate permalink by updating $_REQUEST
  if ($doAutopopulate) { 
    $_REQUEST['permalink'] = permalink_generate(@$_REQUEST, $permalinkPrefix);
  }
}



//
function permalink_cms_onPreSaveLowercase($tableName, $isNewRecord, $oldRecord) {
  if (!array_key_exists('permalink', $GLOBALS['schema'])) { return; } // skip for sections without permalink fields

  // lowercase permalink
  if (@$_REQUEST['permalink']) {
    $_REQUEST['permalink'] = strtolower(@$_REQUEST['permalink']);
  }
}


// on save add some error checking to make sure permalinks are what we want
function permalink_cms_onSaveErrorChecking($tableName, $recordExists, $oldRecord) {
  if (!array_key_exists('permalink', $GLOBALS['schema']))   { return; } // skip for sections without permalink fields
  if ($tableName == '_permalinks') { return; } // skip for _permalinks menu itself

  // check that viewer path can be determined
  list(, $pathErrors) = _permalink_getAbsolutePath($tableName, null);
  if ($pathErrors) { die(t("Permalinks: ") . $pathErrors); }

  // get permalink
  $permalinkText   = @$_REQUEST['permalink'];
  $permalinkRecord = mysql_get('_permalinks', null, array('permalink' => $permalinkText)); // check if permalink already exists in database
  $isAlreadyUsed   = $permalinkRecord && $permalinkRecord['recordNum'] != @$_REQUEST['num'] && ($tableName != '_permalinks');

  // error checking
  $requiredPrefix  = $GLOBALS['schema']['permalink']['defaultValue'];
  if     (!$permalinkText)                              { die("You must enter a value for 'permalink'!"); }
  elseif (preg_match("!^/!", $requiredPrefix))          { die("Permalink prefix can not start with a slash! Change the 'Default Value' for permalink field in Field Editor."); }
  elseif ($permalinkText == $requiredPrefix)            { die("You must enter a value for 'permalink' after '" .htmlencode($requiredPrefix). "'!"); }
  elseif (!startsWith($requiredPrefix, $permalinkText)) { die("Permalink must start with '" .htmlencode($requiredPrefix). "'!"); }
  elseif (preg_match("|[^\w\-\./]|i", $permalinkText))  { die("Permalink can only contain these chars (a-z0-9/-.)!"); }
  elseif (preg_match("!^/|/$!", $permalinkText))        { die("Permalink can not start or end with a slash!"); }
  elseif (preg_match("!\.{2,}!", $permalinkText))       { die("Permalink can not include '..'!"); }
  elseif (preg_match("!/{2,}!", $permalinkText))        { die("Permalink can not include '//'!"); }
  elseif ($isAlreadyUsed)                               { die(sprintf("Permalink '%s' is already in use, please choose another!", htmlencode($permalinkText))); }
}

// on save, add permalink to database
// NOTE: We never remove old permalinks, so that old permalinks ALWAYS work (we only erase permalinks when records are removed)
function permalink_cms_onSaveUpdatePermalinks($tableName, $isNewRecord, $oldRecord, $recordNum) {
  if (!array_key_exists('permalink', $GLOBALS['schema'])) { return; } // skip for sections without permalink fields
  if ($tableName == '_permalinks') { return; } // skip when admin is directly editing permalinks table

  // error checking
  permalink_cms_onSaveErrorChecking($tableName, $isNewRecord, $oldRecord);
  
  // add/update permalink
  $errors = permalink_add(@$_REQUEST['permalink'], $tableName, $recordNum);  
  if ($errors) { die($errors); }

}

// on erase, remove permalinks
function permalink_cms_onEraseRemovePermalinks($tableName, $recordNumsAsCSV) {
  if (!array_key_exists('permalink', $GLOBALS['schema'])) { return; } // skip for sections without permalink fields
  if ($tableName == '_permalinks') { return; } // skip when admin is directly editing permalinks table

  $deleteWhere = "`tableName` = '" .mysql_escape($tableName). "' AND recordNum IN ($recordNumsAsCSV)";
  mysql_delete('_permalinks', null, $deleteWhere);
}

// error checking for manual updates to permalinks DB
function permalinkDB_onSaveErrorChecking($tableName, $recordExists, $oldRecord) {
  if ($tableName != '_permalinks')   { return; } // only run for permalinks DB

  // error checking for custom source urls
  if (@$_REQUEST['customSourceUrl'] != '') {
    list($viewerAbsPath, $pathErrors) = _permalink_getAbsolutePath(null, $_REQUEST['customSourceUrl']);
    if ($pathErrors) { die($pathErrors); }
  }
}

// eof
