`copyFieldset` one source property to multiple target properties
-
13-12-2019 - |
Question
I'm tasked converting quotes into a custom data type, and using Mage_Core_Helper_Data::copyFieldset
was working really well until I had two target properties that had to be set to the same source property. I've tried a couple of different things
<other_thing_convert_quote>
<grand_total>
<to_varien_object>total</to_varien_object>
</grand_total>
<quote_currency_code>
<to_varien_object>currency</to_varien_object>
</quote_currency_code>
<quote_id>
<to_varien_object>refnum</to_varien_object>
<to_varien_object>txn_uuid</to_varien_object>
</quote_id>
</other_thing_convert_quote>
Above is one quote_id
node, multiple to_varien_object
nodes.
<other_thing_convert_quote>
<grand_total>
<to_varien_object>total</to_varien_object>
</grand_total>
<quote_currency_code>
<to_varien_object>currency</to_varien_object>
</quote_currency_code>
<quote_id>
<to_varien_object>refnum</to_varien_object>
</quote_id>
<quote_id>
<to_varien_object>uuid</to_varien_object>
</quote_id>
</other_thing_convert_quote>
Above is multiple quote_id
nodes, each with one to_varien_object
node.
Neither of these approaches successfully apply quote_id
to both refnum
and txn_uuid
.
Looking at the code, I'm not sure if what I'm looking for is even possible, but hopefully I can be proven wrong!
Thanks
Solution
Another solution would be to use the event that gets dispatched when the copyFieldset function is called:
$eventName = sprintf('core_copy_fieldset_%s_%s', $fieldset, $aspect);
Mage::dispatchEvent($eventName, array(
'target' => $target,
'source' => $source,
'root' => $root
));
As you can see the event name is dynamic so in this case if you call copyFieldset('other_thing_convert_quote', 'to_varien_object', ...) the event name will be core_copy_fieldset_other_thing_convert_quote_to_varien_object and this is what you would put in your module's config.xml:
<events>
<core_copy_fieldset_other_thing_convert_quote_to_varien_object>
<observers>
<modulename>
<type>singleton</type>
<class>modulename/observer</class>
<method>coreCopyFieldsetOtherThingConvertQuoteToVarienObject</method>
</modulename>
</observers>
</core_copy_fieldset_other_thing_convert_quote_to_varien_object>
</events>
And finally in the observer method you do this to set the values you need:
public function coreCopyFieldsetOtherThingConvertQuoteToVarienObject($observer) {
// your 'other_thing'
$src = $observer->getSource();
// your 'varien_object'
$target = $observer->getTarget();
$target->setData('refnum', $src->getQuoteId());
$target->setData('txn_uuid', $src->getQuoteId());
}
OTHER TIPS
There doesn't seem to be significantly large interest in this issue, but in case someone stumbles upon this issue in the future, here's the best solution I've been able to determine. Magento gets data from the source and sets data on the target using getDataUsingMethod
/setDataUsingMethod
which attempts to make a "camelized" method call based on the nodename. For example:
<my_module_convert_thing>
<property_a>
<to_another>*</to_another>
</property_a>
</my_module_convert_thing>
Will try to call setPropertyA
and getPropertyA
on the two objects. If instead of those calls delegating to getData
and setData
through Varien_Object::__call
there's a defined method, there's almost no limit to the flexibility. If two properties need to be set from one source, the following XML fieldset will work:
<my_module_convert_thing>
<property_a>
<to_another>properties_ab</to_another>
</property_a>
</my_module_convert_thing>
And if the method setPropertiesAb
is defined on the another
class, that method can handle the setting of both property_a
and property_b
using the property_a
value from thing
.
It'd be nice if there was a better solution that didn't require essentially extending every class that needs this custom approach, but this is my best stab at solving the issue!