You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by ni...@apache.org on 2010/06/13 17:47:25 UTC

svn commit: r954247 - in /incubator/chemistry/trunk/phpclient: README cmis_demo.php cmis_ls.php cmis_mkdir.php cmis_mktextfile.php cmis_query.php cmis_repository_wrapper.php cmis_search.php cmis_test_suite.php

Author: nick
Date: Sun Jun 13 15:47:25 2010
New Revision: 954247

URL: http://svn.apache.org/viewvc?rev=954247&view=rev
Log:
Add PHP Client library now that the IP Clearance has completed

Added:
    incubator/chemistry/trunk/phpclient/README
    incubator/chemistry/trunk/phpclient/cmis_demo.php
    incubator/chemistry/trunk/phpclient/cmis_ls.php
    incubator/chemistry/trunk/phpclient/cmis_mkdir.php
    incubator/chemistry/trunk/phpclient/cmis_mktextfile.php
    incubator/chemistry/trunk/phpclient/cmis_query.php
    incubator/chemistry/trunk/phpclient/cmis_repository_wrapper.php
    incubator/chemistry/trunk/phpclient/cmis_search.php
    incubator/chemistry/trunk/phpclient/cmis_test_suite.php

Added: incubator/chemistry/trunk/phpclient/README
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/phpclient/README?rev=954247&view=auto
==============================================================================
--- incubator/chemistry/trunk/phpclient/README (added)
+++ incubator/chemistry/trunk/phpclient/README Sun Jun 13 15:47:25 2010
@@ -0,0 +1,30 @@
+To Run this example execute the following
+
+php -f cmis_ls.php <rest-endpoint> <username> <password> <folderpath> [debug option 1|2]
+
+Notes:
+ + The if the folder path has spaces in it you must URL encode the folder path i.e. /Data Dictionary --> /Data+Dictionary
+ + The debug option can be omitted. If it is 1 the program will display all of the arrays associated with the objects that
+   are returned.  If the debug option is 2 or more, then the XML returned will also be displayed
+ + This will not work on Pre CMIS-1.0 repositories
+ + There is virtually no error checking.
+ + Your version of php must support DOMDocument and curl
+
+Example Runs
+php -f cmis_ls.php   http://cmis.alfresco.com/service/api/cmis  admin admin /
+php -f cmis_ls.php   http://cmis.alfresco.com/service/api/cmis  admin admin /Data+Dictionary 1
+
+
+The cmis_repository_wrapper.php library provided the following functionality
++ Encapsulates access to a CMIS 1.0 compliant repository
++ Provides utilities for getting information out of:
+  + Workspace (the repositoryInfo)
+  + Object Entries
+  + Non-Hierarchical Object feeds
+
+More information will be on the Wiki for this Google Code Project and on
+the author's blog http://oldschooltechie.com/
+
+
+==============
+Adding Calls that mimick the domain model

Added: incubator/chemistry/trunk/phpclient/cmis_demo.php
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/phpclient/cmis_demo.php?rev=954247&view=auto
==============================================================================
--- incubator/chemistry/trunk/phpclient/cmis_demo.php (added)
+++ incubator/chemistry/trunk/phpclient/cmis_demo.php Sun Jun 13 15:47:25 2010
@@ -0,0 +1,106 @@
+<?php
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require_once ('cmis_repository_wrapper.php');
+function list_objs($objs)
+{
+    foreach ($objs->objectList as $obj)
+    {
+        if ($obj->properties['cmis:baseTypeId'] == "cmis:document")
+        {
+            print "Document: " . $obj->properties['cmis:name'] . "\n";
+        }
+        elseif ($obj->properties['cmis:baseTypeId'] == "cmis:folder")
+        {
+            print "Folder: " . $obj->properties['cmis:name'] . "\n";
+        } else
+        {
+            print "Unknown Object Type: " . $obj->properties['cmis:name'] . "\n";
+        }
+    }
+}
+function check_response($client)
+{
+    if ($client->getLastRequest()->code > 299)
+    {
+        print "There was a problem with this request!\n";
+        exit (255);
+    }
+}
+
+$repo_url = $_SERVER["argv"][1];
+$repo_username = $_SERVER["argv"][2];
+$repo_password = $_SERVER["argv"][3];
+$repo_folder = $_SERVER["argv"][4];
+$repo_new_folder = $_SERVER["argv"][5];
+
+$client = new CMISService($repo_url, $repo_username, $repo_password);
+print "Connected\n";
+$myfolder = $client->getObjectByPath($repo_folder);
+print "Got Folder\n";
+check_response($client);
+if ($myfolder->properties['cmis:baseTypeId'] != "cmis:folder")
+{
+    print "NOT A FOLDER!\n";
+    exit (255);
+}
+
+$my_new_folder = $client->createFolder($myfolder->id, $repo_new_folder);
+check_response($client);
+
+$obj_doc = $client->createDocument($my_new_folder->id, "TextFile.txt", array (), "THIS IS A NEW DOCUMENT", "text/plain");
+check_response($client);
+
+$obj_del = $client->createDocument($my_new_folder->id, "TextFileDel.txt", array (), "THIS IS A NEW DOCUMENT To Be Deleted", "text/plain");
+check_response($client);
+
+print "FOLDER AFTER CREATES\n=============================================\n";
+$objs = $client->getChildren($my_new_folder->id);
+check_response($client);
+list_objs($objs);
+print "=============================================\n\n";
+
+$delContent = $client->getContentStream($obj_del->id);
+echo "DEL CONTENT\n";
+print $delContent . "\n";
+print "\n";
+
+echo "DELETEING " . $obj_del->properties['cmis:name'] . "\n";
+$client->deleteObject($obj_del->id);
+print "\n";
+
+print "FOLDER AFTER DELETE\n=============================================\n";
+$objs = $client->getChildren($my_new_folder->id);
+check_response($client);
+list_objs($objs);
+print "=============================================\n\n";
+
+$sub_folder = $client->createFolder($my_new_folder->id, "SUB_FOLDER");
+$client->moveObject($obj_doc->id, $sub_folder->id, $my_new_folder->id);
+
+print "FOLDER AFTER MOVE\n=============================================\n";
+$objs = $client->getChildren($my_new_folder->id);
+check_response($client);
+list_objs($objs);
+print "=============================================\n\n";
+
+print "SUB-FOLDER AFTER MOVE\n=============================================\n";
+$objs = $client->getChildren($sub_folder->id);
+check_response($client);
+list_objs($objs);
+print "=============================================\n\n";

