This creates a new Gdn_Request object, loaded with the current Environment $_SERVER and $_ENV superglobal imports, such
as REQUEST_URI, SCRIPT_NAME, etc. The intended usage is for additional setter methods to be chained
onto this call in order to fully set up the object.
public static create ( ) : Gdn_Request | ||
return | Gdn_Request |
/** * Analyzes the supplied query string and decides how to dispatch the request. */ public function dispatch($ImportRequest = null, $Permanent = true) { if ($ImportRequest && is_string($ImportRequest)) { $ImportRequest = Gdn_Request::create()->fromEnvironment()->withURI($ImportRequest); } if (is_a($ImportRequest, 'Gdn_Request') && $Permanent) { Gdn::request($ImportRequest); } $Request = is_a($ImportRequest, 'Gdn_Request') ? $ImportRequest : Gdn::request(); $this->EventArguments['Request'] =& $Request; // Move this up to allow pre-routing $this->fireEvent('BeforeDispatch'); // By default, all requests can be blocked by UpdateMode/PrivateCommunity $CanBlock = self::BLOCK_ANY; try { $BlockExceptions = array('/^utility(\\/.*)?$/' => self::BLOCK_NEVER, '/^asset(\\/.*)?$/' => self::BLOCK_NEVER, '/^home\\/error(\\/.*)?/' => self::BLOCK_NEVER, '/^plugin(\\/.*)?$/' => self::BLOCK_NEVER, '/^sso(\\/.*)?$/' => self::BLOCK_NEVER, '/^discussions\\/getcommentcounts/' => self::BLOCK_NEVER, '/^entry(\\/.*)?$/' => self::BLOCK_PERMISSION, '/^user\\/usernameavailable(\\/.*)?$/' => self::BLOCK_PERMISSION, '/^user\\/emailavailable(\\/.*)?$/' => self::BLOCK_PERMISSION, '/^home\\/termsofservice(\\/.*)?$/' => self::BLOCK_PERMISSION); $this->EventArguments['BlockExceptions'] =& $BlockExceptions; $this->fireEvent('BeforeBlockDetect'); $PathRequest = Gdn::request()->path(); foreach ($BlockExceptions as $BlockException => $BlockLevel) { if (preg_match($BlockException, $PathRequest)) { throw new Exception("Block detected - {$BlockException}", $BlockLevel); } } // Never block an admin if (Gdn::session()->checkPermission('Garden.Settings.Manage')) { throw new Exception("Block detected", self::BLOCK_NEVER); } if (Gdn::session()->isValid()) { throw new Exception("Block detected", self::BLOCK_PERMISSION); } } catch (Exception $e) { // BlockLevel // TRUE = Block any time // FALSE = Absolutely no blocking // NULL = Block for permissions (e.g. PrivateCommunity) $CanBlock = $e->getCode(); } // If we're in updatemode and arent explicitly prevented from blocking, block if (Gdn::config('Garden.UpdateMode', false) && $CanBlock > self::BLOCK_NEVER) { $Request->withURI(Gdn::router()->getDestination('UpdateMode')); } // Analyze the request AFTER checking for update mode. $this->analyzeRequest($Request); $this->fireEvent('AfterAnalyzeRequest'); // If we're in update mode and can block, redirect to signin if (C('Garden.PrivateCommunity') && $CanBlock > self::BLOCK_PERMISSION) { if ($this->_DeliveryType === DELIVERY_TYPE_DATA) { safeHeader('HTTP/1.0 401 Unauthorized', true, 401); safeHeader('Content-Type: application/json; charset=' . c('Garden.Charset', 'utf-8'), true); echo json_encode(array('Code' => '401', 'Exception' => t('You must sign in.'))); } else { redirect('/entry/signin?Target=' . urlencode($this->Request)); } exit; } $ControllerName = $this->controllerName(); if ($ControllerName != '' && class_exists($ControllerName)) { // Create it and call the appropriate method/action /* @var Gdn_Controller $Controller */ $Controller = new $ControllerName(); Gdn::controller($Controller); $this->EventArguments['Controller'] =& $Controller; $this->fireEvent('AfterControllerCreate'); // Pass along any assets if (is_array($this->_AssetCollection)) { foreach ($this->_AssetCollection as $AssetName => $Assets) { foreach ($Assets as $Asset) { $Controller->addAsset($AssetName, $Asset); } } } // Instantiate Imported & Uses classes $Controller->getImports(); // Pass in the syndication method $Controller->SyndicationMethod = $this->_SyndicationMethod; // Pass along the request $Controller->SelfUrl = $this->Request; // Pass along any objects foreach ($this->_PropertyCollection as $Name => $Mixed) { $Controller->{$Name} = $Mixed; } // Pass along any data. if (is_array($this->_Data)) { $Controller->Data = $this->_Data; } // Set up a default controller method in case one isn't defined. $ControllerMethod = str_replace('_', '', $this->ControllerMethod); $Controller->OriginalRequestMethod = $ControllerMethod; $this->EventArguments['ControllerMethod'] =& $ControllerMethod; // Take enabled plugins into account, as well $PluginReplacement = Gdn::pluginManager()->hasNewMethod($this->controllerName(), $this->ControllerMethod); if (!$PluginReplacement && ($this->ControllerMethod == '' || !method_exists($Controller, $ControllerMethod)) && !$Controller->isInternal($ControllerMethod)) { // Check to see if there is an 'x' version of the method. if (method_exists($Controller, 'x' . $ControllerMethod)) { // $PluginManagerHasReplacementMethod = TRUE; $ControllerMethod = 'x' . $ControllerMethod; } else { if ($this->ControllerMethod != '') { array_unshift($this->_ControllerMethodArgs, $this->ControllerMethod); } $this->ControllerMethod = 'Index'; $ControllerMethod = 'Index'; $PluginReplacement = Gdn::pluginManager()->hasNewMethod($this->controllerName(), $this->ControllerMethod); } } // Pass in the querystring values $Controller->ApplicationFolder = $this->_ApplicationFolder; $Controller->Application = $this->enabledApplication(); $Controller->RequestMethod = $this->ControllerMethod; $Controller->RequestArgs = $this->_ControllerMethodArgs; $Controller->Request = $Request; $Controller->deliveryType($Request->getValue('DeliveryType', $this->_DeliveryType)); $Controller->deliveryMethod($Request->getValue('DeliveryMethod', $this->_DeliveryMethod)); // Set special controller method options for REST APIs. $Controller->initialize(); $this->EventArguments['Controller'] =& $Controller; $this->fireEvent('AfterControllerInit'); $ReflectionArguments = $Request->get(); $this->EventArguments['Arguments'] =& $ReflectionArguments; $this->fireEvent('BeforeReflect'); // Call the requested method on the controller - error out if not defined. if ($PluginReplacement) { // Reflect the args for the method. $Callback = Gdn::pluginManager()->getCallback($Controller->ControllerName, $ControllerMethod); // Augment the arguments to the plugin with the sender and these arguments. $InputArgs = array_merge(array($Controller), $this->_ControllerMethodArgs, array('Sender' => $Controller, 'Args' => $this->_ControllerMethodArgs)); $Args = reflectArgs($Callback, $InputArgs, $ReflectionArguments); $Controller->ReflectArgs = $Args; try { $this->fireEvent('BeforeControllerMethod'); Gdn::pluginManager()->callEventHandlers($Controller, $Controller->ControllerName, $ControllerMethod, 'Before'); call_user_func_array($Callback, $Args); } catch (Exception $Ex) { $Controller->renderException($Ex); } } elseif (method_exists($Controller, $ControllerMethod) && !$Controller->isInternal($ControllerMethod)) { $Args = reflectArgs(array($Controller, $ControllerMethod), $this->_ControllerMethodArgs, $ReflectionArguments); $this->_ControllerMethodArgs = $Args; $Controller->ReflectArgs = $Args; try { $this->fireEvent('BeforeControllerMethod'); Gdn::pluginManager()->callEventHandlers($Controller, $Controller->ControllerName, $ControllerMethod, 'Before'); call_user_func_array(array($Controller, $ControllerMethod), $Args); } catch (Exception $Ex) { $Controller->renderException($Ex); exit; } } else { $this->EventArguments['Handled'] = false; $Handled =& $this->EventArguments['Handled']; $this->fireEvent('NotFound'); if (!$Handled) { Gdn::request()->withRoute('Default404'); return $this->dispatch(); } else { return $Handled; } } } }
/** * Dispatch a request to a controller method. * * This method analyzes a request and figures out which controller and method it maps to. It also instantiates the * controller and calls the method. * * @param string|Gdn_Request|null $ImportRequest The request to dispatch. This can be a string URL or a Gdn_Request object, * @param bool $Permanent Whether or not to set {@link Gdn::request()} with the dispatched request. */ public function dispatch($ImportRequest = null, $Permanent = true) { if ($ImportRequest && is_string($ImportRequest)) { $ImportRequest = Gdn_Request::create()->fromEnvironment()->withURI($ImportRequest); } if (is_a($ImportRequest, 'Gdn_Request') && $Permanent) { Gdn::request($ImportRequest); } $request = is_a($ImportRequest, 'Gdn_Request') ? $ImportRequest : Gdn::request(); $this->EventArguments['Request'] = $request; // Move this up to allow pre-routing $this->fireEvent('BeforeDispatch'); // If we're in update mode and aren't explicitly prevented from blocking, block. if (Gdn::config('Garden.UpdateMode', false) && $this->getCanBlock($request) > self::BLOCK_NEVER) { $request->withURI(Gdn::router()->getDestination('UpdateMode')); } // Check for URL rewrites. $request = $this->rewriteRequest($request); // We need to save this state now because it's lost after this method. $this->passData('isHomepage', $this->isHomepage); // Let plugins change augment the request before dispatch, but after internal routing. $this->fireEvent('BeforeAnalyzeRequest'); // If we're in a private community and can block, redirect to signin if (c('Garden.PrivateCommunity') && $this->getCanBlock($request) > self::BLOCK_PERMISSION) { if ($this->deliveryType === DELIVERY_TYPE_DATA) { safeHeader('HTTP/1.0 401 Unauthorized', true, 401); safeHeader('Content-Type: application/json; charset=utf-8', true); echo json_encode(array('Code' => '401', 'Exception' => t('You must sign in.'))); } else { redirect('/entry/signin?Target=' . urlencode($request->pathAndQuery())); } exit; } // Analyze the request AFTER checking for update mode. $routeArgs = $this->analyzeRequest($request); $this->fireEvent('AfterAnalyzeRequest'); // Now that the controller has been found, dispatch to a method on it. $this->dispatchController($request, $routeArgs); }