/** * Test a URL request, returning a response object. * * This method is the counterpart of Director::direct() that is used in functional testing. It will execute the URL given, * * @param string $url The URL to visit * @param array $postVars The $_POST & $_FILES variables * @param Session $session The {@link Session} object representing the current session. By passing the same object to multiple * calls of Director::test(), you can simulate a persisted session. * @param string $httpMethod The HTTP method, such as GET or POST. It will default to POST if postVars is set, GET otherwise. * Overwritten by $postVars['_method'] if present. * @param string $body The HTTP body * @param array $headers HTTP headers with key-value pairs * @param array $cookies to populate $_COOKIE * @return SS_HTTPResponse * * @uses getControllerForURL() The rule-lookup logic is handled by this. * @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call. */ static function test($url, $postVars = null, $session = null, $httpMethod = null, $body = null, $headers = null, $cookies = null) { // These are needed so that calling Director::test() doesnt muck with whoever is calling it. // Really, it's some inappropriate coupling and should be resolved by making less use of statics $oldStage = Versioned::current_stage(); $getVars = array(); if (!$httpMethod) { $httpMethod = $postVars || is_array($postVars) ? "POST" : "GET"; } if (!$session) { $session = new Session(null); } // Back up the current values of the superglobals $existingRequestVars = isset($_REQUEST) ? $_REQUEST : array(); $existingGetVars = isset($_GET) ? $_GET : array(); $existingPostVars = isset($_POST) ? $_POST : array(); $existingSessionVars = isset($_SESSION) ? $_SESSION : array(); $existingCookies = isset($_COOKIE) ? $_COOKIE : array(); $existingServer = isset($_SERVER) ? $_SERVER : array(); $existingCookieReportErrors = Cookie::report_errors(); $existingRequirementsBackend = Requirements::backend(); Cookie::set_report_errors(false); Requirements::set_backend(new Requirements_Backend()); // Handle absolute URLs if (@parse_url($url, PHP_URL_HOST) != '') { $bits = parse_url($url); $_SERVER['HTTP_HOST'] = $bits['host']; $url = Director::makeRelative($url); } $urlWithQuerystring = $url; if (strpos($url, '?') !== false) { list($url, $getVarsEncoded) = explode('?', $url, 2); parse_str($getVarsEncoded, $getVars); } // Replace the superglobals with appropriate test values $_REQUEST = array_merge((array) $getVars, (array) $postVars); $_GET = (array) $getVars; $_POST = (array) $postVars; $_SESSION = $session ? $session->inst_getAll() : array(); $_COOKIE = (array) $cookies; $_SERVER['REQUEST_URI'] = Director::baseURL() . $urlWithQuerystring; $req = new SS_HTTPRequest($httpMethod, $url, $getVars, $postVars, $body); if ($headers) { foreach ($headers as $k => $v) { $req->addHeader($k, $v); } } $result = Director::handleRequest($req, $session); // Restore the superglobals $_REQUEST = $existingRequestVars; $_GET = $existingGetVars; $_POST = $existingPostVars; $_SESSION = $existingSessionVars; $_COOKIE = $existingCookies; $_SERVER = $existingServer; Cookie::set_report_errors($existingCookieReportErrors); Requirements::set_backend($existingRequirementsBackend); // These are needed so that calling Director::test() doesnt muck with whoever is calling it. // Really, it's some inappropriate coupling and should be resolved by making less use of statics Versioned::reading_stage($oldStage); return $result; }
static function set_report_errors($reportErrors) { self::$report_errors = $reportErrors; }
/** * Run the task, and do the business * * @param SS_HTTPRequest $httpRequest */ function run($httpRequest) { require_once 'Zend/Log/Writer/Stream.php'; SS_Log::add_writer(new Zend_Log_Writer_Stream('php://output'), SS_Log::NOTICE); $db = DB::getConn(); if (method_exists($db, 'supportsLocks') && $db->supportsLocks() && !$db->getLock('ScheduledPublishing')) { $this->log('Publication has already been triggered by a different process'); return; } Cookie::$report_errors = false; if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = true; } if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = true; } $this->log('Looking for changes that need to be published'); $bt = defined('DB::USE_ANSI_SQL') ? "\"" : "`"; $wfRequests = DataObject::get('WorkflowRequest', "{$bt}Status{$bt} = 'Scheduled' AND {$bt}EmbargoDate{$bt} <= '" . SS_Datetime::now()->getValue() . "'"); $this->log(sprintf('Found %d pages', $wfRequests ? count($wfRequests) : 0)); $admin = Security::findAnAdministrator(); $admin->logIn(); if (count($wfRequests)) { foreach ($wfRequests as $request) { // Use a try block to prevent one bad request // taking down the whole queue try { $page = $request->Page(); $this->log(sprintf("Attempting to publish '%s' (URL: %s)", $page->Title, $page->AbsoluteLink())); // We remove the embargo date and republish to trigger this. $request->EmbargoDate = null; $result = $request->publish('Page was embargoed. Automatically published.', WorkflowSystemMember::get(), false); $this->log(sprintf("Published '%s' (URL: %s)", $page->Title, $page->AbsoluteLink())); } catch (Exception $e) { // Log it? $this->log(sprintf("Failed to publish '%s (URL: %s)", $page->Title, $page->AbsoluteLink())); user_error("Error publishing change to Page ID " . $request->PageID . " - " . $request->Page()->Title . " Error: " . $e->getMessage(), E_USER_WARNING); continue; } } } $this->log('Looking for live pages that need to be expired'); $pagesToExpire = Versioned::get_by_stage('SiteTree', 'Live', "\"ExpiryDate\" <= '" . SS_Datetime::now()->getValue() . "'"); $this->log(sprintf('Found %d pages', $pagesToExpire ? count($pagesToExpire) : 0)); if (count($pagesToExpire)) { foreach ($pagesToExpire as $page) { // Use a try block to prevent one bad request // taking down the whole queue try { $this->log(sprintf("Attempting to unpublish '%s' (URL: %s)", $page->Title, $page->AbsoluteLink())); // Close any existing workflows if ($wf = $page->openWorkflowRequest()) { $this->log(sprintf("Closing '%s' workflow request for '%s'", $wf->Status, $page->Title)); $wf->deny('Page automatically expired. Removing from Live site.', $admin); } $page->ExpiryDate = null; $page->write(); $page->doUnpublish(); $this->log(sprintf("Unpublished '%s' (URL: %s)", $page->Title, $page->AbsoluteLink())); } catch (Exception $e) { $this->log(sprintf("Failed to unpublish '%s' (URL: %s)", $page->Title, $page->AbsoluteLink())); user_error("Error unpublishing Page ID " . $page->ID . " - " . $page->Title . " Error: " . $e->getMessage(), E_USER_WARNING); continue; } } } // We don't need to clear the lock on every potential exception, // as the closing of the DB connection will do that for us. if (method_exists($db, 'supportsLocks') && $db->supportsLocks()) { $db->releaseLock('ScheduledPublishing'); } }
/** * @param bool */ protected function inst_set_report_errors($reportErrors) { self::$report_errors = $reportErrors; }