Added: incubator/chemistry/trunk/phpclient/cmis_ls.php
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/phpclient/cmis_ls.php?rev=954247&view=auto
==============================================================================
--- incubator/chemistry/trunk/phpclient/cmis_ls.php (added)
+++ incubator/chemistry/trunk/phpclient/cmis_ls.php Sun Jun 13 15:47:25 2010
@@ -0,0 +1,70 @@
+<?php
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require_once ('cmis_repository_wrapper.php');
+$repo_url = $_SERVER["argv"][1];
+$repo_username = $_SERVER["argv"][2];
+$repo_password = $_SERVER["argv"][3];
+$repo_folder = $_SERVER["argv"][4];
+$repo_debug = $_SERVER["argv"][5];
+
+$client = new CMISService($repo_url, $repo_username, $repo_password);
+
+if ($repo_debug)
+{
+    print "Repository Information:\n===========================================\n";
+    print_r($client->workspace);
+    print "\n===========================================\n\n";
+}
+
+$myfolder = $client->getObjectByPath($repo_folder);
+if ($repo_debug)
+{
+    print "Folder Object:\n===========================================\n";
+    print_r($myfolder);
+    print "\n===========================================\n\n";
+}
+
+$objs = $client->getChildren($myfolder->id);
+if ($repo_debug)
+{
+    print "Folder Children Objects\n:\n===========================================\n";
+    print_r($objs);
+    print "\n===========================================\n\n";
+}
+
+foreach ($objs->objectList as $obj)
+{
+    if ($obj->properties['cmis:baseTypeId'] == "cmis:document")
+    {
+        print "Document: " . $obj->properties['cmis:name'] . "\n";
+    }
+    elseif ($obj->properties['cmis:baseTypeId'] == "cmis:folder")
+    {
+        print "Folder: " . $obj->properties['cmis:name'] . "\n";
+    } else
+    {
+        print "Unknown Object Type: " . $obj->properties['cmis:name'] . "\n";
+    }
+}
+
+if ($repo_debug > 2)
+{
+    print "Final State of CLient:\n===========================================\n";
+    print_r($client);
+}

Added: incubator/chemistry/trunk/phpclient/cmis_mkdir.php
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/phpclient/cmis_mkdir.php?rev=954247&view=auto
==============================================================================
--- incubator/chemistry/trunk/phpclient/cmis_mkdir.php (added)
+++ incubator/chemistry/trunk/phpclient/cmis_mkdir.php Sun Jun 13 15:47:25 2010
@@ -0,0 +1,79 @@
+<?php
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require_once ('cmis_repository_wrapper.php');
+$repo_url = $_SERVER["argv"][1];
+$repo_username = $_SERVER["argv"][2];
+$repo_password = $_SERVER["argv"][3];
+$repo_folder = $_SERVER["argv"][4];
+$repo_new_folder = $_SERVER["argv"][5];
+$repo_debug = $_SERVER["argv"][6];
+
+$client = new CMISService($repo_url, $repo_username, $repo_password);
+
+if ($repo_debug)
+{
+    print "Repository Information:\n===========================================\n";
+    print_r($client->workspace);
+    print "\n===========================================\n\n";
+}
+
+$myfolder = $client->getObjectByPath($repo_folder);
+if ($repo_debug)
+{
+    print "Folder Object:\n===========================================\n";
+    print_r($myfolder);
+    print "\n===========================================\n\n";
+}
+
+$obs = $client->createFolder($myfolder->id, $repo_new_folder);
+if ($repo_debug)
+{
+    print "Return From Create Folder\n:\n===========================================\n";
+    print_r($objs);
+    print "\n===========================================\n\n";
+}
+
+$objs = $client->getChildren($myfolder->id);
+if ($repo_debug)
+{
+    print "Folder Children Objects\n:\n===========================================\n";
+    print_r($objs);
+    print "\n===========================================\n\n";
+}
+
+foreach ($objs->objectList as $obj)
+{
+    if ($obj->properties['cmis:baseTypeId'] == "cmis:document")
+    {
+        print "Document: " . $obj->properties['cmis:name'] . "\n";
+    }
+    elseif ($obj->properties['cmis:baseTypeId'] == "cmis:folder")
+    {
+        print "Folder: " . $obj->properties['cmis:name'] . "\n";
+    } else
+    {
+        print "Unknown Object Type: " . $obj->properties['cmis:name'] . "\n";
+    }
+}
+
+if ($repo_debug > 2)
+{
+    print "Final State of CLient:\n===========================================\n";
+    print_r($client);
+}

Added: incubator/chemistry/trunk/phpclient/cmis_mktextfile.php
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/phpclient/cmis_mktextfile.php?rev=954247&view=auto
==============================================================================
--- incubator/chemistry/trunk/phpclient/cmis_mktextfile.php (added)
+++ incubator/chemistry/trunk/phpclient/cmis_mktextfile.php Sun Jun 13 15:47:25 2010
@@ -0,0 +1,79 @@
+<?php
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require_once ('cmis_repository_wrapper.php');
+$repo_url = $_SERVER["argv"][1];
+$repo_username = $_SERVER["argv"][2];
+$repo_password = $_SERVER["argv"][3];
+$repo_folder = $_SERVER["argv"][4];
+$repo_new_file = $_SERVER["argv"][5];
+$repo_debug = $_SERVER["argv"][6];
+
+$client = new CMISService($repo_url, $repo_username, $repo_password);
+
+if ($repo_debug)
+{
+    print "Repository Information:\n===========================================\n";
+    print_r($client->workspace);
+    print "\n===========================================\n\n";
+}
+
+$myfolder = $client->getObjectByPath($repo_folder);
+if ($repo_debug)
+{
+    print "Folder Object:\n===========================================\n";
+    print_r($myfolder);
+    print "\n===========================================\n\n";
+}
+
+$obs = $client->createDocument($myfolder->id, $repo_new_file, array (), "THIS IS A NEW DOCUMENT", "text/plain");
+if ($repo_debug)
+{
+    print "Return From Create Document\n:\n===========================================\n";
+    print_r($objs);
+    print "\n===========================================\n\n";
+}
+
+$objs = $client->getChildren($myfolder->id);
+if ($repo_debug)
+{
+    print "Folder Children Objects\n:\n===========================================\n";
+    print_r($objs);
+    print "\n===========================================\n\n";
+}
+
+foreach ($objs->objectList as $obj)
+{
+    if ($obj->properties['cmis:baseTypeId'] == "cmis:document")
+    {
+        print "Document: " . $obj->properties['cmis:name'] . "\n";
+    }
+    elseif ($obj->properties['cmis:baseTypeId'] == "cmis:folder")
+    {
+        print "Folder: " . $obj->properties['cmis:name'] . "\n";
+    } else
+    {
+        print "Unknown Object Type: " . $obj->properties['cmis:name'] . "\n";
+    }
+}
+
+if ($repo_debug > 2)
+{
+    print "Final State of CLient:\n===========================================\n";
+    print_r($client);
+}

