I found it is possible to do a rewrite on a core class that does not actually exist….
Usage case example:
I am creating a reCaptcha module that integrates google recaptcha into magento's core captcha system.
In the core captcha you have the ability to state a 'type', as can be seen in the config.xml
of Mage_Captcha
<default>
......
<admin>
<captcha>
<type>zend</type> <<<<<<<<<<<<<<< specify a captcha type (model)
<enable>0</enable>
<font>linlibertine</font>
<mode>after_fail</mode>
<forms>backend_forgotpassword</forms>
<failed_attempts_login>3</failed_attempts_login>
<failed_attempts_ip>1000</failed_attempts_ip>
<timeout>7</timeout>
<length>4-5</length>
<symbols>ABCDEFGHJKMnpqrstuvwxyz23456789</symbols>
<case_sensitive>0</case_sensitive>
<always_for>
<backend_forgotpassword>1</backend_forgotpassword>
</always_for>
</captcha>
</admin>
......
</default>
so in my module I extend the core functionality and added a new type called 'recaptcha'
However, the developer of that core module kinda locked the model location down to exist within the Mage_Captcha
namespace, as can be seen in the helper class of that module
/**
* Get Captcha
*
* @param string $formId
* @return Mage_Captcha_Model_Interface
*/
public function getCaptcha($formId)
{
if (!array_key_exists($formId, $this->_captcha)) {
$type = $this->getConfigNode('type');
$this->_captcha[$formId] = Mage::getModel('captcha/' . $type, array('formId' => $formId));
}
return $this->_captcha[$formId];
}
so Mage_Captcha_Model_Recaptcha
does not actually exist, which means I cannot use this….BUT, if, I place a rewrite directive in my module for that class/file, to a model class in my module, I can intercept the model instantiation, and successfully instantiate my class.
<captcha>
<rewrite>
<recaptcha>MyNamespace_MyModule_Model_Recapthca</recaptcha>
</rewrite>
</captcha>
Considering how rewrites work, I do think there is not any need for magento's rewrite system to check (or care) that a file exists to rewrite it.
Magento get the rewrite directive, and instantiates the new model class instead of the original (even if it does not exist)
So, is this a bug, or a feature?
Should I not depend on this ability?
It does, however, open up some possibilities on extending some poorly written core functionality (like this captcha system)
EDIT:
I released a module that resulted in this question happening.
The module is a nice drop-in replacement of core captcha with googles reCaptcha
Best Answer
I'd say the "bug" here is a poorly implemented configurable class feature in the
Mage_Captcha
module -- although it could be argued the developer did this specifically to restrict capcha class to thecapcha
model group, and therefore also restrict it to theMage_Capcha
module. If that's the case, this developer didn't comprehend the power of a fully operational Magento rewrite system.Magento's rewrite feature is designed to allow a rewrite of any class irrespective of code pool, so I'd say that's a feature, and you should be able to rely on it. A few caveats follow.
The one thing you left out of your post is how you plan on changing
to
If you're going to change this directly in
Mage_Capcha
, or you're going to use thecore_config_data
table and/or system configuration fields, you'll run into a problem if this configuration exists, but your module with the rewrite is disabled/removed. Your module is removed, Magento tried to instantiate acapcha/recapcha
model, can't find it, dies.So make sure you replace this value either by creating the same node structure in your module such that your value is merged over the above value, or by (at runtime) dynamically replacing the value in the configuration with with
Mage::getConfig()->setNode()
.Finally, if it was me, since you need a rewrite to do this anyway, I'd just rewrite the
getCaptcha
function in thecapcha/data
helper class to instantiate the model you want.