/** * Process the given URL, creating the appropriate controller and executing it. * * Request processing is handled as follows: * - Director::direct() creates a new SS_HTTPResponse object and passes this to Director::handleRequest(). * - Director::handleRequest($request) checks each of the Director rules and identifies a controller to handle this * request. * - Controller::handleRequest($request) is then called. This will find a rule to handle the URL, and call the rule * handling method. * - RequestHandler::handleRequest($request) is recursively called whenever a rule handling method returns a * RequestHandler object. * * In addition to request processing, Director will manage the session, and perform the output of the actual response * to the browser. * * @param $url String, the URL the user is visiting, without the querystring. * @uses handleRequest() rule-lookup logic is handled by this. * @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call. */ static function direct($url, DataModel $model) { // Validate $_FILES array before merging it with $_POST foreach ($_FILES as $k => $v) { if (is_array($v['tmp_name'])) { $v = ArrayLib::array_values_recursive($v['tmp_name']); foreach ($v as $tmpFile) { if ($tmpFile && !is_uploaded_file($tmpFile)) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } else { if ($v['tmp_name'] && !is_uploaded_file($v['tmp_name'])) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } $req = new SS_HTTPRequest(isset($_SERVER['X-HTTP-Method-Override']) ? $_SERVER['X-HTTP-Method-Override'] : $_SERVER['REQUEST_METHOD'], $url, $_GET, array_merge((array) $_POST, (array) $_FILES), @file_get_contents('php://input')); // Load the request headers. If we're not running on Apache, then we // need to manually extract the headers from the $_SERVER array. if (function_exists('apache_request_headers')) { $headers = apache_request_headers(); } else { $headers = self::extract_request_headers($_SERVER); } foreach ($headers as $header => $value) { $req->addHeader($header, $value); } // Load the session into the controller $session = new Session(isset($_SESSION) ? $_SESSION : null); $result = Director::handleRequest($req, $session, $model); $session->inst_save(); // Return code for a redirection request if (is_string($result) && substr($result, 0, 9) == 'redirect:') { $response = new SS_HTTPResponse(); $response->redirect(substr($result, 9)); $response->output(); // Handle a controller } else { if ($result) { if ($result instanceof SS_HTTPResponse) { $response = $result; } else { $response = new SS_HTTPResponse(); $response->setBody($result); } // ?debug_memory=1 will output the number of bytes of memory used for this request if (isset($_REQUEST['debug_memory']) && $_REQUEST['debug_memory']) { Debug::message(sprintf("Peak memory usage in bytes: %s", number_format(memory_get_peak_usage(), 0))); } else { $response->output(); } //$controllerObj->getSession()->inst_save(); } } }
/** * Process the given URL, creating the appropriate controller and executing it. * * Request processing is handled as follows: * - Director::direct() creates a new SS_HTTPResponse object and passes this to Director::handleRequest(). * - Director::handleRequest($request) checks each of the Director rules and identifies a controller to handle this * request. * - Controller::handleRequest($request) is then called. This will find a rule to handle the URL, and call the rule * handling method. * - RequestHandler::handleRequest($request) is recursively called whenever a rule handling method returns a * RequestHandler object. * * In addition to request processing, Director will manage the session, and perform the output of the actual response * to the browser. * * @param $url String, the URL the user is visiting, without the querystring. * @uses handleRequest() rule-lookup logic is handled by this. * @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call. */ static function direct($url) { // Validate $_FILES array before merging it with $_POST foreach ($_FILES as $k => $v) { if (is_array($v['tmp_name'])) { $v = ArrayLib::array_values_recursive($v['tmp_name']); foreach ($v as $tmpFile) { if ($tmpFile && !is_uploaded_file($tmpFile)) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } else { if ($v['tmp_name'] && !is_uploaded_file($v['tmp_name'])) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } $req = new SS_HTTPRequest(isset($_SERVER['X-HTTP-Method-Override']) ? $_SERVER['X-HTTP-Method-Override'] : $_SERVER['REQUEST_METHOD'], $url, $_GET, array_merge((array) $_POST, (array) $_FILES), @file_get_contents('php://input')); // @todo find better way to extract HTTP headers if (isset($_SERVER['HTTP_ACCEPT'])) { $req->addHeader("Accept", $_SERVER['HTTP_ACCEPT']); } if (isset($_SERVER['CONTENT_TYPE'])) { $req->addHeader("Content-Type", $_SERVER['CONTENT_TYPE']); } if (isset($_SERVER['HTTP_REFERER'])) { $req->addHeader("Referer", $_SERVER['HTTP_REFERER']); } // Load the session into the controller $session = new Session(isset($_SESSION) ? $_SESSION : null); $result = Director::handleRequest($req, $session); $session->inst_save(); // Return code for a redirection request if (is_string($result) && substr($result, 0, 9) == 'redirect:') { $response = new SS_HTTPResponse(); $response->redirect(substr($result, 9)); $response->output(); // Handle a controller } else { if ($result) { if ($result instanceof SS_HTTPResponse) { $response = $result; } else { $response = new SS_HTTPResponse(); $response->setBody($result); } // ?debug_memory=1 will output the number of bytes of memory used for this request if (isset($_REQUEST['debug_memory']) && $_REQUEST['debug_memory']) { Debug::message(sprintf("Peak memory usage in bytes: %s", number_format(memory_get_peak_usage(), 0))); } else { $response->output(); } //$controllerObj->getSession()->inst_save(); } } }
/** * Process the given URL, creating the appropriate controller and executing it. * * Request processing is handled as follows: * - Director::direct() creates a new SS_HTTPResponse object and passes this to * Director::handleRequest(). * - Director::handleRequest($request) checks each of the Director rules and identifies a controller * to handle this request. * - Controller::handleRequest($request) is then called. This will find a rule to handle the URL, * and call the rule handling method. * - RequestHandler::handleRequest($request) is recursively called whenever a rule handling method * returns a RequestHandler object. * * In addition to request processing, Director will manage the session, and perform the output of * the actual response to the browser. * * @uses handleRequest() rule-lookup logic is handled by this. * @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call. * * @param string $url * @param DataModel $model * * @throws SS_HTTPResponse_Exception */ public static function direct($url, DataModel $model) { // Validate $_FILES array before merging it with $_POST foreach ($_FILES as $k => $v) { if (is_array($v['tmp_name'])) { $v = ArrayLib::array_values_recursive($v['tmp_name']); foreach ($v as $tmpFile) { if ($tmpFile && !is_uploaded_file($tmpFile)) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } else { if ($v['tmp_name'] && !is_uploaded_file($v['tmp_name'])) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } $req = new SS_HTTPRequest(isset($_SERVER['X-HTTP-Method-Override']) ? $_SERVER['X-HTTP-Method-Override'] : $_SERVER['REQUEST_METHOD'], $url, $_GET, ArrayLib::array_merge_recursive((array) $_POST, (array) $_FILES), @file_get_contents('php://input')); $headers = self::extract_request_headers($_SERVER); foreach ($headers as $header => $value) { $req->addHeader($header, $value); } // Initiate an empty session - doesn't initialize an actual PHP session until saved (see below) $session = Injector::inst()->create('Session', isset($_SESSION) ? $_SESSION : array()); // Only resume a session if its not started already, and a session identifier exists if (!isset($_SESSION) && Session::request_contains_session_id()) { $session->inst_start(); } $output = Injector::inst()->get('RequestProcessor')->preRequest($req, $session, $model); if ($output === false) { // @TODO Need to NOT proceed with the request in an elegant manner throw new SS_HTTPResponse_Exception(_t('Director.INVALID_REQUEST', 'Invalid request'), 400); } $result = Director::handleRequest($req, $session, $model); // Save session data. Note that inst_save() will start/resume the session if required. $session->inst_save(); // Return code for a redirection request if (is_string($result) && substr($result, 0, 9) == 'redirect:') { $url = substr($result, 9); if (Director::is_cli()) { // on cli, follow SilverStripe redirects automatically return Director::direct(str_replace(Director::absoluteBaseURL(), '', $url), DataModel::inst()); } else { $response = new SS_HTTPResponse(); $response->redirect($url); $res = Injector::inst()->get('RequestProcessor')->postRequest($req, $response, $model); if ($res !== false) { $response->output(); } } // Handle a controller } elseif ($result) { if ($result instanceof SS_HTTPResponse) { $response = $result; } else { $response = new SS_HTTPResponse(); $response->setBody($result); } $res = Injector::inst()->get('RequestProcessor')->postRequest($req, $response, $model); if ($res !== false) { $response->output(); } else { // @TODO Proper response here. throw new SS_HTTPResponse_Exception("Invalid response"); } //$controllerObj->getSession()->inst_save(); } }
/** * Called on save, it creates the appropriate objects and writes them * to the database. * * @param SS_List $dataObjects * @param boolean $existingValues If set to TRUE, it tries to find existing objects * based on the database IDs passed as array keys in $dataObjects parameter. * If set to FALSE, it will always create new object (default: TRUE) * @return array Array of saved object IDs in the key, and the status ("Updated") in the value */ function saveData($dataObjects, $existingValues = true) { if(!$dataObjects) return false; $savedObjIds = array(); $fieldset = $this->FieldSetForRow(); // add hiddenfields if($this->extraData) { foreach($this->extraData as $fieldName => $fieldValue) { $fieldset->push(new HiddenField($fieldName)); } } $form = new Form($this, null, $fieldset, new FieldList()); foreach ($dataObjects as $objectid => $fieldValues) { // 'new' counts as an empty column, don't save it if($objectid === "new") continue; // extra data was creating fields, but if($this->extraData) { $fieldValues = array_merge( $this->extraData, $fieldValues ); } // either look for an existing object, or create a new one if($existingValues) { $obj = DataObject::get_by_id($this->sourceClass(), $objectid); } else { $sourceClass = $this->sourceClass(); $obj = new $sourceClass(); } // Legacy: Use the filter as a predefined relationship-ID if($this->filterField && $this->filterValue) { $filterField = $this->filterField; $obj->$filterField = $this->filterValue; } // Determine if there is changed data for saving $dataFields = array(); foreach($fieldValues as $type => $value) { // if the field is an actual datafield (not a preset hiddenfield) if(is_array($this->extraData)) { if(!in_array($type, array_keys($this->extraData))) { $dataFields[$type] = $value; } // all fields are real } else { $dataFields[$type] = $value; } } $dataValues = ArrayLib::array_values_recursive($dataFields); // determine if any of the fields have a value (loose checking with empty()) $hasData = false; foreach($dataValues as $value) { if(!empty($value)) $hasData = true; } if($hasData) { $form->loadDataFrom($fieldValues, true); $form->saveInto($obj); $objectid = $obj->write(); $savedObjIds[$objectid] = "Updated"; } } return $savedObjIds; }
/** * Called on save, it creates the appropriate objects and writes them * to the database. */ function saveData($dataObjects,$ExistingValues = true) { $savedObj = array(); $fieldset = $this->FieldSetForRow(); // add hiddenfields if($this->extraData) { foreach($this->extraData as $fieldName => $fieldValue) { $fieldset->push(new HiddenField($fieldName)); } } $form = new Form($this, null, $fieldset, new FieldSet()); if($dataObjects) { foreach ($dataObjects as $objectid => $fieldValues) { // we have to "sort" new data first, and process it in a seperate saveData-call (see setValue()) if($objectid === "new") continue; // extra data was creating fields, but if($this->extraData) { $fieldValues = array_merge( $this->extraData, $fieldValues ); } $hasData = false; $obj = new $this->sourceClass(); if($ExistingValues) { $obj = DataObject::get_by_id($this->sourceClass, $objectid); } // Legacy: Use the filter as a predefined relationship-ID if($this->filterField && $this->filterValue) { $filterField = $this->filterField; $obj->$filterField = $this->filterValue; } // Determine if there is changed data for saving $dataFields = array(); foreach($fieldValues as $type => $value) { if(is_array($this->extraData)){ // if the field is an actual datafield (not a preset hiddenfield) if(!in_array($type, array_keys($this->extraData))) { $dataFields[$type] = $value; } } else { // all fields are real $dataFields[$type] = $value; } } $dataValues = ArrayLib::array_values_recursive($dataFields); foreach($dataValues as $value) { if(!empty($value)) { $hasData = true; } } // save if($hasData) { $form->loadDataFrom($fieldValues, true); $form->saveInto($obj); $objectid = $obj->write(); $savedObj[$objectid] = "Updated"; } } return $savedObj; } else { return false; } }
/** * Process the given URL, creating the appropriate controller and executing it. * * Request processing is handled as follows: * - Director::direct() creates a new SS_HTTPResponse object and passes this to Director::handleRequest(). * - Director::handleRequest($request) checks each of the Director rules and identifies a controller to handle this * request. * - Controller::handleRequest($request) is then called. This will find a rule to handle the URL, and call the rule * handling method. * - RequestHandler::handleRequest($request) is recursively called whenever a rule handling method returns a * RequestHandler object. * * In addition to request processing, Director will manage the session, and perform the output of the actual response * to the browser. * * @param $url String, the URL the user is visiting, without the querystring. * @uses handleRequest() rule-lookup logic is handled by this. * @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call. */ static function direct($url, DataModel $model) { // Validate $_FILES array before merging it with $_POST foreach ($_FILES as $k => $v) { if (is_array($v['tmp_name'])) { $v = ArrayLib::array_values_recursive($v['tmp_name']); foreach ($v as $tmpFile) { if ($tmpFile && !is_uploaded_file($tmpFile)) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } else { if ($v['tmp_name'] && !is_uploaded_file($v['tmp_name'])) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } $req = new SS_HTTPRequest(isset($_SERVER['X-HTTP-Method-Override']) ? $_SERVER['X-HTTP-Method-Override'] : $_SERVER['REQUEST_METHOD'], $url, $_GET, ArrayLib::array_merge_recursive((array) $_POST, (array) $_FILES), @file_get_contents('php://input')); $headers = self::extract_request_headers($_SERVER); foreach ($headers as $header => $value) { $req->addHeader($header, $value); } // Only resume a session if its not started already, and a session identifier exists if (!isset($_SESSION) && (isset($_COOKIE[session_name()]) || isset($_REQUEST[session_name()]))) { Session::start(); } // Initiate an empty session - doesn't initialize an actual PHP session until saved (see belwo) $session = new Session(isset($_SESSION) ? $_SESSION : null); $output = Injector::inst()->get('RequestProcessor')->preRequest($req, $session, $model); if ($output === false) { // @TODO Need to NOT proceed with the request in an elegant manner throw new SS_HTTPResponse_Exception(_t('Director.INVALID_REQUEST', 'Invalid request'), 400); } $result = Director::handleRequest($req, $session, $model); // Save session data (and start/resume it if required) $session->inst_save(); // Return code for a redirection request if (is_string($result) && substr($result, 0, 9) == 'redirect:') { $response = new SS_HTTPResponse(); $response->redirect(substr($result, 9)); $res = Injector::inst()->get('RequestProcessor')->postRequest($req, $response, $model); if ($res !== false) { $response->output(); } // Handle a controller } else { if ($result) { if ($result instanceof SS_HTTPResponse) { $response = $result; } else { $response = new SS_HTTPResponse(); $response->setBody($result); } $res = Injector::inst()->get('RequestProcessor')->postRequest($req, $response, $model); if ($res !== false) { // ?debug_memory=1 will output the number of bytes of memory used for this request if (isset($_REQUEST['debug_memory']) && $_REQUEST['debug_memory']) { Debug::message(sprintf("Peak memory usage in bytes: %s", number_format(memory_get_peak_usage(), 0))); } else { $response->output(); } } else { // @TODO Proper response here. throw new SS_HTTPResponse_Exception("Invalid response"); } //$controllerObj->getSession()->inst_save(); } } }