===============
Application API
===============

The Web Services API is at the component bases a bunch of browser views. The
following is a list of all the calls available via the Web Services API for
Plone (aka wsapi4plone).

 * get_object
 * get_file_object
 * post_object
 * put_object
 * delete_object
 * clipboard (Not Yet Implemented)
 * get_schema
 * get_types
 * get_workflow
 * set_workflow
 * query

This document attempts to cover a very high view of using wsapi4plone. Don't be scared of its length, as most of those lines are output from various calls. :) 

There is an enormous amount of unknown as far as content-types go. Therefore
this document only attempts to covers some of the basic functionality of
dealing with content.

Note About Security and Authentication
--------------------------------------
Security is handled via the restrictedTraverse method.

The Basics
----------
The retrievers in the Application API are mostly wrapped up in two calls
'get_object' and 'query'. We can start by getting the site object with the
'get_object' call.

    >>> print http(r"""
    ... POST /plone HTTP/1.0
    ... Content-Type: text/xml
    ... 
    ... %s
    ... """ % format_xmlrpc('get_object'))
    HTTP/1.0 200 OK
    Content-Length: ...
    Content-Type: text/xml
    <BLANKLINE>
    <?xml version='1.0'?>
    <methodResponse>
    <params>
    <param>
    <value><struct>
    <member>
    <name></name>
    <value><array><data>
    <value><struct>
    <member>
    <name>description</name>
    <value><string></string></value>
    </member>
    <member>
    <name>id</name>
    <value><string>plone</string></value>
    </member>
    <member>
    <name>title</name>
    <value><string>Plone site</string></value>
    </member>
    </struct></value>
    <value><string>Plone Site</string></value>
    <value><struct>
    <member>
    <name>contents</name>
    <value><struct>
    <member>
    <name>/plone/events</name>
    <value><struct>
    ...
    </member>
    ...
    <member>
    <name>/plone/front-page</name>
    <value><struct>
    <member>
    <name>size</name>
    <value><string>4.9 kB</string></value>
    </member>
    <member>
    <name>container</name>
    <value><boolean>0</boolean></value>
    </member>
    <member>
    <name>Description</name>
    <value><string>Congratulations! You have successfully installed Plone.</string></value>
    </member>
    <member>
    <name>EffectiveDate</name>
    <value><string>None</string></value>
    </member>
    <member>
    <name>listCreators</name>
    <value><array><data>
    <value><string>portal_owner</string></value>
    </data></array></value>
    </member>
    <member>
    <name>effective</name>
    <value><dateTime.iso8601>...</dateTime.iso8601></value>
    </member>
    <member>
    <name>Date</name>
    <value><string>...</string></value>
    </member>
    <member>
    <name>expires</name>
    <value><dateTime.iso8601>...</dateTime.iso8601></value>
    </member>
    <member>
    <name>modified</name>
    <value><dateTime.iso8601>...</dateTime.iso8601></value>
    </member>
    <member>
    <name>created</name>
    <value><dateTime.iso8601>...</dateTime.iso8601></value>
    </member>
    <member>
    <name>ModificationDate</name>
    <value><string>...</string></value>
    </member>
    <member>
    <name>Creator</name>
    <value><string>portal_owner</string></value>
    </member>
    <member>
    <name>ExpirationDate</name>
    <value><string>None</string></value>
    </member>
    <member>
    <name>Title</name>
    <value><string>Welcome to Plone</string></value>
    </member>
    <member>
    <name>review_state</name>
    <value><string>published</string></value>
    </member>
    <member>
    <name>CreationDate</name>
    <value><string>...</string></value>
    </member>
    <member>
    <name>Type</name>
    <value><string>Page</string></value>
    </member>
    <member>
    <name>id</name>
    <value><string>front-page</string></value>
    </member>
    <member>
    <name>Subject</name>
    <value><array><data>
    </data></array></value>
    </member>
    </struct></value>
    </member>
    ...
    </struct></value>
    </param>
    </params>
    </methodResponse>