Added: incubator/chemistry/trunk/phpclient/cmis_query.php
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/phpclient/cmis_query.php?rev=954247&view=auto
==============================================================================
--- incubator/chemistry/trunk/phpclient/cmis_query.php (added)
+++ incubator/chemistry/trunk/phpclient/cmis_query.php Sun Jun 13 15:47:25 2010
@@ -0,0 +1,61 @@
+<?php
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require_once ('cmis_repository_wrapper.php');
+$repo_url = $_SERVER["argv"][1];
+$repo_username = $_SERVER["argv"][2];
+$repo_password = $_SERVER["argv"][3];
+$repo_debug = $_SERVER["argv"][4];
+
+$client = new CMISService($repo_url, $repo_username, $repo_password);
+
+if ($repo_debug)
+{
+    print "Repository Information:\n===========================================\n";
+    print_r($client->workspace);
+    print "\n===========================================\n\n";
+}
+
+$objs = $client->query("select * from cmis:folder");
+if ($repo_debug)
+{
+    print "Returned Objects\n:\n===========================================\n";
+    print_r($objs);
+    print "\n===========================================\n\n";
+}
+
+foreach ($objs->objectList as $obj)
+{
+    if ($obj->properties['cmis:baseTypeId'] == "cmis:document")
+    {
+        print "Document: " . $obj->properties['cmis:name'] . "\n";
+    }
+    elseif ($obj->properties['cmis:baseTypeId'] == "cmis:folder")
+    {
+        print "Folder: " . $obj->properties['cmis:name'] . "\n";
+    } else
+    {
+        print "Unknown Object Type: " . $obj->properties['cmis:name'] . "\n";
+    }
+}
+
+if ($repo_debug > 2)
+{
+    print "Final State of CLient:\n===========================================\n";
+    print_r($client);
+}

