The exportables system by default produces objects of class stdClass, and there's provision to set this to a different class by setting 'object' in the hook_schema data.

However, this doesn't quite go far enough.
In Clients module, client connection objects have different classes depending on their type -- this is the same pattern as in Flag module, for instance.

Obviously I can work around this in my load callback like this:

      $type = $result[$name]->type;
      $class = 'clients_connection_' . $type;
      // Hand the object over to the constructor which takes care of putting the
      // data into the handler object and any processing that needs doing.
      $connection = new $class((array) $result[$name]);

but it's a bit messy to have to remake the object, and also it means I have to implement my own static caching rather than rely on that in ctools_export_load_object().

What I suggest is either:

a) a 'object class callback' setting, where the callback is called with the $data before calling _ctools_export_unpack_object().

b) two settings, 'object class key' and 'object class prefix'. So in my case I would set this in my hook_schema():

'object class key' => 'type'
'object class prefix' => 'clients_connection_'

Let me know which you prefer, or another method, and I'll work on a patch :)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

merlinofchaos’s picture

The callback is probably more flexible. Since I had never imagined a usecase where there would be multiple classes used for objects of the same time, I suspect the array of possible use cases is larger than what we have here. The callback would enable support for any. I'm in favor of going that route, and I'm happy to support this kind of case.

joachim’s picture

Version: 7.x-1.x-dev » 6.x-1.x-dev
Status: Active » Needs review
FileSize
2.57 KB

On 6 as that's where I have a test setup right now... will reroll for 7 if you approve the approach.

I'm not entirely sure about having all this prelude to calling _ctools_export_unpack_object() present in two places -- my gut feeling would be to change _ctools_export_unpack_object() to look inside $schema which it already has as a first parameter. In fact nothing calls _ctools_export_unpack_object() with an object to unpack into -- at least within ctools and as an underscore-prefixed function, it's meant to be internal...

joachim’s picture

Here's another approach which I think is cleaner, though it removes the ability to pass in an arbitrary string to _ctools_export_unpack_object().

merlinofchaos’s picture

The second approach seems pretty reasonable.

joachim’s picture

Had an idea for a third approach in my sleep... ;)

Define 'object factory' in the schema, and if set, that function is called instead of _ctools_export_unpack_object().

This would mean implementing modules can call their constructor with whatever parameters they need. In my case:

  $connection = new $class($data);
  // The class's __construct() does stuff with the $data.
merlinofchaos’s picture

Okay, I like approach #3 as a very sane, flexible way to do it.

joachim’s picture

Here's approach #3. It's actually the simplest patch out of all three too! :)

merlinofchaos’s picture

Status: Needs review » Fixed

Committed to D6 and D7. Note that in D6 I updated the API version for the new functionality and in both cases I updated API.txt

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.