Пример #1
0
 /**
  * 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();
     if (Gdn::Session()->NewVisit()) {
         Gdn::UserModel()->FireEvent('Visit');
     }
     // 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, '/^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'));
     }
     // Analze the request AFTER checking for update mode.
     $this->AnalyzeRequest($Request);
     $this->FireEvent('AfterAnalyzeRequest');
     // If we're in updatemode and can block, redirect to signin
     if (C('Garden.PrivateCommunity') && $CanBlock > self::BLOCK_PERMISSION) {
         Redirect('/entry/signin?Target=' . urlencode($this->Request));
         exit;
     }
     $ControllerName = $this->ControllerName();
     if ($ControllerName != '' && class_exists($ControllerName)) {
         // Create it and call the appropriate method/action
         $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;
         // Take enabled plugins into account, as well
         $PluginReplacement = Gdn::PluginManager()->HasNewMethod($this->ControllerName(), $this->ControllerMethod);
         if (!$PluginReplacement && ($this->ControllerMethod == '' || !method_exists($Controller, $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->ControllerFolder = $this->ControllerFolder;
         $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');
         // Call the requested method on the controller - error out if not defined.
         if ($PluginReplacement) {
             // Set the application folder to the plugin's key.
             //            $PluginInfo = Gdn::PluginManager()->GetPluginInfo($PluginReplacement, Gdn_PluginManager::ACCESS_CLASSNAME);
             //            if ($PluginInfo) {
             //               $Controller->ApplicationFolder = 'plugins/'.GetValue('Index', $PluginInfo);
             //            }
             // 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));
             //            decho(array_keys($InputArgs), 'InputArgs');
             $Args = ReflectArgs($Callback, $InputArgs, $Request->Get());
             $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)) {
             $Args = ReflectArgs(array($Controller, $ControllerMethod), $this->_ControllerMethodArgs, $Request->Get());
             $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;
             }
         }
     }
 }
Пример #2
0
 /**
  * Call a method on the given model.
  */
 public function Model()
 {
     $this->Permission('Garden.Settings.Manage');
     $this->DeliveryMethod(DELIVERY_METHOD_JSON);
     $this->DeliveryType(DELIVERY_TYPE_DATA);
     $Args = func_get_args();
     // Check to see if we have a model.
     $ModelName = StringEndsWith(array_shift($Args), 'Model', TRUE, TRUE);
     $ModelName = ucfirst($ModelName) . 'Model';
     if (!class_exists($ModelName)) {
         throw NotFoundException($ModelName);
     }
     // Check for json/xml style extension.
     if (count($Args)) {
         $LastArg = $Args[count($Args) - 1];
         $Extension = strrchr($LastArg, '.');
         if ($Extension) {
             $Args[count($Args) - 1] = substr($LastArg, 0, -strlen($Extension));
             $Extension = strtolower($Extension);
             if ($Extension == '.xml') {
                 $this->DeliveryMethod(DELIVERY_METHOD_XML);
             }
         }
     }
     // Instantiate the model.
     $Model = new $ModelName();
     $MethodName = array_shift($Args);
     // Reflect the arguments.
     $Callback = array($Model, $MethodName);
     if ($this->Request->Get('help')) {
         $this->SetData('Model', get_class($Model));
         if ($MethodName) {
             if (!method_exists($Model, $MethodName)) {
                 throw NotFoundException($ModelName . '->' . $MethodName . '()');
             }
             $this->SetData('Method', $MethodName);
             $Meth = new ReflectionMethod($Callback[0], $Callback[1]);
             $MethArgs = $Meth->getParameters();
             $Args = array();
             foreach ($MethArgs as $Index => $MethArg) {
                 $ParamName = $MethArg->getName();
                 if ($MethArg->isDefaultValueAvailable()) {
                     $Args[$ParamName] = $MethArg->getDefaultValue();
                 } else {
                     $Args[$ParamName] = 'REQUIRED';
                 }
             }
             $this->SetData('Args', $Args);
         } else {
             $Class = new ReflectionClass($Model);
             $Meths = $Class->getMethods();
             $Methods = array();
             foreach ($Meths as $Meth) {
                 $MethodName = $Meth->getName();
                 if (StringBeginsWith($MethodName, '_')) {
                     continue;
                 }
                 $MethArgs = $Meth->getParameters();
                 $Args = array();
                 foreach ($MethArgs as $Index => $MethArg) {
                     $ParamName = $MethArg->getName();
                     if ($MethArg->isDefaultValueAvailable()) {
                         $Args[$ParamName] = $MethArg->getDefaultValue();
                     } else {
                         $Args[$ParamName] = 'REQUIRED';
                     }
                 }
                 $Methods[$MethodName] = array('Method' => $MethodName, 'Args' => $Args);
             }
             $this->SetData('Methods', $Methods);
         }
     } else {
         if (!method_exists($Model, $MethodName)) {
             throw NotFoundException($ModelName . '->' . $MethodName . '()');
         }
         $MethodArgs = ReflectArgs($Callback, $this->Request->Get(), $Args);
         $Result = call_user_func_array($Callback, $MethodArgs);
         if (is_array($Result)) {
             $this->Data = $Result;
         } elseif (is_a($Result, 'Gdn_DataSet')) {
             $Result = $Result->ResultArray();
             $this->Data = $Result;
         } elseif (is_a($Result, 'stdClass')) {
             $this->Data = (array) $Result;
         } else {
             $this->SetData('Result', $Result);
         }
     }
     $this->Render();
 }