Next we will get a site that does not exist. It should return a 404.

    >>> print http(r"""
    ... POST /nosite HTTP/1.0
    ... Content-Type: text/xml
    ... 
    ... %s
    ... """ % format_xmlrpc('get_object'))
    HTTP/1.0 404 Not Found
    ...

Let's get the front-page object to do a basic test on an 'get_object' call on
some real content.

    >>> print http(r"""
    ... POST /plone HTTP/1.0
    ... Content-Type: text/xml
    ... 
    ... %s
    ... """ % format_xmlrpc('get_object', (['front-page'],)) )
    HTTP/1.0 200 OK
    Content-Length: ...
    Content-Type: text/xml
    <BLANKLINE>
    <?xml version='1.0'?>
    <methodResponse>
    <params>
    <param>
    <value><struct>
    <member>
    <name>front-page</name>
    <value><array><data>
    <value><struct>
    <member>
    <name>description</name>
    <value><string>Congratulations! You have successfully installed Plone.</string></value>
    </member>
    <member>
    <name>contributors</name>
    <value><array><data>
    </data></array></value>
    </member>
    <member>
    <name>text</name>
    <value><string>&lt;p class="discreet"&gt;
    If you're seeing this instead of the web site you were expecting, the owner of
    this web site has just installed Plone. Do not contact the Plone Team 
    or the Plone mailing lists about this.
    &lt;/p&gt;
    ...
    </string></value>
    </member>
    <member>
    <name>subject</name>
    <value><array><data>
    </data></array></value>
    </member>
    <member>
    <name>creation_date</name>
    <value><dateTime.iso8601>...</dateTime.iso8601></value>
    </member>
    <member>
    <name>expirationDate</name>
    <value><nil/></value></member>
    <member>
    <name>tableContents</name>
    <value><boolean>0</boolean></value>
    </member>
    <member>
    <name>id</name>
    <value><string>front-page</string></value>
    </member>
    <member>
    <name>effectiveDate</name>
    <value><nil/></value></member>
    <member>
    <name>creators</name>
    <value><array><data>
    <value><string>portal_owner</string></value>
    </data></array></value>
    </member>
    <member>
    <name>modification_date</name>
    <value><dateTime.iso8601>...</dateTime.iso8601></value>
    </member>
    <member>
    <name>language</name>
    <value><string></string></value>
    </member>
    <member>
    <name>title</name>
    <value><string>Welcome to Plone</string></value>
    </member>
    <member>
    <name>rights</name>
    <value><string></string></value>
    </member>
    <member>
    <name>relatedItems</name>
    <value><array><data>
    </data></array></value>
    </member>
    <member>
    <name>location</name>
    <value><string></string></value>
    </member>
    <member>
    <name>allowDiscussion</name>
    <value><boolean>0</boolean></value>
    </member>
    <member>
    <name>excludeFromNav</name>
    <value><boolean>0</boolean></value>
    </member>
    <member>
    <name>presentation</name>
    <value><boolean>1</boolean></value>
    </member>
    </struct></value>
    <value><string>Document</string></value>
    <value><nil/></value></data></array></value>
    </member>
    </struct></value>
    </param>
    </params>
    </methodResponse>

We will come back to the 'get_object' call when we have other content-type
objects to look at.


Editing Content in the Site
---------------------------

Let's change the front-page object's body text to something short and sweet
using the 'put_object' call (see also it's sister call 'post_object' for
creating content).

    >>> print http("""
    ... POST /plone HTTP/1.0
    ... Content-Type: text/xml
    ... Cookie: %s
    ... 
    ... %s
    ... """ % (self.cookie, format_xmlrpc('put_object', ({'front-page': [{'text': "<p>Action and reaction, ebb and flow, trial and error, change - this is the rhythm of living. Out of our over-confidence, fear; out of our fear, clearer vision, fresh hope. And out of hope, progress.</p><br /> --<i>Bruce Barton</i>"}]},))) )
    HTTP/1.0 200 OK
    Content-Length: 181
    Content-Type: text/xml
    <BLANKLINE>
    <?xml version='1.0'?>
    <methodResponse>
    <params>
    <param>
    <value><array><data>
    <value><string>front-page</string></value>
    </data></array></value>
    </param>
    </params>
    </methodResponse>


