Subscribing to event

11 views
Skip to first unread message

Thomas Olsen

unread,
Aug 2, 2012, 3:56:14 PM8/2/12
to sabredav...@googlegroups.com
Starting a new thread as if was becoming OT of the OP ;)

> Repairing the cards would also be an interesting option for SabreDAV too..
>
> But if you want to do this properly, do so by intercepting the
> beforeCreateFile and beforeWriteContent events. And make sure your events
> get triggered before the validation code gets triggered.

How would I ensure that?

> This gives you a chance to intercept the data and repair it before
> validation kicks in.

Would it be something like:

$server = new Sabre_DAV_Server($nodes);

// snip adding plugins etc.

$server->subscribeEvent('beforeWriteContent',
array('MyClass', 'beforeWriteContent'));
$server->subscribeEvent('beforeCreateFile',
array('MyClass', 'beforeCreateFile'));

Or does it have to be an instantiated object and not a class name?

Or am I going the totally wrong way?

> Well, I hope you like it!

Indeed, it's very well structured, I just still haven't got the whole picture.

--
Med venlig hilsen,

Thomas Olsen

Evert Pot

unread,
Aug 2, 2012, 4:06:52 PM8/2/12
to sabredav...@googlegroups.com

On Aug 2, 2012, at 9:56 PM, Thomas Olsen wrote:

> Starting a new thread as if was becoming OT of the OP ;)
>
>> Repairing the cards would also be an interesting option for SabreDAV too..
>>
>> But if you want to do this properly, do so by intercepting the
>> beforeCreateFile and beforeWriteContent events. And make sure your events
>> get triggered before the validation code gets triggered.
>
> How would I ensure that?

subscribeEvent has a third argument, which is a priority number. The default is 100, and lower is earlier.. so if you use:

subscribeEvent('eventName',callback,90) it is guaranteed to come before.

>
>> This gives you a chance to intercept the data and repair it before
>> validation kicks in.
>
> Would it be something like:
>
> $server = new Sabre_DAV_Server($nodes);
>
> // snip adding plugins etc.
>
> $server->subscribeEvent('beforeWriteContent',
> array('MyClass', 'beforeWriteContent'));
> $server->subscribeEvent('beforeCreateFile',
> array('MyClass', 'beforeCreateFile'));
>
> Or does it have to be an instantiated object and not a class name?
>
> Or am I going the totally wrong way?

This is correct. The second argument can be _any_ PHP callable, as long as it passes the 'is_callable()' test.
This includes PHP 5.3 closures.

Regardless, you should probably always use an instance of an object. Static access to objects is almost always a bad design patterns. It defeats the purpose of inheritance. I've noticed the OwnCloud source in particular is a pretty bad offender of this.

For examples of how to use these events, check:

Sabre_CalDAV_Plugin::beforeWriteContent and
Sabre_CalDAV_Plugin::beforeCreateFile

Note that the $data arguments are passed by reference.

>
>> Well, I hope you like it!
>
> Indeed, it's very well structured, I just still haven't got the whole picture.

That's great to hear!

Evert

Thomas Olsen

unread,
Aug 2, 2012, 4:24:04 PM8/2/12
to sabredav...@googlegroups.com
On Thursday 02 August 2012 22:06 Evert Pot wrote:
> On Aug 2, 2012, at 9:56 PM, Thomas Olsen wrote:
> >
> > How would I ensure that?
>
> subscribeEvent has a third argument, which is a priority number. The default
> is 100, and lower is earlier.. so if you use:
>
> subscribeEvent('eventName',callback,90) it is guaranteed to come before.

Ah, yes of course. I noticed that but mostly saw "it is recommended to ommit."
So in this case it makes sense.

> This is correct. The second argument can be _any_ PHP callable, as long as
> it passes the 'is_callable()' test. This includes PHP 5.3 closures.
>
> Regardless, you should probably always use an instance of an object. Static
> access to objects is almost always a bad design patterns. It defeats the
> purpose of inheritance. I've noticed the OwnCloud source in particular is a
> pretty bad offender of this.

Yes, that's true. I wasn't aware it was considered bad design though.

> For examples of how to use these events, check:
>
> Sabre_CalDAV_Plugin::beforeWriteContent and
> Sabre_CalDAV_Plugin::beforeCreateFile
>
> Note that the $data arguments are passed by reference.

So I basically write a 'ValidateAndFix' ;) class which extends
Sabre_DAV_ServerPlugin and call $server->addPlugin(new ValidateAndFix()); ?

Evert Pot

