SyncCode I3 rpc.php

From MWWiki

Jump to: navigation, search

Back to WordPress Synchronizer

<?php
 
session_start();
 
include_once('common.inc.php');
 
// first, set up the function cache of callables
$cache = array('load', 
               'merge',
               'sync'
               );
 
// initialize the timer
if (!isset($_SESSION['time'])) {
  $_SESSION['time'] = 0;
}
 
// this is where all the magic happens
// might want to do some processing here so the user can't call,
// say, phpinfo() ...
if (in_array($_GET['function'], $cache)) {
  echo $_GET['function']($_GET['argument']);
} else {
  if (!isset($_GET['function'])) {
    echo 'Error!  No argument defined!<br />';
  } else {
    echo 'Error!  Undefined argument "' . $_GET['function'] . '".<br />';
  }
}
 
// ********* FUNCTIONS ***********
 
/**
 * Loads the latest entry from the specified WordRPC handler.
 *
 * The calling script specifies what WordRPC handler is going to process
 * a request for the latest entry the handler is connected to.  Provided
 * the argument provided is valid, this function returns the ID number
 * of the latest entry.
 *
 * @param class object A reference to the WordRPC object being used.
 * @return int The ID of the latest entry.
 */
function load($class) {
  global $$class;
 
  // sanity check
  if (!isset($$class)) {
    return 'Error!  Invalid argument "' . $class . '" provided to function "load()".<br />';
  }
 
  // start the timer
  $retval = "";
  $start = time();
 
  // make the request
  $_SESSION[$class] = $$class->getPostIDs(1);
  if (count($_SESSION[$class]) == 0) {
    $retval = 'Error!  Blog "' . $class . '" returned 0 results!<br />';
  } else {
    $retval = 'RPC successful.  Response from blog "' . $class . '" with ID ' .
              $_SESSION[$class][0]['postid'] . '.<br />';
  }
 
  // stop the timer
  $end = time();
  $_SESSION['time'] += $end - $start;
 
  // a bit of debugging
  $cfg = Config::getInstance();
  if ($cfg->getValue('debug')) {
    fb($retval, 'Return value', FirePHP::LOG);
    fb($_SESSION['time'], 'Current Time Value', FirePHP::LOG);
    fb($_SESSION[$class][0]['postid'], $class . ' Post ID', FirePHP::LOG);
  }
 
  // finish!
  return $retval;
}
 
/**
 * Conglomerates the posts together and creates an HTML form of the post IDs
 * that need to be synchronized to the blog that is lacking posts.
 *
 * @return string An HTML string consisting of the form for RPC to submit the entries.
 */
function merge() {
  // WordRPC objects
  global $local, $remote;
  $retval = "";
 
  // start the timer
  $start = time();
 
  // entry IDs
  $localID = $_SESSION['local'][0]['postid'];
  $remoteID = $_SESSION['remote'][0]['postid'];
 
  // check the entry IDs
  // 1) if they are equal, there's nothing to be done!
  // 2) if they are not equal, some synchronizing needs to happen
  if ($localID == $remoteID) {
    // case 1
    $retval = 'No entries to synchronize!  Both blogs up to date.<br />';
  } else {
    // case 2
    // the blog with the latest entries
    $from = ($localID > $remoteID ? $from = $local : $from = $remote);
 
    // get all the missing posts
    $posts = $from->getPostIDs(abs($localID - $remoteID)); 
    $posts = requestedPosts($posts, $localID, $remoteID);
 
    // make everything in a nice printable format
    $retval = makeReadable($posts);
 
    // debugging
    $cfg = Config::getInstance();
    if ($cfg->getValue('debug')) {
      $numPosts = count($posts);
      fb($numPosts, 'Number of posts', FirePHP::LOG);
      $printable = array();
      for ($i = 0; $i < $numPosts; $i++) {
        $printable[$i] = $posts[$i]['postid'];
      }
      fb($printable, 'Posts', FirePHP::LOG);
      fb($retval, 'Readable format', FirePHP::LOG);
    }
  }
 
  // stop the timer
  $end = time();
  $_SESSION['time'] += $end - $start;
  $retval .= '<b>Operation took ' . $_SESSION['time'] . ' seconds.</b><br />';
  cleanup();
  return $retval;
}
 
/**
 * This method posts all the selected entries via RPC to the blog requiring entry
 * updates.  This is determined by querying both RPC connections for their latest
 * post ID, and the blog with the lesser ID number is considered in need of updating.
 *
 * @return string An HTML string consisting of the results of the RPC submission.
 */