Instead of checking the whole object for the results, let's just check on the
attribute we changed. Notice that in this 'get_object' call we are giving a
list of parameters we want the 'get_object' to return. This is a very easy
way of limiting the output of the 'get_object' call.

    >>> print http("""
    ... POST /plone HTTP/1.0
    ... Content-Type: text/xml
    ... 
    ... %s
    ... """ % format_xmlrpc('get_object', (['front-page'],)) )
    HTTP/1.0 200 OK
    Content-Length: ...
    Content-Type: text/xml
    <BLANKLINE>
    <?xml version='1.0'?>
    <methodResponse>
    <params>
    <param>
    <value><struct>
    <member>
    <name>front-page</name>
    <value><array><data>
    <value><struct>
    ...
    <member>
    <name>text</name>
    <value><string>&lt;p&gt;Action and reaction, ebb and flow, trial and error, change - this is the rhythm of living. Out of our over-confidence, fear; out of our fear, clearer vision, fresh hope. And out of hope, progress.&lt;/p&gt;&lt;br /&gt; --&lt;i&gt;Bruce Barton&lt;/i&gt;</string></value>
    </member>
    ...
    </struct></value>
    <value><string>Document</string></value>
    <value><nil/></value></data></array></value>
    </member>
    </struct></value>
    </param>
    </params>
    </methodResponse>

Creating Content in the Site
----------------------------

Let's create some content using the 'post_object' call. This process is the
same for creating any content in the site.

Let's create a folder called folder1. To create objects we use the
'post_object' call. Keep in mind that we must be authenticated in order to
create content.

    >>> parameters = ({'': [{'id': 'folder1',
    ...                      'title': 'Folder One',
    ...                      'description': 'Folder 1 (one)'},
    ...                     'Folder']},)
    >>> print http("""
    ... POST /plone HTTP/1.0
    ... Content-Type: text/xml
    ... Cookie: %s
    ... 
    ... %s
    ... """ % (self.cookie, format_xmlrpc('post_object', parameters)) )
    HTTP/1.0 200 OK
    Content-Length: 178
    Content-Type: text/xml
    <BLANKLINE>
    <?xml version='1.0'?>
    <methodResponse>
    <params>
    <param>
    <value><array><data>
    <value><string>folder1</string></value>
    </data></array></value>
    </param>
    </params>
    </methodResponse>

Now delete the folder we created using the 'delete_object' call.

    >>> print http("""
    ... POST /plone HTTP/1.0
    ... Content-Type: text/xml
    ... Cookie: %s
    ... 
    ... %s
    ... """ % (self.cookie, format_xmlrpc('delete_object', (['folder1'],))) )
    HTTP/1.0 200 OK
    Content-Length: 114
    Content-Type: text/xml
    <BLANKLINE>
    <?xml version='1.0'?>
    <methodResponse>
    <params>
    <param>
    <value><nil/></value></param>
    </params>
    </methodResponse>

What if we wanted to create an object of type 'Link' but didn't know what
fields it has or requires? The 'get_schema' call can return an existing
object's schema or return the schema of a content-type. Let's get the 'Link'
content-type's schema as an example.

    >>> print http("""
    ... POST /plone HTTP/1.0
    ... Content-Type: text/xml
    ... Cookie: %s
    ... 
    ... %s
    ... """ % (self.cookie, format_xmlrpc('get_schema', ('Link',))) )
    HTTP/1.0 200 OK
    Content-Length: 4031
    Content-Type: text/xml
    <BLANKLINE>
    <?xml version='1.0'?>
    <methodResponse>
    <params>
    <param>
    <value><struct>
    <member>
    <name>...</name>
    <value><struct>
    <member>
    <name>required</name>
    <value><boolean>...</boolean></value>
    </member>
    <member>
    <name>type</name>
    <value><string>...</string></value>
    </member>
    </struct></value>
    </member>
    ...
    </methodResponse>