Magento: Extending Customer Account Controller to add actions to the forgot password steps

霸气de小男生 提交于 2019-12-04 10:32:52

So this is what we did, we got the flag and checked if the action had the flag of no-dispatch. then we unset it, cleared the header and reset the response code.

public function preDispatch()
{
    // a brute-force protection here would be nice

    parent::preDispatch();

    $action = $this->getRequest()->getActionName();

    // The parent preDispatch call will set:
    // 1. the 'no-dispatch' flag and set a
    // 2. a 'Location' header for a 302 redirect to the login page
    //    for any actions which are not on the list.
    // 3. a HTTP Response Code of 302 (temporary redirect).
    // We add additional actions securityquestion and securityquestionpost in our override below, but
    // we need to undo the settings which get set by the call to the parent above.
    if (preg_match('/^(securityquestion|securityquestionpost)/i', $action))
    {
        $flag = 'no-dispatch';

        if ($this->getFlag($action, $flag))
        {
              unset($this->_flags[$action][$flag]); // Remove the flag to unset it
              $this->getResponse()->clearHeader('Location'); // Remove Location header for redirect
              $this->getResponse()->setHttpResponseCode(200); // Set HTTP Response Code to OK

        }
    }

    if (!$this->getRequest()->isDispatched()) {
        return;
    }


    if (!preg_match('/^(create|login|logoutSuccess|forgotpassword|forgotpasswordpost|confirm|confirmation|securityquestion|securityquestionpost)/i', $action)) {
        if (!$this->_getSession()->authenticate($this)) {
            $this->setFlag('', 'no-dispatch', true);
        }
    } else {
        $this->_getSession()->setNoReferer(true);
    }
}

I needed to do something simmilar, I ended up skipping the original implementation of preDispatch of the Mage_Customer_AccountController.

so in my overriding class I have:

public function validActions() { return 'create|login|logoutSuccess|forgotpassword|forgotpasswordpost|confirm|confirmation|mynewaction'; }

public function preDispatch()
{
    //I override this to add my new Action as a valid one.
    //this is also the reason why I call the grand parent and not parent class's preDispatch()
    // becase the default implementation does not enable to simply override the list of valid actions.

    // a brute-force protection here would be nice

    $par = get_parent_class($this);
    $gpar = get_parent_class($par);  
    $gpar::preDispatch();

    if (!$this->getRequest()->isDispatched()) {
        return;
    }

    $action = $this->getRequest()->getActionName();
    if (!preg_match('/^(' . $this->validActions() . ')/i', $action)) {
        if (!$this->_getSession()->authenticate($this)) {
            $this->setFlag('', 'no-dispatch', true);
        }
    } else {
        $this->_getSession()->setNoReferer(true);
    }
}

as you can see I also added a validActions() that returns a pipe separated list of actions so if someone wants to override my own code it will be much easier to add another action.

I have done it as follows

1) Overridden the function preDispatch

2) and replaced the code parent::preDispatch(); with Mage_Core_Controller_Front_Action::preDispatch(); . Its working fine now .But not sure if this is the proper method .

I suggest that you add an Observer on postDispatch, filter for accountController and then set the _redirect. Let me know if you need more info.

protected $_validActions = array('create','login','logoutSuccess','forgotpassword','forgotpasswordpost','confirm','confirmation');
protected $_customActions = array('customaction1', 'customaction2');

/**
 * Action predispatch
 *
 * Check customer authentication for some actions
 */
public function preDispatch()
{
    // a brute-force protection here would be nice

    $action = $this->getRequest()->getActionName();

    /**
     * If the requested action is a custom action, we can get around the parent class's 
     * action validation check by passing it an action it knows like 'login' for example.
     * 
     * We'll reset the action name in the request temporairily so that we don't have to deal with 
     * all the headers and flags that get set when an action check fails validation. This will also
     * allow us to avoid having the session->beforeAuthUrl getting set when session->authenticate(action) fails
     */
    if (preg_match('/^('.$this->_getCustomActions().')/i', $action))
    {
        $this->getRequest()->setActionName($this->_validActions[1]);
    }

    parent::preDispatch();

    /**
     * Parent check is complete, reset request action name to origional value
     */
    if ($action != $this->getRequest()->getActionName())
    {
        $this->getRequest()->setActionName($action);
    }

    if (!$this->getRequest()->isDispatched()) {
        return;
    }

    if (!preg_match('/^('.$this->_getValidActions().')/i', $action)) {
        if (!$this->_getSession()->authenticate($this)) {
            $this->setFlag('', 'no-dispatch', true);
        }
    } else {
        $this->_getSession()->setNoReferer(true);
    }

}

/**
 * Gets default action names and returns them as a pipe separated string
 *
 * @return string
 */
protected function _getValidActions()
{
    return implode("|", array_merge($this->_validActions, $this->_customActions));
}

/**
 * Gets custom action names and returns them as a pipe separated string
 *
 * @return string
 */
protected function _getCustomActions()
{
    return implode("|", $this->_customActions);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!