3

I want to create a subscriber that gets triggered when the user tries to access the resource (which is a custom content-type). So, the object is not being added, modified, nothing, is just being traversed. Something like a Zope View Event.

So, basically, suppose a custom content type has a custom workflow (two states: private and viewed). The initial state is private. This content type is only going to be created programatically, using _createObjectByType by anonymous users. Suppose an object called myobjet was added, programatically, to the root folder of my Plone site.

What I want is: when the user access

http://localhost:8080/Plone/myobject

...it automatically changes the state of the workflow of this object to viewed. The url http://localhost:8080/Plone/myobject is going to be a custom view, not the default base_edit.

Which event should I use? I tried IEndRequestEvent and IBeforeTraverseEvent from this list and none of them work: the handler is not being called for my custom object interface.

I've tried other events with my custom object interface (like IObjectEditedEvent), and, for this event, my handler is called when I edit an object that implements the interface. But using IEndRequestEvent and IBeforeTraverseEvent doesn't call the handler.

IEndRequestEvent and IBeforeTraverseEvent only work when I set the subscriber to all interfaces:

  <subscriber
     for="*
          zope.app.publication.interfaces.IBeforeTraverseEvent"
     handler=".subscriber.myhandler"
     />

And when I make myhandler print the object and the event in this situation, it shows:

<PloneSite at Plone>
<zope.app.publication.interfaces.BeforeTraverseEvent object at 0xd52618c>

If the solution is to write an event myself, is there an easy tutorial for this?

2 Answers2

4

You might want to have a look at http://pypi.python.org/pypi/plone.validatehook.

Make sure you bind the event to the right interface. If you bind it to "Interface" (as described on the plone.validatehook pypi page) the event will get called for every single request. In order to restrict the event to contentish objects you can do the following:

from Products.CMFCore.interfaces import IContentish

@adapter(IContentish, IPostValidationEvent)
def RedirectMember(object, event):
    ...

(Edit: I removed my first answer because it didn't work)

tisto
  • 1,337
  • 7
  • 13
  • Did you test it? I've done this and it doesn't work. I've edited the question adding more information. – Somebody still uses you MS-DOS Jul 07 '11 at 17:03
  • Yes. I just tested it and it doesn't work for me neither. I will try plone.validatehook next. – tisto Jul 07 '11 at 17:20
  • It worked, but I needed to edit configure.zcml like the documentation here (http://plone.org/documentation/kb/set-up-subscriber-in-five) instead of just using `` like proposed in the validatehook implementation. But thanks for the link, this is going to be really useful. – Somebody still uses you MS-DOS Jul 08 '11 at 17:03
  • another question. If I add plone.validatehook.interfaces.IPostValidationEvent to my configure.zcml, if the egg is not installed, I can't start my instance. How can I make it ignore the module if it doesn't find it? – Somebody still uses you MS-DOS Jul 08 '11 at 17:23
  • 1
    You can use a zcml condition: http://stackoverflow.com/questions/1596611/what-are-the-valid-conditions-for-zcmlcondition – tisto Jul 09 '11 at 11:03
2

Not sure what this subscriber is supposed to do, but if the object is not being modified, added or whatsoever than I must suspect it will just be viewed...so why not just use the __call__ method of the items view (or the __update__ method if you are using five.grok/dexterity)?

  • Hum, this is indeed something I haven't thought myself. Thanks for the tip! – Somebody still uses you MS-DOS Jul 06 '11 at 21:17
  • are you sure __call__ is called when the object is traversed? I added __call__ in the content-type definition with a simple print statement and nothing happens... – Somebody still uses you MS-DOS Jul 06 '11 at 21:37
  • 1
    I can only guess what your content type looks like, but most of the time you will have a custom view as well. If it is an Archetypes based content type than this would be a dedicated browser view with a `class MyTypeView(BrowserView)` where you have an `__init__` method to do some processing or where you can add a dedicated `__call__` method. – Christoph Böhner Jul 06 '11 at 22:00