Demonstrating using the save content adapter.

 - add adapter
 
 - select adapter

 - test adapter with all fields
 
 - test adapter with(out) avoiding security checks

 - test with creating different content types

 - event triggering

Being a doctest, we can tell a story here.

First, we must perform some setup. We use the testbrowser that is shipped
with Five, as this provides proper Zope 2 integration. Most of the 
documentation, though, is in the underlying zope.testbrower package.

    >>> from Products.Five.testbrowser import Browser
    >>> browser = Browser()
    >>> browser.handleErrors = False
    >>> portal_url = self.portal.absolute_url()

The following is useful when writing and debugging testbrowser tests. It lets
us see all error messages in the error_log.

    >>> self.portal.error_log._ignored_exceptions = ()

With that in place, we can go to the portal front page and log in. We will
do this using the default user from PloneTestCase:

    >>> from Products.PloneTestCase.setup import portal_owner, default_password
    >>> browser.open(portal_url + '/login')

We have the login portlet, so let's use that.

    >>> browser.getControl(name='__ac_name').value = portal_owner
    >>> browser.getControl(name='__ac_password').value = default_password
    >>> browser.getControl(name='submit').click()

And we ensure that we get the friendly logged-in message:

    >>> "You are now logged in" in browser.contents
    True
      
Add the form

  >>> browser.open(self.portal.absolute_url())
  >>> browser.getLink('Form Folder').click()
  >>> browser.getControl(name="title").value = "test-form"
  >>> browser.getControl(name="actionAdapter:list").value = []
  >>> browser.getControl("Save").click()
  >>> form = self.portal['test-form']
  

Add the adapter

  >>> browser.getLink('Save Data to Content Adapter').click()
  >>> browser.getControl(name="title").value = 'results'
  >>> browser.getControl(name="dynamicTitle").value = 'string:hello this is my title'
  >>> browser.getControl(name="form.button.save").click()

Enable the adapter

  >>> browser.getLink(text="test-form").click()
  >>> browser.getLink(text="Edit").click()
  >>> browser.getControl(name="actionAdapter:list").value = ['results']
  >>> browser.getControl("Save").click()
  >>> adapter = form['results']
  
  
Now, we'll add all interesting fields to the form.

Checkbox

  >>> browser.open(form.absolute_url())
  >>> browser.getLink(text="Checkbox Field").click()
  >>> browser.getControl(name="title").value = 'checkbox'
  >>> browser.getControl("Save").click()
  
Date/Time

  >>> browser.open(form.absolute_url())
  >>> browser.getLink(text="Date/Time Field").click()
  >>> browser.getControl(name="title").value = 'datetime'
  >>> browser.getControl("Save").click()
  
Decimal Number
  
  >>> browser.open(form.absolute_url())
  >>> browser.getLink(text="Decimal Number Field").click()
  >>> browser.getControl(name="title").value = 'decimal'
  >>> browser.getControl("Save").click()
  
Lines Field

  >>> browser.open(form.absolute_url())
  >>> browser.getLink(text="Lines Field").click()
  >>> browser.getControl(name="title").value = 'lines'
  >>> browser.getControl("Save").click()
  
Password

  >>> browser.open(form.absolute_url())
  >>> browser.getLink(text="Password Field").click()
  >>> browser.getControl(name="title").value = 'password'
  >>> browser.getControl("Save").click()
  
Rating

  >>> browser.open(form.absolute_url())
  >>> browser.getLink(text="Rating-Scale Field").click()
  >>> browser.getControl(name="title").value = 'rating'
  >>> browser.getControl("Save").click()
  
Selection Field

  >>> browser.open(form.absolute_url())
  >>> browser.getLink(text="Selection Field").click()
  >>> browser.getControl(name="title").value = 'selection'
  >>> browser.getControl(name="fgVocabulary:lines").value = 'one\ntwo\nthree'
  >>> browser.getControl("Save").click()
  

