Magento: расширение контроллера учетных записей клиентов для добавления действий к шагам забытого пароля - PullRequest
4 голосов
/ 23 сентября 2010

Мы пытаемся добавить пару действий в AccountController, чтобы добавить еще одно действие после действия Forgotpasswordpost. Проблема в том, что если мы добавим действие в логику preDispatch, чтобы убедиться, что вам не нужно входить в нее, она все равно перенаправляет обратно на страницу входа.

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

        parent::preDispatch();

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

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

Это не работает, потому что мы сначала вызываем родителя, который также выполняет это, но, конечно, preg_match не совпадает, и он запускает метод authenticate, который запускает метод $ action-> getResponse () -> setRedirect ( $ url), который, конечно, устанавливает заголовок, и когда он возвращается к нашему коду, это не имеет значения, а затем перенаправляет.

Мы могли бы просто удалить вызов родителя, но я не уверен, что это лучший подход, так как родитель также вызывает своего родителя, который запускает некоторые вещи для установки области макета, а затем также вызывает родительский метод. Я думал просто вызвать родителя с помощью Mage_Core_Controller_Front_Action, но не был уверен, что это был правильный подход.

Ответы [ 5 ]

4 голосов
/ 23 сентября 2010

Итак, это то, что мы сделали, мы получили флаг и проверили, имеет ли действие флаг no-dispatch.затем мы сбросили его, очистили заголовок и сбросили код ответа.

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);
    }
}
2 голосов
/ 14 августа 2013

Я сделал это следующим образом

1) Переопределил функцию preDispatch

2) и заменил код parent :: preDispatch ();с Mage_Core_Controller_Front_Action :: preDispatch ();,Теперь он работает нормально. Но не уверен, что это правильный метод.

2 голосов
/ 26 декабря 2010

Мне нужно было сделать что-то похожее, В итоге я пропустил оригинальную реализацию preDispatch Mage_Customer_AccountController.

так что в моем главном классе у меня есть:

публичная функция validActions () { return 'create | login | logoutSuccess | Forgotpassword | Forgotpasswordpost | подтвердить | подтверждение | 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);
    }
}

как вы можете видеть, я также добавил validActions (), который возвращает разделенный на конвейер список действий, поэтому, если кто-то захочет переопределить мой собственный код, будет намного проще добавить другое действие.

1 голос
/ 23 сентября 2010

Я предлагаю добавить Наблюдатель в postDispatch, фильтр для accountController, а затем установить _redirect.Дайте мне знать, если вам нужна дополнительная информация.

0 голосов
/ 06 апреля 2011
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);
}
...