Added: incubator/chemistry/trunk/phpclient/cmis_repository_wrapper.php
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/phpclient/cmis_repository_wrapper.php?rev=954247&view=auto
==============================================================================
--- incubator/chemistry/trunk/phpclient/cmis_repository_wrapper.php (added)
+++ incubator/chemistry/trunk/phpclient/cmis_repository_wrapper.php Sun Jun 13 15:47:25 2010
@@ -0,0 +1,1083 @@
+<?php
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+class CMISRepositoryWrapper
+{
+    // Handles --
+    //   Workspace -- but only endpoints with a single repo
+    //   Entry -- but only for objects
+    //   Feeds -- but only for non-hierarchical feeds
+    // Does not handle --
+    //   -- Hierarchical Feeds
+    //   -- Types
+    //   -- Others?
+    // Only Handles Basic Auth
+    // Very Little Error Checking
+    // Does not work against pre CMIS 1.0 Repos
+    var $url;
+    var $username;
+    var $password;
+    var $authenticated;
+    var $workspace;
+    var $last_request;
+    var $do_not_urlencode;
+    static $namespaces = array (
+        "cmis" => "http://docs.oasis-open.org/ns/cmis/core/200908/",
+        "cmisra" => "http://docs.oasis-open.org/ns/cmis/restatom/200908/",
+        "atom" => "http://www.w3.org/2005/Atom",
+        "app" => "http://www.w3.org/2007/app",
+        
+    );
+
+    function __construct($url, $username = null, $password = null, $options = null)
+    {
+        if (is_array($options) && $options["config:do_not_urlcode"]) {
+            $this->do_not_urlencode=true;
+        }
+        $this->connect($url, $username, $password, $options);
+    }
+
+    static function getOpUrl($url, $options = null)
+    {
+        if (is_array($options) && (count($options) > 0))
+        {
+            $needs_question = strstr($url, "?") === false;
+            return $url . ($needs_question ? "?" : "&") . http_build_query($options);
+        } else
+        {
+            return $url;
+        }
+    }
+
+    function connect($url, $username, $password, $options)
+    {
+        // TODO: Make this work with cookies
+        $this->url = $url;
+        $this->username = $username;
+        $this->password = $password;
+        $this->auth_options = $options;
+        $this->authenticated = false;
+        $retval = $this->doGet($this->url);
+        if ($retval->code == 200 || $retval->code == 201)
+        {
+            $this->authenticated = true;
+            $this->workspace = CMISRepositoryWrapper :: extractWorkspace($retval->body);
+        }
+    }
+
+    function doGet($url)
+    {
+        return $this->doRequest($url);
+    }
+
+    function doDelete($url)
+    {
+        return $this->doRequest($url, "DELETE");
+    }
+
+    function doPost($url, $content, $contentType, $charset = null)
+    {
+        return $this->doRequest($url, "POST", $content, $contentType);
+    }
+
+    function doPut($url, $content, $contentType, $charset = null)
+    {
+        return $this->doRequest($url, "PUT", $content, $contentType);
+    }
+
+    function doRequest($url, $method = "GET", $content = null, $contentType = null, $charset = null)
+    {
+        // Process the HTTP request
+        // 'til now only the GET request has been tested
+        // Does not URL encode any inputs yet
+        if (is_array($this->auth_options))
+        {
+            $url = CMISRepositoryWrapper :: getOpUrl($url, $this->auth_options);
+        }
+        $session = curl_init($url);
+        curl_setopt($session, CURLOPT_HEADER, false);
+        curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
+        if ($this->username)
+        {
+            curl_setopt($session, CURLOPT_USERPWD, $this->username . ":" . $this->password);
+        }
+        curl_setopt($session, CURLOPT_CUSTOMREQUEST, $method);
+        if ($contentType)
+        {
+            $headers = array ();
+            $headers["Content-Type"] = $contentType;
+            curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
+        }
+        if ($content)
+        {
+            curl_setopt($session, CURLOPT_POSTFIELDS, $content);
+        }
+        if ($method == "POST")
+        {
+            curl_setopt($session, CURLOPT_HTTPHEADER, array (
+                "Content-Type: " . $contentType
+            ));
+            curl_setopt($session, CURLOPT_POST, true);
+        }
+        //TODO: Make this storage optional
+        $retval = new stdClass();
+        $retval->url = $url;
+        $retval->method = $method;
+        $retval->content_sent = $content;
+        $retval->content_type_sent = $contentType;
+        $retval->body = curl_exec($session);
+        $retval->code = curl_getinfo($session, CURLINFO_HTTP_CODE);
+        $retval->content_type = curl_getinfo($session, CURLINFO_CONTENT_TYPE);
+        $retval->content_length = curl_getinfo($session, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
+        curl_close($session);
+        $this->last_request = $retval;
+        return $retval;
+    }
+
+    function getLastRequest()
+    {
+        return $this->last_request;
+    }
+
+    function getLastRequestBody()
+    {
+        return $this->last_request->body;
+    }
+
+    function getLastRequestCode()
+    {
+        return $this->last_request->code;
+    }
+
+    function getLastRequestContentType()
+    {
+        return $this->last_request->content_type;
+    }
+
+    function getLastRequestContentLength()
+    {
+        return $this->last_request->content_length;
+    }
+
+    function getLastRequestURL()
+    {
+        return $this->last_request->url;
+    }
+
+    function getLastRequestMethod()
+    {
+        return $this->last_request->method;
+    }
+
+    function getLastRequestContentTypeSent()
+    {
+        return $this->last_request->content_type_sent;
+    }
+
+    function getLastRequestContentSent()
+    {
+        return $this->last_request->content_sent;
+    }
+
+    // Static Utility Functions
+    static function processTemplate($template, $values = array ())
+    {
+        // Fill in the blanks -- 
+        $retval = $template;
+        if (is_array($values))
+        {
+            foreach ($values as $name => $value)
+            {
+                $retval = str_replace("{" . $name . "}", $value, $retval);
+            }
+        }
+        // Fill in any unpoupated variables with ""
+        return preg_replace("/{[a-zA-Z0-9_]+}/", "", $retval);
+
+    }
+
+    static function doXQuery($xmldata, $xquery)
+    {
+        $doc = new DOMDocument();
+        $doc->loadXML($xmldata);
+        return CMISRepositoryWrapper :: doXQueryFromNode($doc, $xquery);
+    }
+
+    static function doXQueryFromNode($xmlnode, $xquery)
+    {
+        // Perform an XQUERY on a NODE
+        // Register the 4 CMIS namespaces
+        $xpath = new DomXPath($xmlnode);
+        foreach (CMISRepositoryWrapper :: $namespaces as $nspre => $nsuri)
+        {
+            $xpath->registerNamespace($nspre, $nsuri);
+        }
+        return $xpath->query($xquery);
+
+    }
+    static function getLinksArray($xmlnode)
+    {
+        // Gets the links of an object or a workspace
+        // Distinguishes between the two "down" links
+        //  -- the children link is put into the associative array with the "down" index
+        //  -- the descendants link is put into the associative array with the "down-tree" index
+        //  These links are distinquished by the mime type attribute, but these are probably the only two links that share the same rel ..
+        //    so this was done as a one off
+        $links = array ();
+        $link_nodes = $xmlnode->getElementsByTagName("link");
+        foreach ($link_nodes as $ln)
+        {
+            if ($ln->attributes->getNamedItem("rel")->nodeValue == "down" && $ln->attributes->getNamedItem("type")->nodeValue == "application/cmistree+xml")
+            {
+                //Descendents and Childredn share same "rel" but different document type
+                $links["down-tree"] = $ln->attributes->getNamedItem("href")->nodeValue;
+            } else
+            {
+                $links[$ln->attributes->getNamedItem("rel")->nodeValue] = $ln->attributes->getNamedItem("href")->nodeValue;
+            }
+        }
+        return $links;
+    }
+    static function extractObject($xmldata)
+    {
+        $doc = new DOMDocument();
+        $doc->loadXML($xmldata);
+        return CMISRepositoryWrapper :: extractObjectFromNode($doc);
+
+    }
+    static function extractObjectFromNode($xmlnode)
+    {
+        // Extracts the contents of an Object and organizes them into:
+        //  -- Links
+        //  -- Properties
+        //  -- the Object ID
+        // RRM -- NEED TO ADD ALLOWABLEACTIONS
+        $retval = new stdClass();
+        $retval->links = CMISRepositoryWrapper :: getLinksArray($xmlnode);
+        $retval->properties = array ();
+        $prop_nodes = $xmlnode->getElementsByTagName("object")->item(0)->getElementsByTagName("properties")->item(0)->childNodes;
+        foreach ($prop_nodes as $pn)
+        {
+            if ($pn->attributes)
+            {
+                $retval->properties[$pn->attributes->getNamedItem("propertyDefinitionId")->nodeValue] = $pn->getElementsByTagName("value")->item(0)->nodeValue;
+            }
+        }
+        $retval->uuid = $xmlnode->getElementsByTagName("id")->item(0)->nodeValue;
+        $retval->id = $retval->properties["cmis:objectId"];
+        return $retval;
+    }
+    
+    function handleSpaces($path)
+    {
+        return $this->do_not_urlencode ? $path : str_replace(" ","%20",str_replace("%","%25",$path));
+    }
+
+    static function extractTypeDef($xmldata)
+    {
+        $doc = new DOMDocument();
+        $doc->loadXML($xmldata);
+        return CMISRepositoryWrapper :: extractTypeDefFromNode($doc);
+
+    }
+    static function extractTypeDefFromNode($xmlnode)
+    {
+        // Extracts the contents of an Object and organizes them into:
+        //  -- Links
+        //  -- Properties
+        //  -- the Object ID
+        // RRM -- NEED TO ADD ALLOWABLEACTIONS
+        $retval = new stdClass();
+        $retval->links = CMISRepositoryWrapper :: getLinksArray($xmlnode);
+        $retval->properties = array ();
+        $retval->attributes = array ();
+        $result = CMISRepositoryWrapper :: doXQueryFromNode($xmlnode, "//cmisra:type/*");
+        foreach ($result as $node)
+        {
+            if ((substr($node->nodeName, 0, 13) == "cmis:property") && (substr($node->nodeName, -10) == "Definition"))
+            {
+                $id = $node->getElementsByTagName("id")->item(0)->nodeValue;
+                $cardinality = $node->getElementsByTagName("cardinality")->item(0)->nodeValue;
+                $propertyType = $node->getElementsByTagName("propertyType")->item(0)->nodeValue;
+                // Stop Gap for now
+                $retval->properties[$id] = array (
+                    "cmis:propertyType" => $propertyType,
+                    "cmis:cardinality" => $cardinality,
+                    
+                );
+            } else
+            {
+                $retval->attributes[$node->nodeName] = $node->nodeValue;
+            }
+            $retval->id = $retval->attributes["cmis:id"];
+        }
+
+        /*
+         * 
+        
+        
+        
+        		$prop_nodes = $xmlnode->getElementsByTagName("object")->item(0)->getElementsByTagName("properties")->item(0)->childNodes;
+        		foreach ($prop_nodes as $pn) {
+        			if ($pn->attributes) {
+        				$retval->properties[$pn->attributes->getNamedItem("propertyDefinitionId")->nodeValue] = $pn->getElementsByTagName("value")->item(0)->nodeValue;
+        			}
+        		}
+                $retval->uuid=$xmlnode->getElementsByTagName("id")->item(0)->nodeValue;
+                $retval->id=$retval->properties["cmis:objectId"];
+         */
+        return $retval;
+    }
+
+    static function extractObjectFeed($xmldata)
+    {
+        //Assumes only one workspace for now
+        $doc = new DOMDocument();
+        $doc->loadXML($xmldata);
+        return CMISRepositoryWrapper :: extractObjectFeedFromNode($doc);
+    }
+    static function extractObjectFeedFromNode($xmlnode)
+    {
+        // Process a feed and extract the objects
+        //   Does not handle hierarchy
+        //   Provides two arrays 
+        //   -- one sequential array (a list)
+        //   -- one hash table indexed by objectID
+        $retval = new stdClass();
+        $retval->objectList = array ();
+        $retval->objectsById = array ();
+        $result = CMISRepositoryWrapper :: doXQueryFromNode($xmlnode, "//atom:entry");
+        foreach ($result as $node)
+        {
+            $obj = CMISRepositoryWrapper :: extractObjectFromNode($node);
+            $retval->objectsById[$obj->id] = $obj;
+            $retval->objectList[] = & $retval->objectsById[$obj->id];
+        }
+        return $retval;
+    }
+
+    static function extractWorkspace($xmldata)
+    {
+        //Assumes only one workspace for now
+        $doc = new DOMDocument();
+        $doc->loadXML($xmldata);
+        return CMISRepositoryWrapper :: extractWorkspaceFromNode($doc);
+    }
+    static function extractWorkspaceFromNode($xmlnode)
+    {
+        // Assumes only one workspace for now
+        // Load up the workspace object with arrays of
+        //  links
+        //  URI Templates
+        //  Collections
+        //  Capabilities
+        //  General Repository Information
+        $retval = new stdClass();
+        $retval->links = CMISRepositoryWrapper :: getLinksArray($xmlnode);
+        $retval->uritemplates = array ();
+        $retval->collections = array ();
+        $retval->capabilities = array ();
+        $retval->repositoryInfo = array ();
+        $result = CMISRepositoryWrapper :: doXQueryFromNode($xmlnode, "//cmisra:uritemplate");
+        foreach ($result as $node)
+        {
+            $retval->uritemplates[$node->getElementsByTagName("type")->item(0)->nodeValue] = $node->getElementsByTagName("template")->item(0)->nodeValue;
+        }
+        $result = CMISRepositoryWrapper :: doXQueryFromNode($xmlnode, "//app:collection");
+        foreach ($result as $node)
+        {
+            $retval->collections[$node->getElementsByTagName("collectionType")->item(0)->nodeValue] = $node->attributes->getNamedItem("href")->nodeValue;
+        }
+        $result = CMISRepositoryWrapper :: doXQueryFromNode($xmlnode, "//cmis:capabilities/*");
+        foreach ($result as $node)
+        {
+            $retval->capabilities[$node->nodeName] = $node->nodeValue;
+        }
+        $result = CMISRepositoryWrapper :: doXQueryFromNode($xmlnode, "//cmisra:repositoryInfo/*");
+        foreach ($result as $node)
+        {
+            if ($node->nodeName != "cmis:capabilities")
+            {
+                $retval->repositoryInfo[$node->nodeName] = $node->nodeValue;
+            }
+        }
+
+        return $retval;
+    }
+}
+
+// Option Contants for Array Indexing
+// -- Generally optional flags that control how much information is returned
+// -- Change log token is an anomoly -- but included in URL as parameter
+define("OPT_MAX_ITEMS", "maxItems");
+define("OPT_SKIP_COUNT", "skipCount");
+define("OPT_FILTER", "filter");
+define("OPT_INCLUDE_PROPERTY_DEFINITIONS", "includePropertyDefinitions");
+define("OPT_INCLUDE_RELATIONSHIPS", "includeRelationships");
+define("OPT_INCLUDE_POLICY_IDS", "includePolicyIds");
+define("OPT_RENDITION_FILTER", "renditionFilter");
+define("OPT_INCLUDE_ACL", "includeACL");
+define("OPT_INCLUDE_ALLOWABLE_ACTIONS", "includeAllowableActions");
+define("OPT_DEPTH", "depth");
+define("OPT_CHANGE_LOG_TOKEN", "changeLogToken");
+
+define("LINK_ALLOWABLE_ACTIONS", "http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions");
+
+define("MIME_ATOM_XML", 'application/atom+xml');
+define("MIME_ATOM_XML_ENTRY", 'application/atom+xml;type=entry');
+define("MIME_ATOM_XML_FEED", 'application/atom+xml;type=feed');
+define("MIME_CMIS_TREE", 'application/cmistree+xml');
+define("MIME_CMIS_QUERY", 'application/cmisquery+xml');
+
+// Many Links have a pattern to them based upon objectId -- but can that be depended upon?
+
+class CMISService extends CMISRepositoryWrapper
+{
+    var $_link_cache;
+    function __construct($url, $username, $password, $options = null)
+    {
+        parent :: __construct($url, $username, $password, $options);
+        $this->_link_cache = array ();
+        $this->_title_cache = array ();
+        $this->_objTypeId_cache = array ();
+        $this->_type_cache = array ();
+    }
+
+    // Utility Methods -- Added Titles
+    // Should refactor to allow for single object	
+    function cacheEntryInfo($obj)
+    {
+        $this->_link_cache[$obj->id] = $obj->links;
+        $this->_title_cache[$obj->id] = $obj->properties["cmis:name"]; // Broad Assumption Here?
+        $this->_objTypeId_cache[$obj->id] = $obj->properties["cmis:objectTypeId"];
+    }
+
+    function cacheFeedInfo($objs)
+    {
+        foreach ($objs->objectList as $obj)
+        {
+            $this->cacheEntryInfo($obj);
+        }
+    }
+
+    function cacheTypeInfo($tDef)
+    {
+        $this->_type_cache[$tDef->id] = $tDef;
+    }
+
+    function getPropertyType($typeId, $propertyId)
+    {
+        if ($this->_type_cache[$typeId])
+        {
+            return $this->_type_cache[$typeId]->properties[$propertyId]["cmis:propertyType"];
+        }
+        $obj = $this->getTypeDefinition($typeId);
+        return $obj->properties[$propertyId]["cmis:propertyType"];
+    }
+
+    function getObjectType($objectId)
+    {
+        if ($this->_objTypeId_cache[$objectId])
+        {
+            return $this->_objTypeId_cache[$objectId];
+        }
+        $obj = $this->getObject($objectId);
+        return $obj->properties["cmis:objectTypeId"];
+    }
+
+    function getTitle($objectId)
+    {
+        if ($this->_title_cache[$objectId])
+        {
+            return $this->_title_cache[$objectId];
+        }
+        $obj = $this->getObject($objectId);
+        return $obj->properties["cmis:name"];
+    }
+    function getLink($objectId, $linkName)
+    {
+        if ($this->_link_cache[$objectId][$linkName])
+        {
+            return $this->_link_cache[$objectId][$linkName];
+        }
+        $obj = $this->getObject($objectId);
+        return $obj->links[$linkName];
+    }
+
+    // Repository Services
+    function getRepositories()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function getRepositoryInfo()
+    {
+        return $this->workspace;
+    }
+
+    function getTypeChildren()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function getTypeDescendants()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function getTypeDefinition($typeId, $options = array ())
+    { // Nice to have
+        $varmap = $options;
+        $varmap["id"] = $typeId;
+        $myURL = $this->processTemplate($this->workspace->uritemplates['typebyid'], $varmap);
+        $ret = $this->doGet($myURL);
+        $obj = $this->extractTypeDef($ret->body);
+        $this->cacheTypeInfo($obj);
+        return $obj;
+    }
+
+    function getObjectTypeDefinition($objectId)
+    { // Nice to have
+        $myURL = $this->getLink($objectId, "describedby");
+        $ret = $this->doGet($myURL);
+        $obj = $this->extractTypeDef($ret->body);
+        $this->cacheTypeInfo($obj);
+        return $obj;
+    }
+    //Navigation Services
+    function getFolderTree()
+    { // Would Be Useful
+        throw Exception("Not Implemented");
+    }
+
+    function getDescendants()
+    { // Nice to have
+        throw Exception("Not Implemented");
+    }
+
+    function getChildren($objectId, $options = array ())
+    {
+        $myURL = $this->getLink($objectId, "down");
+        //TODO: Need GenURLQueryString Utility
+        $ret = $this->doGet($myURL);
+        $objs = $this->extractObjectFeed($ret->body);
+        $this->cacheFeedInfo($objs);
+        return $objs;
+    }
+
+    function getFolderParent($objectId, $options = array ())
+    { //yes
+        $myURL = $this->getLink($objectId, "up");
+        //TODO: Need GenURLQueryString Utility
+        $ret = $this->doGet($myURL);
+        $obj = $this->extractObjectEntry($ret->body);
+        $this->cacheEntryInfo($obj);
+        return $obj;
+    }
+
+    function getObjectParents($objectId, $options = array ())
+    { // yes
+        $myURL = $this->getLink($objectId, "up");
+        //TODO: Need GenURLQueryString Utility
+        $ret = $this->doGet($myURL);
+        $objs = $this->extractObjectFeed($ret->body);
+        $this->cacheFeedInfo($objs);
+        return $objs;
+    }
+
+    function getCheckedOutDocs($options = array ())
+    {
+        $obj_url = $this->workspace->collections['checkedout'];
+        $ret = $this->doGet($obj_url);
+        $objs = $this->extractObjectFeed($ret->body);
+        $this->cacheFeedInfo($objs);
+        return $objs;
+    }
+
+    //Discovery Services
+
+    static function getQueryTemplate()
+    {
+        ob_start();
+        echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' . "\n";
+?>
+<cmis:query xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/"
+xmlns:cmism="http://docs.oasis-open.org/ns/cmis/messaging/200908/"
+xmlns:atom="http://www.w3.org/2005/Atom"
+xmlns:app="http://www.w3.org/2007/app"
+xmlns:cmisra="http://docs.oasisopen.org/ns/cmis/restatom/200908/">
+<cmis:statement>{q}</cmis:statement>
+<cmis:searchAllVersions>{searchAllVersions}</cmis:searchAllVersions>
+<cmis:includeAllowableActions>{includeAllowableActions}</cmis:includeAllowableActions>
+<cmis:includeRelationships>{includeRelationships}</cmis:includeRelationships>
+<cmis:renditionFilter>{renditionFilter}</cmis:renditionFilter>
+<cmis:maxItems>{maxItems}</cmis:maxItems>
+<cmis:skipCount>{skipCount}</cmis:skipCount>
+</cmis:query>
+<?
+
+        return ob_get_clean();
+    }
+    function query($q, $options = array ())
+    {
+        static $query_template;
+        if (!isset ($query_template))
+        {
+            $query_template = CMISService :: getQueryTemplate();
+        }
+        $hash_values = $options;
+        $hash_values['q'] = $q;
+        $post_value = CMISRepositoryWrapper :: processTemplate($query_template, $hash_values);
+        $ret = $this->doPost($this->workspace->collections['query'], $post_value, MIME_CMIS_QUERY);
+        $objs = $this->extractObjectFeed($ret->body);
+        $this->cacheFeedInfo($objs);
+        return $objs;
+    }
+
+    function getContentChanges()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    //Object Services
+    static function getEntryTemplate()
+    {
+        ob_start();
+        echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' . "\n";
+?>
+<atom:entry xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/"
+xmlns:cmism="http://docs.oasis-open.org/ns/cmis/messaging/200908/"
+xmlns:atom="http://www.w3.org/2005/Atom"
+xmlns:app="http://www.w3.org/2007/app"
+xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">
+<atom:title>{title}</atom:title>
+{SUMMARY}
+{CONTENT}
+<cmisra:object><cmis:properties>{PROPERTIES}</cmis:properties></cmisra:object>
+</atom:entry>
+<?
+
+        return ob_get_clean();
+    }
+
+    static function getPropertyTemplate()
+    {
+        ob_start();
+?>
+		<cmis:property{propertyType} propertyDefinitionId="{propertyId}">
+			<cmis:value>{properties}</cmis:value>
+		</cmis:property{propertyType}>
+<?
+
+        return ob_get_clean();
+    }
+
+    function processPropertyTemplates($objectType, $propMap)
+    {
+        static $propTemplate;
+        static $propertyTypeMap;
+        if (!isset ($propTemplate))
+        {
+            $propTemplate = CMISService :: getPropertyTemplate();
+        }
+        if (!isset ($propertyTypeMap))
+        { // Not sure if I need to do this like this
+            $propertyTypeMap = array (
+                "integer" => "Integer",
+                "boolean" => "Boolean",
+                "datetime" => "DateTime",
+                "decimal" => "Decimal",
+                "html" => "Html",
+                "id" => "Id",
+                "string" => "String",
+                "url" => "Url",
+                "xml" => "Xml",
+                
+            );
+        }
+        $propertyContent = "";
+        $hash_values = array ();
+        foreach ($propMap as $propId => $propValue)
+        {
+            $hash_values['propertyType'] = $propertyTypeMap[$this->getPropertyType($objectType, $propId)];
+            $hash_values['propertyId'] = $propId;
+            if (is_array($propValue))
+            {
+                $first_one = true;
+                $hash_values['properties'] = "";
+                foreach ($propValue as $val)
+                {
+                    //This is a bit of a hack
+                    if ($first_one)
+                    {
+                        $first_one = false;
+                    } else
+                    {
+                        $hash_values['properties'] .= "</cmis:values>\n<cmis:values>";
+                    }
+                    $hash_values['properties'] .= $val;
+                }
+            } else
+            {
+                $hash_values['properties'] = $propValue;
+            }
+            //echo "HASH:\n";
+            //print_r(array("template" =>$propTemplate, "Hash" => $hash_values));
+            $propertyContent .= CMISRepositoryWrapper :: processTemplate($propTemplate, $hash_values);
+        }
+        return $propertyContent;
+    }
+
+    static function getContentEntry($content, $content_type = "application/octet-stream")
+    {
+        static $contentTemplate;
+        if (!isset ($contentTemplate))
+        {
+            $contentTemplate = CMISService :: getContentTemplate();
+        }
+        if ($content)
+        {
+            return CMISRepositoryWrapper :: processTemplate($contentTemplate, array (
+                "content" => base64_encode($content
+            ), "content_type" => $content_type));
+        } else
+        {
+            return "";
+        }
+    }
+
+    static function getSummaryTemplate()
+    {
+        ob_start();
+?>
+		<atom:summary>{summary}</atom:summary>
+<?
+
+        return ob_get_clean();
+    }
+
+    static function getContentTemplate()
+    {
+        ob_start();
+?>
+		<cmisra:content>
+			<cmisra:mediatype>
+				{content_type}
+			</cmisra:mediatype>
+			<cmisra:base64>
+				{content}
+			</cmisra:base64>
+		</cmisra:content>
+<?
+
+        return ob_get_clean();
+    }
+    static function createAtomEntry($name, $properties)
+    {
+
+    }
+    function getObject($objectId, $options = array ())
+    {
+        $varmap = $options;
+        $varmap["id"] = $objectId;
+        $obj_url = $this->processTemplate($this->workspace->uritemplates['objectbyid'], $varmap);
+        $ret = $this->doGet($obj_url);
+        $obj = $this->extractObject($ret->body);
+        $this->cacheEntryInfo($obj);
+        return $obj;
+    }
+
+    function getObjectByPath($path, $options = array ())
+    {
+        $varmap = $options;
+        $varmap["path"] = $this->handleSpaces($path);
+        $obj_url = $this->processTemplate($this->workspace->uritemplates['objectbypath'], $varmap);
+        $ret = $this->doGet($obj_url);
+        $obj = $this->extractObject($ret->body);
+        $this->cacheEntryInfo($obj);
+        return $obj;
+    }
+
+    function getProperties($objectId, $options = array ())
+    {
+        // May need to set the options array default -- 
+        return $this->getObject($objectId, $options);
+    }
+
+    function getAllowableActions($objectId, $options = array ())
+    {
+        // get stripped down version of object (for the links) and then get the allowable actions?
+        // Low priority -- can get all information when getting object
+        throw Exception("Not Implemented");
+    }
+
+    function getRenditions($objectId, $options = array (
+        OPT_RENDITION_FILTER => "*"
+    ))
+    {
+        return getObject($objectId, $options);
+    }
+
+    function getContentStream($objectId, $options = array ())
+    { // Yes
+        $myURL = $this->getLink($objectId, "edit-media");
+        $ret = $this->doGet($myURL);
+        // doRequest stores the last request information in this object
+        return $ret->body;
+    }
+
+    function postObject($folderId, $objectName, $objectType, $properties = array (), $content = null, $content_type = "application/octet-stream", $options = array ())
+    { // Yes
+        $myURL = $this->getLink($folderId, "down");
+        // TODO: Need Proper Query String Handling
+        // Assumes that the 'down' link does not have a querystring in it
+        $myURL = CMISRepositoryWrapper :: getOpUrl($myURL, $options);
+        static $entry_template;
+        if (!isset ($entry_template))
+        {
+            $entry_template = CMISService :: getEntryTemplate();
+        }
+        if (is_array($properties))
+        {
+            $hash_values = $properties;
+        } else
+        {
+            $hash_values = array ();
+        }
+        if (!isset ($hash_values["cmis:objectTypeId"]))
+        {
+            $hash_values["cmis:objectTypeId"] = $objectType;
+        }
+        $properties_xml = $this->processPropertyTemplates($objectType, $hash_values);
+        if (is_array($options))
+        {
+            $hash_values = $options;
+        } else
+        {
+            $hash_values = array ();
+        }
+        $hash_values["PROPERTIES"] = $properties_xml;
+        $hash_values["SUMMARY"] = CMISService :: getSummaryTemplate();
+        if ($content)
+        {
+            $hash_values["CONTENT"] = CMISService :: getContentEntry($content, $content_type);
+        }
+        if (!isset ($hash_values['title']))
+        {
+            $hash_values['title'] = $objectName;
+        }
+        if (!isset ($hash_values['summary']))
+        {
+            $hash_values['summary'] = $objectName;
+        }
+        $post_value = CMISRepositoryWrapper :: processTemplate($entry_template, $hash_values);
+        $ret = $this->doPost($myURL, $post_value, MIME_ATOM_XML_ENTRY);
+        // print "DO_POST\n";
+        // print_r($ret);
+        $obj = $this->extractObject($ret->body);
+        $this->cacheEntryInfo($obj);
+        return $obj;
+    }
+
+    function createDocument($folderId, $fileName, $properties = array (), $content = null, $content_type = "application/octet-stream", $options = array ())
+    { // Yes
+        return $this->postObject($folderId, $fileName, "cmis:document", $properties, $content, $content_type, $options);
+    }
+
+    function createDocumentFromSource()
+    { //Yes?
+        throw Exception("Not Implemented in This Binding");
+    }
+
+    function createFolder($folderId, $folderName, $properties = array (), $options = array ())
+    { // Yes
+        return $this->postObject($folderId, $folderName, "cmis:folder", $properties, null, null, $options);
+    }
+
+    function createRelationship()
+    { // Not in first Release
+        throw Exception("Not Implemented");
+    }
+
+    function createPolicy()
+    { // Not in first Release
+        throw Exception("Not Implemented");
+    }
+
+    function updateProperties($objectId, $properties = array (), $options = array ())
+    { // Yes
+        $varmap = $options;
+        $varmap["id"] = $objectId;
+        $objectName = $this->getTitle($objectId);
+        $objectType = $this->getObjectType($objectId);
+        $obj_url = $this->getLink($objectId, "edit");
+        $obj_url = CMISRepositoryWrapper :: getOpUrl($obj_url, $options);
+        static $entry_template;
+        if (!isset ($entry_template))
+        {
+            $entry_template = CMISService :: getEntryTemplate();
+        }
+        if (is_array($properties))
+        {
+            $hash_values = $properties;
+        } else
+        {
+            $hash_values = array ();
+        }
+        $properties_xml = $this->processPropertyTemplates($objectType, $hash_values);
+        if (is_array($options))
+        {
+            $hash_values = $options;
+        } else
+        {
+            $hash_values = array ();
+        }
+        $hash_values["PROPERTIES"] = $properties_xml;
+        $hash_values["SUMMARY"] = CMISService :: getSummaryTemplate();
+        if (!isset ($hash_values['title']))
+        {
+            $hash_values['title'] = $objectName;
+        }
+        if (!isset ($hash_values['summary']))
+        {
+            $hash_values['summary'] = $objectName;
+        }
+        $put_value = CMISRepositoryWrapper :: processTemplate($entry_template, $hash_values);
+        $ret = $this->doPut($obj_url, $put_value, MIME_ATOM_XML_ENTRY);
+        $obj = $this->extractObject($ret->body);
+        $this->cacheEntryInfo($obj);
+        return $obj;
+    }
+
+    function moveObject($objectId, $targetFolderId, $sourceFolderId, $options = array ())
+    { //yes
+        $options['sourceFolderId'] = $sourceFolderId;
+        return $this->postObject($targetFolderId, $this->getTitle($objectId), $this->getObjectType($objectId), array (
+            "cmis:objectId" => $objectId
+        ), null, null, $options);
+    }
+
+    function deleteObject($objectId, $options = array ())
+    { //Yes
+        $varmap = $options;
+        $varmap["id"] = $objectId;
+        $obj_url = $this->getLink($objectId, "edit");
+        $ret = $this->doDelete($obj_url);
+        return;
+    }
+
+    function deleteTree()
+    { // Nice to have
+        throw Exception("Not Implemented");
+    }
+
+    function setContentStream($objectId, $content, $content_type, $options = array ())
+    { //Yes
+        $myURL = $this->getLink($objectId, "edit-media");
+        $ret = $this->doPut($myURL, $content, $content_type);
+    }
+
+    function deleteContentStream($objectId, $options = array ())
+    { //yes
+        $myURL = $this->getLink($objectId, "edit-media");
+        $ret = $this->doDelete($myURL);
+        return;
+    }
+
+    //Versioning Services
+    function getPropertiesOfLatestVersion($objectId, $options = array ())
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function getObjectOfLatestVersion($objectId, $options = array ())
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function getAllVersions()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function checkOut()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function checkIn()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function cancelCheckOut()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function deleteAllVersions()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    //Relationship Services
+    function getObjectRelationships()
+    {
+        // get stripped down version of object (for the links) and then get the relationships?
+        // Low priority -- can get all information when getting object
+        throw Exception("Not Implemented");
+    }
+
+    //Multi-Filing Services
+    function addObjectToFolder()
+    { // Probably
+        throw Exception("Not Implemented");
+    }
+
+    function removeObjectFromFolder()
+    { //Probably
+        throw Exception("Not Implemented");
+    }
+
+    //Policy Services
+    function getAppliedPolicies()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function applyPolicy()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function removePolicy()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    //ACL Services
+    function getACL()
+    {
+        throw Exception("Not Implemented");
+    }
+
+    function applyACL()
+    {
+        throw Exception("Not Implemented");
+    }
+}

Added: incubator/chemistry/trunk/phpclient/cmis_search.php
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/phpclient/cmis_search.php?rev=954247&view=auto
==============================================================================
--- incubator/chemistry/trunk/phpclient/cmis_search.php (added)
+++ incubator/chemistry/trunk/phpclient/cmis_search.php Sun Jun 13 15:47:25 2010
@@ -0,0 +1,53 @@
+<?php
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require_once ('cmis_repository_wrapper.php');
+$repo_url = $_SERVER["argv"][1];
+$repo_username = $_SERVER["argv"][2];
+$repo_password = $_SERVER["argv"][3];
+$repo_search_text = $_SERVER["argv"][4];
+$repo_debug = $_SERVER["argv"][5];
+
+$client = new CMISService($repo_url, $repo_username, $repo_password);
+
+if ($repo_debug)
+{
+    print "Repository Information:\n===========================================\n";
+    print_r($client->workspace);
+    print "\n===========================================\n\n";
+}
+
+$query = sprintf("SELECT cmis:name,score() as rel from cmis:document WHERE CONTAINS('%s')", $repo_search_text);
+$objs = $client->query($query);
+if ($repo_debug)
+{
+    print "Returned Objects\n:\n===========================================\n";
+    print_r($objs);
+    print "\n===========================================\n\n";
+}
+
+foreach ($objs->objectList as $obj)
+{
+    print "Document: " . $obj->properties['cmis:name'] . "\n";
+}
+
+if ($repo_debug > 2)
+{
+    print "Final State of CLient:\n===========================================\n";
+    print_r($client);
+}

Added: incubator/chemistry/trunk/phpclient/cmis_test_suite.php
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/phpclient/cmis_test_suite.php?rev=954247&view=auto
==============================================================================
--- incubator/chemistry/trunk/phpclient/cmis_test_suite.php (added)
+++ incubator/chemistry/trunk/phpclient/cmis_test_suite.php Sun Jun 13 15:47:25 2010
@@ -0,0 +1,149 @@
+<?php
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require_once ('cmis_repository_wrapper.php');
+$repo_url = $_SERVER["argv"][1];
+$repo_username = $_SERVER["argv"][2];
+$repo_password = $_SERVER["argv"][3];
+$repo_folder = $_SERVER["argv"][4];
+$repo_new_folder = $_SERVER["argv"][5];
+$repo_debug = $_SERVER["argv"][6];
+
+if ($repo_username == "alf_ticket")
+{
+    $client = new CMISService($repo_url, null, null, array (
+        $repo_username => $repo_password
+    ));
+} else
+{
+    $client = new CMISService($repo_url, $repo_username, $repo_password);
+}
+
+if ($repo_debug)
+{
+    print "Repository Information:\n===========================================\n";
+    print_r($client->workspace);
+    print "\n===========================================\n\n";
+}
+
+$myfolder = $client->getObjectByPath($repo_folder);
+print_r($client->getLastRequest());
+if ($repo_debug)
+{
+    print "Folder Object:\n===========================================\n";
+    print_r($myfolder);
+    print "\n===========================================\n\n";
+}
+
+$myfolderType = $client->getObjectTypeDefinition($myfolder->id);
+print_r($client->getLastRequest());
+if ($repo_debug)
+{
+    print "Folder Type Def:\n===========================================\n";
+    print_r($myfolderType);
+    print "\n===========================================\n\n";
+}
+
+$my_new_folder = $client->createFolder($myfolder->id, $repo_new_folder);
+print_r($client->getLastRequest());
+if ($repo_debug)
+{
+    print "Return From Create Folder\n:\n===========================================\n";
+    print_r($my_new_folder);
+    print "\n===========================================\n\n";
+}
+
+$obj_doc = $client->createDocument($my_new_folder->id, "TextFile.txt", array (), "THIS IS A NEW DOCUMENT", "text/plain");
+print_r($client->getLastRequest());
+if ($repo_debug)
+{
+    print "Return From Create Document\n:\n===========================================\n";
+    print_r($obj_doc);
+    print "\n===========================================\n\n";
+}
+
+$obj_del = $client->createDocument($my_new_folder->id, "TextFileDel.txt", array (), "THIS IS A NEW DOCUMENT To Be Deleted", "text/plain");
+if ($repo_debug)
+{
+    print "Return From Create Document\n:\n===========================================\n";
+    print_r($obj_del);
+    print "\n===========================================\n\n";
+}
+
+$objs = $client->getChildren($my_new_folder->id);
+if ($repo_debug)
+{
+    print "Folder Children Objects\n:\n===========================================\n";
+    print_r($objs);
+    print "\n===========================================\n\n";
+}
+
+foreach ($objs->objectList as $obj)
+{
+    if ($obj->properties['cmis:baseTypeId'] == "cmis:document")
+    {
+        print "Document: " . $obj->properties['cmis:name'] . "\n";
+    }
+    elseif ($obj->properties['cmis:baseTypeId'] == "cmis:folder")
+    {
+        print "Folder: " . $obj->properties['cmis:name'] . "\n";
+    } else
+    {
+        print "Unknown Object Type: " . $obj->properties['cmis:name'] . "\n";
+    }
+}
+
+$delContent = $client->getContentStream($obj_del->id);
+echo "DEL CONTENT\n";
+print $delContent . "\n";
+
+echo "DELETEING " . $obj_del->properties['cmis:name'] . "\n";
+$client->deleteObject($obj_del->id);
+$sub_folder = $client->createFolder($my_new_folder->id, "SUB_FOLDER");
+$client->moveObject($obj_doc->id, $sub_folder->id, $my_new_folder->id);
+print "MOVE REQUEST\n=============================================\n";
+print_r($client->getLastRequest());
+
+$objs = $client->getChildren($my_new_folder->id);
+if ($repo_debug)
+{
+    print "Folder Children Objects\n:\n===========================================\n";
+    print_r($objs);
+    print "\n===========================================\n\n";
+}
+
+foreach ($objs->objectList as $obj)
+{
+    if ($obj->properties['cmis:baseTypeId'] == "cmis:document")
+    {
+        print "Document: " . $obj->properties['cmis:name'] . "\n";
+    }
+    elseif ($obj->properties['cmis:baseTypeId'] == "cmis:folder")
+    {
+        print "Folder: " . $obj->properties['cmis:name'] . "\n";
+    } else
+    {
+        print "Unknown Object Type: " . $obj->properties['cmis:name'] . "\n";
+    }
+}
+
+if ($repo_debug > 2)
+{
+    print "Final State of CLient:\n===========================================\n";
+    print_r($client);
+}