Fill out the fields and make sure they get saved.

  >>> browser.open(form.absolute_url())
  >>> browser.getLink(text="test-form").click()
  >>> browser.getLink(text="View").click()
  
  >>> browser.getControl(name="replyto").value = "foo@bar.com"
  >>> browser.getControl(name="topic").value = "Hello"
  >>> browser.getControl(name="comments").value = "This is awesome."
  >>> browser.getControl(name="checkbox:boolean").value = True
  
  >>> browser.getControl(name="datetime_year").value = ['2010']
  >>> browser.getControl(name="datetime_month").value = ['01']
  >>> browser.getControl(name="datetime_day").value = ['01']
  >>> browser.getControl(name="datetime_hour").value = ['01']
  >>> browser.getControl(name="datetime_minute").value = ['00']
  >>> browser.getControl(name="datetime_ampm").value = ['PM']

  >>> browser.getControl(name="decimal").value = "1.0"
  >>> browser.getControl(name="lines:lines").value = "hello"
  >>> browser.getControl(name="password").value = "mypassword"
  
  >>> browser.getControl(name="rating.1:record").value = ['Strongly disagree']
  >>> browser.getControl(name="rating.2:record").value = ['Strongly agree']
  
  >>> browser.getControl(name="selection").value = ["one"]
  
  >>> browser.getControl("Submit").click()
  

Check that the results were saved and go to them.

  >>> len(adapter.objectIds()) == 1
  True
  
  >>> result = adapter.values()[0]
  >>> browser.open(result.absolute_url())
  
  >>> 'foo@bar.com' in browser.contents
  True
  
  >>> 'Hello' in browser.contents
  True
  
  >>> 'This is awesome.' in browser.contents
  True
  
  >>> 'hello this is my title' in browser.contents
  True
  
  >>> schema = result.Schema()
  >>> schema.get('rating').get(result)
  {'1': 'Strongly disagree', '2': 'Strongly agree'}
  

Now let's make the form public and make sure it still creates the result when
not logged in.

  >>> browser.open(form.absolute_url())
  >>> browser.getLink('Publish').click()
  >>> browser.open(self.portal.absolute_url() + '/logout')
  
  >>> browser.open(form.absolute_url())
  >>> browser.getControl(name="replyto").value = "foo1@bar1.com"
  >>> browser.getControl(name="topic").value = "Hello Again"
  >>> browser.getControl(name="comments").value = "This is cool."
  >>> browser.getControl("Submit").click()
  
  >>> len(adapter.objectIds()) == 2
  True
  
  
let's login and make the adapter not avoid security permissions
  
  >>> browser.open(portal_url + '/login')
  >>> browser.getControl(name='__ac_name').value = portal_owner
  >>> browser.getControl(name='__ac_password').value = default_password
  >>> browser.getControl(name='submit').click()
  
  >>> browser.open(adapter.absolute_url())
  >>> browser.getLink("Edit").click()
  >>> browser.getControl(name="avoidSecurityChecks:boolean").value = None
  >>> browser.getControl(name="form.button.save").click()
  
  
We'll log out again and try submitting the form.

  >>> browser.open(self.portal.absolute_url() + '/logout')

  >>> browser.open(form.absolute_url())
  >>> browser.getControl(name="replyto").value = "foo1@bar1.com"
  >>> browser.getControl(name="topic").value = "Hello Again"
  >>> browser.getControl(name="comments").value = "This is cool."
  >>> browser.getControl("Submit").click()

  >>> len(adapter.objectIds()) == 2
  True
  
  
Let's try out the functionality of saving as different content types.

Login first...

  >>> browser.open(portal_url + '/login')
  >>> browser.getControl(name='__ac_name').value = portal_owner
  >>> browser.getControl(name='__ac_password').value = default_password
  >>> browser.getControl(name='submit').click()
  

Next, let's copy the FormSaveData2ContentEntry entry first and use
that.

  >>> browser.open(self.portal.absolute_url() + '/portal_types/manage_main')
  >>> browser.getControl(name="ids:list").value = ['FormSaveData2ContentEntry']
  >>> browser.getControl(name="manage_copyObjects:method").click()
  >>> browser.getControl(name="manage_pasteObjects:method").click()
  >>> browser.open(self.portal.absolute_url() + '/portal_types/copy_of_FormSaveData2ContentEntry/manage_propertiesForm')
  >>> browser.getControl(name="title:string").value = "My New D2C Content Type"
  >>> browser.getControl(name="manage_editProperties:method").click()