function sync() {
  global $local, $remote;
 
  // first, a little sanity check
  if (!isset($_POST['elements'])) {
    die('No posts found for synchronizing!');
  }
 
  // start the timer
  $start = time();
 
  // set up the blogs
  $localID = $local->getPostIDs(1);
  $remoteID = $remote->getPostIDs(1);
  if ($localID < $remoteID) {
    $to = $local;
    $from = $remote;
  } else {
    $to = $remote;
    $from = $local;
  }
 
  // pick up the entries 
 
  $retval = "";
  $prev = -1;
  for ($i = ($_POST['elements'] - 1); $i >= 0; $i--) {
    $ID = $_POST['id_' . $i];
 
    // do we need a few dummy entries?
    if ($prev > -1 && $prev < ($ID - 1)) {
      $prev = dummyEntries($prev, $ID);
    }
 
    // get the entire post to send
    $entry = $from->getPost($ID);
 
    // submit the post
    $value = $to->newPost($entry);
    if (is_array($value)) {
      die( '<b>Error!</b><br />' . $value['faultCode'] . ': ' .
                                   $value['faultString'] . '<br />');
    }
 
    // print the result
    $retval .= 'Entry ' . $value . ' sent!<br />';
 
    // update the previous counter
    $prev = $entry;
  }
 
  $retval .= '<br /><b>Finished in ' . (time() - $start) . ' seconds! :)</b></br />';
  return $retval;
}
 
/**
 * This function handles looping on creation and deletion of dummy entries,
 * in order to truly have the remote server mirror the local one.  This can
 * be computationally expensive; there will be wait times involved for the user.
 *
 * @param previous An integer indicating the last successful postID synchronized.
 * @param current An integer indicating the current postID waiting to be synchronized.
 * @return An integer indicating the last successful postID - should be (current - 1).
 */
function dummyEntries($previous, $current, $rpc) {
 
  /* loop until we reach our goal */
  while ($previous < ($current - 1)) {
    $struct['post_title'] = "DUMMY";
    $struct['description'] = "DUMMY POST! LOLZ";
 
    /* insert the post */
    $id = $rpc->newPost($struct);
    if (is_array($id)) { /* crap on a stick */
      die( '<b>Error posting dummy entry!</b><br />' . $id['faultCode'] . ': ' .
                                                       $id['faultString'] . '<br />');
    }
    /* update the count */
    $previous = $id;
 
    /* now, delete it */
    $id = $rpc->deletePost($id);
    if (is_array($id)) { /* shucks */
      die( '<b>Error deleting dummy post!</b><br />' . $id['faultCode'] . ': ' .
                                                       $id['faultString'] . '<br />');
    }
 
  } /* end while loop */
 
  /* return the current previous count */
  return $previous;
}
 
/**
 * Unsets all session variables and destroys the current session.
 */
function cleanup() {
  unset($_SESSION['local']);
  unset($_SESSION['remote']);
  unset($_SESSION['time']);
  session_destroy();
}
 
/**
 * Trims the array of entries returned by XMLRPC to only include those entries
 * with IDs between $first and $last.
 *
 * @param $entries array The array of entries (response from XMLRPC)
 * @param $local int The ID corresponding to the last local entry
 * @param $remote int The ID corresponding to the last remote entry
 * @return array A subset of the $entries array: ($first, $last]
 */
function requestedPosts($entries, $local, $remote) {
  $first = $local;
  $last = $remote;
 
  // make sure $first <= $last
  if ($first > $last) {
    $last = $local;
    $first = $remote;
  }
 
  $retval = array();
  $length = count($entries);
  $numElems = 0;
 
  // do the loop
  for ($i = 0; $i < $length; $i++) {
    if ($entries[$i]['postid'] > $first &&
        $entries[$i]['postid'] <= $last) {
      $retval[$numElems++] = $entries[$i];
    }
  }
 
  // finished
  return $retval;
}
 
/**
 * Converts the posts into an HTML form that can be read through AJAX and
 * submitted.
 *
 * @param $posts array The array of posts.
 * @return string The posts in HTML.
 */
function makeReadable($posts) {
  $numPosts = count($posts);
  $retval = '<form action="javascript:POSTrequest(' . $numPosts . ');" ' .
            'method="post"><input type="submit" value="Post Entries" />' . "\n";
  for ($i = 0; $i < $numPosts; $i++) {
    $retval .= '<input type="hidden" name="id_' . $i . '" value="' . 
               $posts[$i]['postid'] . '" />';
    $retval .= '<label>' . date('j M Y, g:ia', $posts[$i]['dateCreated']->timestamp) .
               ' - ';
    $retval .= (isset($posts[$i]['title']) && $posts[$i]['title'] != '' ? 
                htmlentities($posts[$i]['title']) : '<i>[no subject]</i>');
    $retval .= '</label><br />' . "\n";
  }
  $retval .= '</form>';
 
  // finished
  return $retval;
}
?>
Personal tools