00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 abstract class Mage_Core_Controller_Varien_Action
00038 {
00039 const FLAG_NO_CHECK_INSTALLATION = 'no-install-check';
00040 const FLAG_NO_DISPATCH = 'no-dispatch';
00041 const FLAG_NO_PRE_DISPATCH = 'no-preDispatch';
00042 const FLAG_NO_POST_DISPATCH = 'no-postDispatch';
00043 const FLAG_NO_START_SESSION = 'no-startSession';
00044 const FLAG_NO_DISPATCH_BLOCK_EVENT = 'no-beforeGenerateLayoutBlocksDispatch';
00045 const FLAG_NO_COOKIES_REDIRECT = 'no-cookies-redirect';
00046
00047 const PARAM_NAME_SUCCESS_URL = 'success_url';
00048 const PARAM_NAME_ERROR_URL = 'error_url';
00049 const PARAM_NAME_REFERER_URL = 'referer_url';
00050 const PARAM_NAME_BASE64_URL = 'r64';
00051 const PARAM_NAME_URL_ENCODED = 'uenc';
00052
00053 const PROFILER_KEY = 'mage::dispatch::controller::action';
00054
00055
00056
00057
00058
00059
00060 protected $_request;
00061
00062
00063
00064
00065
00066
00067 protected $_response;
00068
00069
00070
00071
00072
00073
00074 protected $_realModuleName;
00075
00076
00077
00078
00079
00080
00081
00082
00083 protected $_flags = array();
00084
00085
00086
00087
00088
00089
00090 protected $_cookieCheckActions = array();
00091
00092
00093
00094
00095
00096
00097
00098
00099 public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array())
00100 {
00101 $this->_request = $request;
00102 $this->_response= $response;
00103
00104 Mage::app()->getFrontController()->setAction($this);
00105
00106 $this->_construct();
00107 }
00108
00109 protected function _construct()
00110 {
00111
00112 }
00113
00114 public function hasAction($action)
00115 {
00116 return is_callable(array($this, $this->getActionMethodName($action)));
00117 }
00118
00119
00120
00121
00122
00123
00124 public function getRequest()
00125 {
00126 return $this->_request;
00127 }
00128
00129
00130
00131
00132
00133
00134 public function getResponse()
00135 {
00136 return $this->_response;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146 public function getFlag($action, $flag='')
00147 {
00148 if (''===$action) {
00149 $action = $this->getRequest()->getActionName();
00150 }
00151 if (''===$flag) {
00152 return $this->_flags;
00153 }
00154 elseif (isset($this->_flags[$action][$flag])) {
00155 return $this->_flags[$action][$flag];
00156 }
00157 else {
00158 return false;
00159 }
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 public function setFlag($action, $flag, $value)
00171 {
00172 if (''===$action) {
00173 $action = $this->getRequest()->getActionName();
00174 }
00175 $this->_flags[$action][$flag] = $value;
00176 return $this;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186 public function getFullActionName($delimiter='_')
00187 {
00188 return $this->getRequest()->getRouteName().$delimiter.
00189 $this->getRequest()->getControllerName().$delimiter.
00190 $this->getRequest()->getActionName();
00191 }
00192
00193
00194
00195
00196
00197
00198 public function getLayout()
00199 {
00200 return Mage::getSingleton('core/layout');
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 public function loadLayout($handles=null, $generateBlocks=true, $generateXml=true)
00212 {
00213
00214 if (false!==$handles && ''!==$handles) {
00215 $this->getLayout()->getUpdate()->addHandle($handles ? $handles : 'default');
00216 }
00217
00218
00219 $this->addActionLayoutHandles();
00220
00221 $this->loadLayoutUpdates();
00222
00223 if (!$generateXml) {
00224 return $this;
00225 }
00226 $this->generateLayoutXml();
00227
00228 if (!$generateBlocks) {
00229 return $this;
00230 }
00231 $this->generateLayoutBlocks();
00232
00233 return $this;
00234 }
00235
00236 public function addActionLayoutHandles()
00237 {
00238 $update = $this->getLayout()->getUpdate();
00239
00240
00241 $update->addHandle('STORE_'.Mage::app()->getStore()->getCode());
00242
00243
00244 $package = Mage::getSingleton('core/design_package');
00245 $update->addHandle('THEME_'.$package->getArea().'_'.$package->getPackageName().'_'.$package->getTheme('layout'));
00246
00247
00248 $update->addHandle(strtolower($this->getFullActionName()));
00249
00250 return $this;
00251 }
00252
00253 public function loadLayoutUpdates()
00254 {
00255 $_profilerKey = self::PROFILER_KEY . '::' .$this->getFullActionName();
00256
00257
00258 Mage::dispatchEvent(
00259 'controller_action_layout_load_before',
00260 array('action'=>$this, 'layout'=>$this->getLayout())
00261 );
00262
00263
00264 Varien_Profiler::start("$_profilerKey::layout_load");
00265 $this->getLayout()->getUpdate()->load();
00266 Varien_Profiler::stop("$_profilerKey::layout_load");
00267
00268 return $this;
00269 }
00270
00271 public function generateLayoutXml()
00272 {
00273 $_profilerKey = self::PROFILER_KEY . '::' . $this->getFullActionName();
00274
00275 if(!$this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) {
00276 Mage::dispatchEvent(
00277 'controller_action_layout_generate_xml_before',
00278 array('action'=>$this, 'layout'=>$this->getLayout())
00279 );
00280 }
00281
00282
00283 Varien_Profiler::start("$_profilerKey::layout_generate_xml");
00284 $this->getLayout()->generateXml();
00285 Varien_Profiler::stop("$_profilerKey::layout_generate_xml");
00286
00287 return $this;
00288 }
00289
00290 public function generateLayoutBlocks()
00291 {
00292 $_profilerKey = self::PROFILER_KEY . '::' . $this->getFullActionName();
00293
00294 if(!$this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) {
00295 Mage::dispatchEvent(
00296 'controller_action_layout_generate_blocks_before',
00297 array('action'=>$this, 'layout'=>$this->getLayout())
00298 );
00299 }
00300
00301
00302 Varien_Profiler::start("$_profilerKey::layout_generate_blocks");
00303 $this->getLayout()->generateBlocks();
00304 Varien_Profiler::stop("$_profilerKey::layout_generate_blocks");
00305
00306 if(!$this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) {
00307 Mage::dispatchEvent(
00308 'controller_action_layout_generate_blocks_after',
00309 array('action'=>$this, 'layout'=>$this->getLayout())
00310 );
00311 }
00312
00313 return $this;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322 public function renderLayout($output='')
00323 {
00324 $_profilerKey = self::PROFILER_KEY . '::' . $this->getFullActionName();
00325
00326 if ($this->getFlag('', 'no-renderLayout')) {
00327 return;
00328 }
00329
00330 if (Mage::app()->getFrontController()->getNoRender()) {
00331 return;
00332 }
00333
00334 Varien_Profiler::start("$_profilerKey::layout_render");
00335
00336
00337 if (''!==$output) {
00338 $this->getLayout()->addOutputBlock($output);
00339 }
00340
00341 Mage::dispatchEvent('controller_action_layout_render_before');
00342 Mage::dispatchEvent('controller_action_layout_render_before_'.$this->getFullActionName());
00343
00344 #ob_implicit_flush();
00345 $this->getLayout()->setDirectOutput(false);
00346
00347 $output = $this->getLayout()->getOutput();
00348
00349 $this->getResponse()->appendBody($output);
00350 Varien_Profiler::stop("$_profilerKey::layout_render");
00351
00352 return $this;
00353 }
00354
00355 public function dispatch($action)
00356 {
00357 try {
00358 $actionMethodName = $this->getActionMethodName($action);
00359
00360 if (!is_callable(array($this, $actionMethodName))) {
00361 $actionMethodName = 'norouteAction';
00362 }
00363
00364 Varien_Profiler::start(self::PROFILER_KEY.'::predispatch');
00365 $this->preDispatch();
00366 Varien_Profiler::stop(self::PROFILER_KEY.'::predispatch');
00367
00368 if ($this->getRequest()->isDispatched()) {
00369
00370
00371
00372 if (!$this->getFlag('', self::FLAG_NO_DISPATCH)) {
00373 $_profilerKey = self::PROFILER_KEY.'::'.$this->getFullActionName();
00374
00375 Varien_Profiler::start($_profilerKey);
00376 $this->$actionMethodName();
00377 Varien_Profiler::stop($_profilerKey);
00378
00379 Varien_Profiler::start(self::PROFILER_KEY.'::postdispatch');
00380 $this->postDispatch();
00381 Varien_Profiler::stop(self::PROFILER_KEY.'::postdispatch');
00382 }
00383 }
00384 }
00385 catch (Mage_Core_Controller_Varien_Exception $e) {
00386
00387 foreach ($e->getResultFlags() as $flagData) {
00388 list($action, $flag, $value) = $flagData;
00389 $this->setFlag($action, $flag, $value);
00390 }
00391
00392 list($method, $parameters) = $e->getResultCallback();
00393 switch ($method) {
00394 case Mage_Core_Controller_Varien_Exception::RESULT_REDIRECT:
00395 list($path, $arguments) = $parameters;
00396 $this->_redirect($path, $arguments);
00397 break;
00398 case Mage_Core_Controller_Varien_Exception::RESULT_FORWARD:
00399 list($action, $controller, $module, $params) = $parameters;
00400 $this->_forward($action, $controller, $module, $params);
00401 break;
00402 default:
00403 $actionMethodName = $this->getActionMethodName($method);
00404 $this->getRequest()->setActionName($method);
00405 $this->$actionMethodName($method);
00406 break;
00407 }
00408 }
00409 }
00410
00411 public function getActionMethodName($action)
00412 {
00413 $method = $action.'Action';
00414 return $method;
00415 }
00416
00417
00418
00419
00420 public function preDispatch()
00421 {
00422 if (!$this->getFlag('', self::FLAG_NO_CHECK_INSTALLATION)) {
00423 if (!Mage::isInstalled()) {
00424 $this->setFlag('', self::FLAG_NO_DISPATCH, true);
00425 $this->_redirect('install');
00426 return;
00427 }
00428 }
00429
00430 if ($this->_rewrite()) {
00431 return;
00432 }
00433
00434 if (!$this->getFlag('', self::FLAG_NO_START_SESSION)) {
00435 $namespace = $this->getLayout()->getArea();
00436 $checkCookie = in_array($this->getRequest()->getActionName(), $this->_cookieCheckActions);
00437 if ($checkCookie && !Mage::getSingleton('core/cookie')->get($namespace)) {
00438 $this->setFlag('', self::FLAG_NO_COOKIES_REDIRECT, true);
00439 }
00440 Mage::getSingleton('core/session', array('name' => $namespace))->start();
00441 }
00442
00443 Mage::app()->loadArea($this->getLayout()->getArea());
00444
00445 if ($this->getFlag('', self::FLAG_NO_COOKIES_REDIRECT) && Mage::getStoreConfig('web/browser_capabilities/cookies')) {
00446 $this->_forward('noCookies', 'index', 'core');
00447 return;
00448 }
00449
00450 if ($this->getFlag('', self::FLAG_NO_PRE_DISPATCH)) {
00451 return;
00452 }
00453
00454 Mage::dispatchEvent('controller_action_predispatch', array('controller_action'=>$this));
00455 Mage::dispatchEvent(
00456 'controller_action_predispatch_'.$this->getRequest()->getRouteName(),
00457 array('controller_action'=>$this)
00458 );
00459 Varien_Autoload::registerScope($this->getRequest()->getRouteName());
00460 Mage::dispatchEvent(
00461 'controller_action_predispatch_'.$this->getFullActionName(),
00462 array('controller_action'=>$this)
00463 );
00464 }
00465
00466
00467
00468
00469 public function postDispatch()
00470 {
00471 if ($this->getFlag('', self::FLAG_NO_POST_DISPATCH)) {
00472 return;
00473 }
00474
00475 Mage::dispatchEvent(
00476 'controller_action_postdispatch_'.$this->getFullActionName(),
00477 array('controller_action'=>$this)
00478 );
00479 Mage::dispatchEvent(
00480 'controller_action_postdispatch_'.$this->getRequest()->getRouteName(),
00481 array('controller_action'=>$this)
00482 );
00483 Mage::dispatchEvent('controller_action_postdispatch', array('controller_action'=>$this));
00484 }
00485
00486 public function norouteAction($coreRoute = null)
00487 {
00488 $status = ( $this->getRequest()->getParam('__status__') )
00489 ? $this->getRequest()->getParam('__status__')
00490 : new Varien_Object();
00491
00492 Mage::dispatchEvent('controller_action_noroute', array('action'=>$this, 'status'=>$status));
00493 if ($status->getLoaded() !== true
00494 || $status->getForwarded() === true
00495 || !is_null($coreRoute) ) {
00496 $this->loadLayout(array('default', 'noRoute'));
00497 $this->renderLayout();
00498 } else {
00499 $status->setForwarded(true);
00500 #$this->_forward('cmsNoRoute', 'index', 'cms');
00501 $this->_forward(
00502 $status->getForwardAction(),
00503 $status->getForwardController(),
00504 $status->getForwardModule(),
00505 array('__status__' => $status));
00506 }
00507 }
00508
00509 public function noCookiesAction()
00510 {
00511 $redirect = new Varien_Object();
00512 Mage::dispatchEvent('controller_action_nocookies', array(
00513 'action' => $this,
00514 'redirect' => $redirect
00515 ));
00516
00517 if ($url = $redirect->getRedirectUrl()) {
00518 $this->_redirectUrl($url);
00519 }
00520 elseif ($redirect->getRedirect()) {
00521 $this->_redirect($redirect->getPath(), $redirect->getArguments());
00522 }
00523 else {
00524 $this->loadLayout(array('default', 'noCookie'));
00525 $this->renderLayout();
00526 }
00527
00528 $this->getRequest()->setDispatched(true);
00529 }
00530
00531 protected function _forward($action, $controller = null, $module = null, array $params = null)
00532 {
00533 $request = $this->getRequest();
00534
00535 if (!is_null($params)) {
00536 $request->setParams($params);
00537 }
00538
00539 if (!is_null($controller)) {
00540 $request->setControllerName($controller);
00541
00542
00543 if (!is_null($module)) {
00544 $request->setModuleName($module);
00545 }
00546 }
00547
00548 $request->setActionName($action)
00549 ->setDispatched(false);
00550 }
00551
00552 protected function _initLayoutMessages($messagesStorage)
00553 {
00554 if ($storage = Mage::getSingleton($messagesStorage)) {
00555 $this->getLayout()->getMessagesBlock()->addMessages($storage->getMessages(true));
00556 }
00557 else {
00558 Mage::throwException(
00559 Mage::helper('core')->__('Invalid messages storage "%s" for layout messages initialization', (string)$messagesStorage)
00560 );
00561 }
00562 return $this;
00563 }
00564
00565
00566
00567
00568
00569
00570
00571 protected function _redirectUrl($url)
00572 {
00573 $this->getResponse()->setRedirect($url);
00574 return $this;
00575 }
00576
00577
00578
00579
00580
00581
00582
00583 protected function _redirect($path, $arguments=array())
00584 {
00585 $this->getResponse()->setRedirect(Mage::getUrl($path, $arguments));
00586 return $this;
00587 }
00588
00589
00590
00591
00592
00593
00594 protected function _redirectSuccess($defaultUrl)
00595 {
00596 $successUrl = $this->getRequest()->getParam(self::PARAM_NAME_SUCCESS_URL);
00597 if (empty($successUrl)) {
00598 $successUrl = $defaultUrl;
00599 }
00600 if (!$this->_isUrlInternal($successUrl)) {
00601 $successUrl = Mage::app()->getStore()->getBaseUrl();
00602 }
00603 $this->getResponse()->setRedirect($successUrl);
00604 return $this;
00605 }
00606
00607
00608
00609
00610
00611
00612 protected function _redirectError($defaultUrl)
00613 {
00614 $errorUrl = $this->getRequest()->getParam(self::PARAM_NAME_ERROR_URL);
00615 if (empty($errorUrl)) {
00616 $errorUrl = $defaultUrl;
00617 }
00618 if (!$this->_isUrlInternal($errorUrl)) {
00619 $errorUrl = Mage::app()->getStore()->getBaseUrl();
00620 }
00621 $this->getResponse()->setRedirect($errorUrl);
00622 return $this;
00623 }
00624
00625
00626
00627
00628
00629
00630
00631 protected function _redirectReferer($defaultUrl=null)
00632 {
00633
00634 $refererUrl = $this->_getRefererUrl();
00635 if (empty($refererUrl)) {
00636 $refererUrl = empty($defaultUrl) ? Mage::getBaseUrl() : $defaultUrl;
00637 }
00638
00639 $this->getResponse()->setRedirect($refererUrl);
00640 return $this;
00641 }
00642
00643
00644
00645
00646
00647
00648 protected function _getRefererUrl()
00649 {
00650 $refererUrl = $this->getRequest()->getServer('HTTP_REFERER');
00651 if ($url = $this->getRequest()->getParam(self::PARAM_NAME_REFERER_URL)) {
00652 $refererUrl = $url;
00653 }
00654 if ($url = $this->getRequest()->getParam(self::PARAM_NAME_BASE64_URL)) {
00655 $refererUrl = Mage::helper('core')->urlDecode($url);
00656 }
00657 if ($url = $this->getRequest()->getParam(self::PARAM_NAME_URL_ENCODED)) {
00658 $refererUrl = Mage::helper('core')->urlDecode($url);
00659 }
00660
00661 if (!$this->_isUrlInternal($refererUrl)) {
00662 $refererUrl = Mage::app()->getStore()->getBaseUrl();
00663 }
00664 return $refererUrl;
00665 }
00666
00667
00668
00669
00670
00671
00672
00673 protected function _isUrlInternal($url)
00674 {
00675 if (strpos($url, 'http') !== false) {
00676
00677
00678
00679 if ((strpos($url, Mage::app()->getStore()->getBaseUrl()) === 0)
00680 || (strpos($url, Mage::app()->getStore()->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true)) === 0)) {
00681 return true;
00682 }
00683 }
00684 return false;
00685 }
00686
00687
00688
00689
00690
00691
00692 protected function _getRealModuleName()
00693 {
00694 if (empty($this->_realModuleName)) {
00695 $class = get_class($this);
00696 $this->_realModuleName = substr(
00697 $class,
00698 0,
00699 strpos(strtolower($class), '_' . strtolower($this->getRequest()->getControllerName() . 'Controller'))
00700 );
00701 }
00702 return $this->_realModuleName;
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 protected function _rewrite()
00732 {
00733 $route = $this->getRequest()->getRouteName();
00734 $controller = $this->getRequest()->getControllerName();
00735 $action = $this->getRequest()->getActionName();
00736
00737 $rewrite = Mage::getConfig()->getNode('global/routers/'.$route.'/rewrite/'.$controller);
00738 if (!$rewrite) {
00739 return false;
00740 }
00741
00742 if (!($rewrite->actions && $rewrite->actions->$action) || $rewrite->is('override_actions')) {
00743 $t = explode('/', (string)$rewrite->to);
00744 if (sizeof($t)!==2 || empty($t[0]) || empty($t[1])) {
00745 return false;
00746 }
00747 $t[2] = $action;
00748 } else {
00749 $t = explode('/', (string)$rewrite->actions->$action->to);
00750 if (sizeof($t)!==3 || empty($t[0]) || empty($t[1]) || empty($t[2])) {
00751 return false;
00752 }
00753 }
00754
00755 $this->_forward(
00756 $t[2]==='*' ? $action : $t[2],
00757 $t[1]==='*' ? $controller : $t[1],
00758 $t[0]==='*' ? $route : $t[0]
00759 );
00760
00761 return true;
00762 }
00763
00764
00765
00766
00767
00768
00769 protected function _validateFormKey()
00770 {
00771 if (!($formKey = $this->getRequest()->getParam('form_key', null))
00772 || $formKey != Mage::getSingleton('core/session')->getFormKey()) {
00773 return false;
00774 }
00775 return true;
00776 }
00777 }