Now go to the save data adapter and see if the option for the new content type is there.

  >>> browser.open(adapter.absolute_url())
  >>> browser.getLink("Edit").click()
  >>> "My New D2C Content Type" in browser.contents
  True

FormSaveData2ContentEntry should be the default value.

  >>> browser.getControl(name="entryType").value
  ['FormSaveData2ContentEntry']

Okay, the new type is there. Let's use it now.

  >>> browser.getControl(name="entryType").value = ["copy_of_FormSaveData2ContentEntry"]
  >>> browser.getControl(name="form.button.save").click()

Make sure it saved.

  >>> "My New D2C Content Type" in browser.contents
  True

  >>> adapter.getEntryType()
  'copy_of_FormSaveData2ContentEntry'

Now that the type is selected, try and submit another form and make sure
it is of the same type.

  >>> browser.open(form.absolute_url())
  >>> browser.getControl(name="replyto").value = "foo2@bar2.com"
  >>> browser.getControl(name="topic").value = "Another One! Yay!"
  >>> browser.getControl(name="comments").value = "Nice. a new content type"
  >>> browser.getControl("Submit").click()

  >>> len(adapter.objectIds())
  3

  >>> entry = adapter[adapter.objectIds()[-1]]
  >>> entry.getField('replyto').get(entry)
  'foo2@bar2.com'

  >>> entry.portal_type
  'copy_of_FormSaveData2ContentEntry'

Set up an event subscriber to listen to FormSaveData2ContentEntryFinalizedEvent events.

  >>> class EntryAddedHandler:
  ...    events = []
  ...    def __call__(self, obj, evt):
  ...       self.events.append((obj, evt))
  ...

  >>> handler = EntryAddedHandler()

Add it to subscriber list:
  
  >>> import zope.component
  >>> import zope.component.event # needed for the event system to start
  >>> gsm = zope.component.getGlobalSiteManager()
  >>> from uwosh.pfg.d2c.interfaces import IFormSaveData2ContentEntry
  >>> from uwosh.pfg.d2c.interfaces import IFormSaveData2ContentEntryFinalizedEvent
  >>> gsm.registerHandler(handler, [IFormSaveData2ContentEntry, IFormSaveData2ContentEntryFinalizedEvent])

Fill in yet another entry form to fire an event. 

  >>> browser.open(form.absolute_url())
  >>> browser.getControl(name="replyto").value = "foo3@bar3.com"
  >>> browser.getControl(name="topic").value = "..And yet another.."
  >>> browser.getControl(name="comments").value = "We want to send an event"
  >>> browser.getControl("Submit").click()

  >>> len(handler.events) == 1
  True

  >>> len(adapter.objectIds()) == 4
  True

Let's add a new TALES expression override to generate a custom entry title.

  >>> browser.open(adapter.absolute_url())
  >>> browser.getLink("Edit").click()
  >>> browser.getControl(name="dynamicTitle").value = "python:object.getValue('replyto') + ': ' + object.getValue('topic')"
  >>> browser.getControl(name="form.button.save").click()
 
See that it works:

  >>> browser.open(form.absolute_url())
  >>> browser.getControl(name="replyto").value = "asker@from.com"
  >>> browser.getControl(name="topic").value = "I have a question"
  >>> browser.getControl(name="comments").value = "What's 40+2?"
  >>> browser.getControl("Submit").click()
  >>> entry = handler.events[-1][0]
  >>> browser.open(entry.absolute_url())
  >>> open("contents.html", "w").write(browser.contents)

  >>> "asker@from.com: I have a question" in browser.contents
  True
  
Log out again and submit to check that everything works anonymously. First disable security checks.

  >>> browser.open(adapter.absolute_url())
  >>> browser.getLink("Edit").click()
  >>> browser.getControl(name="avoidSecurityChecks:boolean").value = True
  >>> browser.getControl(name="form.button.save").click()

  >>> browser.open(self.portal.absolute_url() + "/logout")
  >>> browser.open(form.absolute_url())
  >>> browser.getControl(name="replyto").value = "anon@net.fi"
  >>> browser.getControl(name="topic").value = "question"
  >>> browser.getControl(name="comments").value = "This is question comment"
  >>> browser.getControl("Submit").click()

  >>> len(adapter.objectIds()) == 6
  True
  >>> len(handler.events) == 3
  True
