Folder Marshalling
==================

Historically, Archetypes only supported marshalling behaviour on
BaseContent-based objects. That made creating folderish objects that
played with WebDAV unnecessarily hard.

The time has come where now the folderish and the non-folderish unite
under the same banner, and play nicely with WebDAV.

  >>> from plone.app.testing import TEST_USER_NAME as user_name
  >>> from plone.app.testing import TEST_USER_PASSWORD as user_password
  >>> portal = layer['portal']
  >>> portal_name = portal.getId()
  >>> from plone.app.testing import setRoles
  >>> from plone.app.testing import TEST_USER_ID
  >>> setRoles(portal, TEST_USER_ID, ['Manager'])

CMF 1.5 returns the id of the created object, CMF 1.4 doesn't ...

  >>> portal.invokeFactory('SimpleFolder', 'simple_folder') in \
  ...                           (None, 'simple_folder')
  True

  >>> portal.invokeFactory('SimpleBTreeFolder', 'simple_btree_folder') \
  ...                           in (None, 'simple_btree_folder')
  True

Make sure we've got some reasonable marshaller setup over there:

  >>> portal.simple_folder.Schema().getLayerImpl('marshall')
  <Products.Archetypes.Marshall.RFC822Marshaller instance at ...>

  >>> portal.simple_btree_folder.Schema().getLayerImpl('marshall')
  <Products.Archetypes.Marshall.RFC822Marshaller instance at ...>

The trick here is that, to keep backwards compatibility, we only
enable the new behaviour on folderish objects that have
``__dav_marshall__`` set to a valid value.

  >>> folder = portal.simple_folder

  >>> from Testing.ZopeTestCase.zopedoctest.functional import http 
  >>> from Testing.ZopeTestCase.sandbox import AppZapper 
  >>> AppZapper().set(layer['app'])
  >>> print http(r"""
  ... PUT /%s/simple_folder HTTP/1.1
  ... Authorization: Basic %s:%s
  ... Content-Type: text/plain; charset="utf-8"
  ... Depth: 0
  ...
  ... description: Simple Folder Content
  ... """ % (portal_name, user_name, user_password))
  HTTP/1.1 405 Method Not Allowed
  ...

  >>> folder.called_afterPUT_hook
  Traceback (most recent call last):
  ...
  AttributeError: called_afterPUT_hook

  >>> print folder.Description()
  <BLANKLINE>

Note that 'GET' will also result in the same response. We simulate a
WebDAV 'GET' by appending 'manage_DAVget' to the target, which is just
about what the 'WebDAVSrcHandler' does:

  >>> print http(r"""
  ... GET /%s/simple_folder/manage_DAVget HTTP/1.1
  ... Authorization: Basic %s:%s
  ... """ % (portal_name, user_name, user_password))
  HTTP/1.1 405 Method Not Allowed
  ...

Then we set ``__dav_marshall__`` to ``True`` and it should behave
like a normal resource:

  >>> folder.__dav_marshall__ = True

  >>> print http(r"""
  ... PUT /%s/simple_folder HTTP/1.1
  ... Authorization: Basic %s:%s
  ... Content-Type: text/plain; charset="utf-8"
  ... Depth: 0
  ...
  ... description: Simple Folder Content
  ... """ % (portal_name, user_name, user_password))
  HTTP/1.1 204 No Content
  ...

  >>> print folder.Description()
  Simple Folder Content
  <BLANKLINE>

  >>> folder.called_afterPUT_hook
  True

  >>> print http(r"""
  ... GET /%s/simple_folder/manage_DAVget HTTP/1.1
  ... Authorization: Basic %s:%s
  ... """ % (portal_name, user_name, user_password))
  HTTP/1.1 200 OK
  ...
  id: simple_folder
  title:
  allowDiscussion: None
  subject:
  description: Simple Folder Content
  location:
  contributors:
  creators: test_user_1_
  effectiveDate: None
  expirationDate: None
  language: en
  rights:
  creation_date: ...
  modification_date: ...

The same for BTreeFolder:

  >>> folder = portal.simple_btree_folder

  >>> print http(r"""
  ... PUT /%s/simple_btree_folder/ HTTP/1.1
  ... Authorization: Basic %s:%s
  ... Content-Type: text/plain; charset="utf-8"
  ... Depth: 0
  ...
  ... description: BTree Folder Content
  ... """ % (portal_name, user_name, user_password))
  HTTP/1.1 405 Method Not Allowed
  ...

  >>> print folder.Description()
  <BLANKLINE>

  >>> folder.called_afterPUT_hook
  Traceback (most recent call last):
  ...
  AttributeError: called_afterPUT_hook

Note that 'GET' will also result in the same response. We simulate a
WebDAV 'GET' by appending 'manage_DAVget' to the target, which is just
about what the 'WebDAVSrcHandler' does:

  >>> print http(r"""
  ... GET /%s/simple_btree_folder/manage_DAVget HTTP/1.1
  ... Authorization: Basic %s:%s
  ... """ % (portal_name, user_name, user_password))
  HTTP/1.1 405 Method Not Allowed
  ...

Then we set ``__dav_marshall__`` to ``True`` and it should behave
like a normal resource:

  >>> folder.__dav_marshall__ = True

  >>> print http(r"""
  ... PUT /%s/simple_btree_folder/ HTTP/1.1
  ... Authorization: Basic %s:%s
  ... Content-Type: text/plain; charset="utf-8"
  ... Depth: 0
  ...
  ... description: BTree Folder Content
  ... """ % (portal_name, user_name, user_password))
  HTTP/1.1 204 No Content
  ...

  >>> print folder.Description()
  BTree Folder Content
  <BLANKLINE>

  >>> folder.called_afterPUT_hook
  True

  >>> print http(r"""
  ... GET /%s/simple_btree_folder/manage_DAVget HTTP/1.1
  ... Authorization: Basic %s:%s
  ... """ % (portal_name, user_name, user_password))
  HTTP/1.1 200 OK
  ...
  id: simple_btree_folder
  title:
  allowDiscussion: None
  subject:
  description: BTree Folder Content
  location:
  contributors:
  creators: test_user_1_
  effectiveDate: None
  expirationDate: None
  language: en
  rights:
  creation_date: ...
  modification_date: ...

  Clean up

  >>> del portal['simple_folder']
  >>> del portal['simple_btree_folder']
  >>> AppZapper().clear()