unread,
Aug 2, 2012, 6:50:43 PM8/2/12
to sabredav...@googlegroups.com
>
>> This is correct. The second argument can be _any_ PHP callable, as long as
>> it passes the 'is_callable()' test. This includes PHP 5.3 closures.
>>
>> Regardless, you should probably always use an instance of an object. Static
>> access to objects is almost always a bad design patterns. It defeats the
>> purpose of inheritance. I've noticed the OwnCloud source in particular is a
>> pretty bad offender of this.
>
> Yes, that's true. I wasn't aware it was considered bad design though.

Basically.. the whole idea of OOP is that you can very swap out one object for another, with different behavior.
As long as they share the same parent class, the calling code does not need to be aware of the fact that the object is different.

If you are using static classes, there's no immediate way to replace the injected behaviour without altering the 'calling code'.
Technically this is called inversion of control.

Effectively you are using classes as a way to namespace your procedural code. You're introducing global state, which makes it harder to test and general this will be more difficult to extend.

>
>> For examples of how to use these events, check:
>>
>> Sabre_CalDAV_Plugin::beforeWriteContent and
>> Sabre_CalDAV_Plugin::beforeCreateFile
>>
>> Note that the $data arguments are passed by reference.
>
> So I basically write a 'ValidateAndFix' ;) class which extends
> Sabre_DAV_ServerPlugin and call $server->addPlugin(new ValidateAndFix()); ?

A plugin class is not required. It's a bit of a 'design pattern' you may choose to use.. or not. I put everything in Plugin classes because it makes it easy to add a set of features in one step ;)

Cheers,
Evert

Thomas Olsen

unread,
Aug 2, 2012, 7:24:51 PM8/2/12
to sabredav...@googlegroups.com
On Friday 03 August 2012 00:50 Evert Pot wrote:
>> Static access to objects is almost always a bad design patterns. It defeats
>> the purpose of inheritance. I've noticed the OwnCloud source in particular
>> is a pretty bad offender of this.
> > Yes, that's true. I wasn't aware it was considered bad design though.
>
> Basically.. the whole idea of OOP is that you can very swap out one object
> for another, with different behavior. As long as they share the same parent
> class, the calling code does not need to be aware of the fact that the
> object is different.
>
> If you are using static classes, there's no immediate way to replace the
> injected behaviour without altering the 'calling code'. Technically this is
> called inversion of control.
>
> Effectively you are using classes as a way to namespace your procedural
> code. You're introducing global state, which makes it harder to test and
> general this will be more difficult to extend.

Yes classes in ownCloud are pretty much everywhere only used as namespaces
providing static methods. For a small project that would probably be fine, but
I can imagine us getting into trouble with it in the not so far future.

> A plugin class is not required. It's a bit of a 'design pattern' you may
> choose to use.. or not. I put everything in Plugin classes because it makes
> it easy to add a set of features in one step ;)

When it's there I might as well use it which will probably also make it easier
to track any errors that might appear.

If I wanted to support me-card - which I know very little about other than
it's possible - would that also be done with a server plugin?

Evert Pot

unread,
Aug 2, 2012, 7:47:26 PM8/2/12
to sabredav...@googlegroups.com
> When it's there I might as well use it which will probably also make it easier
> to track any errors that might appear.
>
> If I wanted to support me-card - which I know very little about other than
> it's possible - would that also be done with a server plugin?

No you can do this in the principal backend.

If you add support for the:

{http://sabredav.org/ns}vcard-url

property in getPrincipalsByPrefix, getPrincipalsByPath and updatePrincipals everything should work as expected.

The CardDAV plugin makes sure that that property gets re-exposed as:

{http://calendarserver.org/ns/}me-card


The reason I'm using a different property, is because OS X addressbook demands it to be on the addressbook-home-set path, and my property is defined on the principal (along with all the other principal-related properties).

Evert

Thomas Olsen

unread,
Aug 2, 2012, 8:36:21 PM8/2/12
to sabredav...@googlegroups.com
On Friday 03 August 2012 01:47 Evert Pot wrote:
> > If I wanted to support me-card - which I know very little about other than
> > it's possible - would that also be done with a server plugin?

> property in getPrincipalsByPrefix, getPrincipalsByPath and updatePrincipals
> everything should work as expected.

Interesting, I guess I will have to find a client that actually supports it,
to be able to test it.

A while ago there was talk about adding support for setting a contact as "me",
but I didn't know there was a property for it in CardDAV until I stumbled over
it in he code.

> The reason I'm using a different property, is because OS X addressbook
> demands it to be on the addressbook-home-set path, and my property is
> defined on the principal (along with all the other principal-related
> properties).

Which makes more sense, since you can have several addressbooks. Well,
sometimes Apple have their own way of doing things ;)
Reply all
Reply to author
Forward
0 new messages