SynchroEdit integration - PHP

From SynchroEdit

Revision as of 09:23, 27 October 2007; WikiAdm (Talk | contribs)
(diff) ←Older revision | Current revision | Newer revision→ (diff)
Jump to: navigation, search

Contents

SynchroEdit integration - PHP

Please note that this document applies to SynchroEdit 0.3.9 and newer only.

Introduction

The main purpose of SynchroEdit is to be a tool as opposed to being an application. As such, focus have been from the get-go to implement it as if it was a part of a bigger picture, a wheel rather than a vehicle. The most prominent utility for this implementation is the SessionProtocol, which gives any application able to communicate over a socket the ability to "order SynchroEdit around."

Examples are available that describe how scripts of various types can handle SynchroEdit, creating sessions, modifying sessions, handling access control and so on. This page will give a brief insight into how to do this yourself. Similar pages are (will be) available describing various languages or dialects, but this document is on PHP.

There is a PHP class (PHP 5 compatible) available here which we will be using throughout this document. We will describe both how to use the synchroedit.php class, and how to use the response service directly. Please note that the synchroedit.php class is also available in the SVN repository and the tarball, in the 'extras' directory.

Getting the synchroedit.php file

  • The file is available for download here. Simply rename it to synchroedit.php.
  • The file is additionally available in the development release of SynchroEdit, both via SVN (http://svn.synchroedit.com/root/branch/dev/extras) and inside the distributed tarball (in the extras/ directory).

In-general good-to-know

  • Your application, whatever it is written in, is referred to as the request server.
  • The service with which your request server is communicating is referred to as the request service or, more often as to not confuse you too much, as SynchroEdit plain and simple.

For each session, there are two distinct identifiers, and it is important to use the right one with the right request.

  1. The "document" is the native identifier for a session. For instance, if the native system was MediaWiki, then the "document" may be "SynchroEdit_integration_-_PHP", presuming you were editing this page via SynchroEdit (which is, at this point, not possible, to clarify).
  2. The "session identifier" is the, well, session identifier, and is abbreviated to "SID." This identifier is the letters "SID" followed by a number. The session identifier is the internal reference to the document, and is there mostly for practical reasons. This is also the filename of the XHTML-ized document on the server in the form [localPath]SID[SID].xhtml.

When a protocol asks for [document], you supply the former. When it asks for [session], you supply the latter.

The all-purpose "you don't make sense" response from the response service (SynchroEdit) is "NAK". It can mean anything from "I don't know which document you're talking about" to "I have no clue what you just said." Other error-responses are sometimes available, such as ISOPEN, the response used when the ABORT or OPEN commands are used upon a session which is already open.

You can make sure that your SynchroEdit server is actually active by telnetting to it on the service port. The service port is defined in the synchroedit.rc file, and defaults to 7962. An example of a functional SynchroEdit response service session might look like this (bold text is user-typed):

kalle@synchro:~$ telnet localhost 7962
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
SynchroEdit 0.3.9 running on synchro
USER root
PASS secret
QUERY
DOCUMENT default
IS SID1 8000 GDAY:DWIN:ACLR:
END 
STATUS SID1
STATUS SID1
DOCUMENT default
AGE 1144958333
USERS
CONTRIBUTORS
DOCSIZE 90
END
INIT testdoc
SESSION SID2
END
OPEN testdoc
HAVE SID2 8002 GDAY:DWIN:ACLR:
END
QUERY
DOCUMENT default
IS SID1 8000 GDAY:DWIN:ACLR:
DOCUMENT testdoc
IS SID2 8002 GDAY:DWIN:ACLR:
END
STATUS SID2
STATUS SID2
DOCUMENT testdoc
AGE 1144958382
USERS
CONTRIBUTORS
DOCSIZE 90
END
SHUTDOWN SID2
ACK
END
QUERY
DOCUMENT default
IS SID1 8000 GDAY:DWIN:ACLR:
END
QUIT
Byebyethen!
Connection closed by foreign host.

The "END" method of concluding statements is sort of like an EOF and should be used as such in handling server responses. Especially if requesting a response which may have multi-line responses, or handling multiple requests simultaneously.

That all said, let's see about getting PHP to do this for us.

PHP features of use

PHP supports socket communication fairly well. We will be using fsockopen, fgets, fwrite and fclose here. Instead of using feof we will be using the server-provided "END" statement whenever we attempt to figure out if a particular request response is concluded.

In the first section, we will go through how to do various things using the synchroedit.php class. In the second section we will do some tinkering on our own.

Section 1 - Using the provided synchroedit.php class

Setting things up

The synchroedit.php file contains two classes; SynchroEdit and SynchroSession. The SynchroSession class depends on an active and connected SynchroEdit instance in all cases. So, the first thing we want to do before accessing SynchroEdit is to include the synchroedit.php file and instantiate that class.

include_once("synchroedit.php");
$mySession = new SynchroEdit();

At this point, we have a SynchroEdit class instantiated, but it has as yet not connected to the service. This is simply a matter of ...

if (!$mySession->connect("localhost", 7962, "root", "secret")) {
    echo "Warning: Failed to connect to response service (#" . $mySession->errno . ": " . $mySession->error . ")";
    exit;
}

The errno and error variables are set to the corresponding error codes and error messages whenever an error occurs. This allows you to act based on the error code if you are serious, or act based on the error message if you are lazy (printing it out to the user, and/or to a log file, or whatnot). Of note also is that there is a short-hand function in both classes called getError() which returns "#ERRNO: ERROR" in that format.

At this point, we're connected and can begin to issue commands.

Getting a list of existing sessions

There are two manners in which we can query the service for a list of existing sessions -- simple and extended query. Extended query means an additional request is made to the service for each existing session, providing us with additional information about each of the sessions (namely age, users, contributors and document size). There is no reason not to use the extended method of querying for sessions unless you don't care about those additional values.

The following line of code would retrieve a simple session query.

$sessions = $mySession->sessions();

And this line would retrieve an extended query.

$sessions = $mySession->sessions(true);

The data is stored in a map like so:

["SID1" => ["DOCUMENT", "PORT", "FLAGS", "AGE", "USERS", "CONTRIBUTORS", "DOCSIZE"],
 "SID2" => ...]

Which means you could step through the existing sessions like so:

reset($sessions);
while (list($sid, $data) = each($sessions)) {
    // $sid is "SID1", $data is a map with values.
}

Finally, the following (complete) script would fetch sessions and print out a list of "session id -> document" on the page.

// Definitions.
define("RS_HOST", "localhost");
define("RS_PORT", 7962);
define("RS_USER", "root");
define("RS_PASS", "secret");

// Need the class file.
include_once("synchroedit.php");

// Instantiate the session.
$mySession = new SynchroEdit(); 

// Connect.
if (!$mySession->connect(RS_HOST, RS_PORT, RS_USER, RS_PASS)) {
    echo "Failed to connect! " . $mySession->getError();
    exit;
}

// Grab sessions.
$sessions = $mySession->sessions(true);
if (!$sessions) {
    echo "Failed to grab sessions! " . $mySession->getError();
    exit;
}

// And print them out.
echo "Current active sessions on " . RS_HOST . ":
Personal tools