/** * Configures debugging for inKWell * * @access private * @return void */ private function configDebugging($config) { if (isset($config['error_level'])) { error_reporting($config['error_level']); } // // Return pretty much immediatley if we're on CLI // if (App\Core::checkSAPI('cli')) { ini_set('display_errors', 1); return; } if ($this->checkExecutionMode(EXEC_MODE_DEVELOPMENT)) { $display_errors = TRUE; } else { $display_errors = FALSE; } $display_errors = isset($config['display_errors']) ? $config['display_errors'] : $display_errors; if ($display_errors) { ini_set('display_errors', 1); if (class_exists('Tracy\\Debugger')) { Debugger::enable(Debugger::DEVELOPMENT, $this->getWriteDirectory('logs')); } else { App\Core::enableErrorHandling('html'); App\Core::enableExceptionHandling('html', 'time'); } } else { ini_set('display_errors', 0); if (isset($config['error_email_to'])) { if (class_exists('Tracy\\Debugger')) { Debugger::enable(Debugger::PRODUCTION, $this->getWriteDirectory('logs')); Debugger::$email = $config['error_email_to']; } else { App\Core::enableErrorHandling($config['error_email_to']); App\Core::enableExceptionHandling($config['error_email_to'], 'time'); } } } }
/** * Sends the response to the screen * * @access public * @param boolean $headers_only Whether or not we're only sending headers * @return integer The status of the request */ public function send($headers_only = FALSE) { $protocol = explode($_SERVER['SERVER_PROTOCOL'], '/'); $version = end($protocol); $aliases = array('1.0' => array(405 => 400, 406 => 400), '1.1' => array()); // // If for some reason we have been provided a NULL view we should try to // see if we have a default body for the response type. If we don't, let's // provide a legitimate no content response. // if ($this->view === NULL) { if (isset(self::$states[$this->status]['body'])) { $this->view = self::$states[$this->status]['body']; $this->view = App\Text::create($this->view)->compose(); } else { $this->code = 204; $this->status = HTTP\NO_CONTENT; } } // // We want to let any renderers work their magic before doing anything else. A // good renderer will do whatever it can to resolve the response to a string. // Otherwise whatever the response is will be casted as a (string) and may not do // what one expects. // // NOTE: This logic is kept separate from the if statement above, in the event // the default body for a response needs additional processing. // if ($this->view !== NULL) { if (isset(self::$renderFilters[$this->type])) { foreach (self::$renderFilters[$this->type] as $filter) { if ($filter::filter($this)) { break; } } } if (is_object($this->view)) { $view_class = get_class($this->view); $class_key = strtolower($view_class); if (isset(self::$renderMethods[$class_key])) { $method = self::$renderMethods[$class_key]; if (!is_callable([$this->view, $method])) { throw new Flourish\ProgrammerException('Cannot render view with registered non-callable method %s()', $method); } } elseif (is_callable([$this->view, '__toString'])) { $method = '__toString'; } else { throw new Flourish\ProgrammerException('Cannot render object of class %s, no rendering method available', $view_class); } $this->view = $this->view->{$method}(); } } $this->view = (string) $this->view; $this->code = isset($aliases[$version][$this->code]) ? $aliases[$version][$this->code] : $this->code; // // Now that our view is rendered to a string and we have our code looked up // we want to deal with caching and etag generation. // $etag = $this->request->getHeader('If-None-Match'); $cache_control = $this->request->getHeader('Cache-Control'); $cache_file = $this->cache($etag); if (!$cache_file) { $this->view = NULL; $this->status = 'Not Modified'; $this->code = 304; } else { $this->setHeader('Etag', $etag); if (strpos($cache_control, 'no-store') !== FALSE) { $cache_file->delete(); } } // // Output all of our headers. // // Apparently fastCGI explicitly does not like the standard header format, so // so we send different leading headers based on that. The content type downward, // however, is exactly the same. // $headers = [!App\Core::checkSAPI('cgi-fcgi') ? sprintf('%s %d %s', $_SERVER['SERVER_PROTOCOL'], $this->code, $this->status) : sprintf('Status: %d %s', $this->code, $this->status)]; if ($this->code != 204) { if (in_array($this->type, self::$textTypes)) { $headers[] = sprintf('Content-Type: %s; charset=utf-8', $this->type); } else { $headers[] = sprintf('Content-Type: %s', $this->type); } } if ($this->expireCache) { $headers[] = sprintf('Cache-Control: max-age=0, s-maxage=0, must-revalidate'); } elseif ($this->aging) { $cc_parts = ['must-revalidate', 'max-age=' . $this->aging]; if ($this->sharedAging) { $cc_parts[] = 's-maxage=' . $this->sharedAging; } if ($this->cacheVisibility) { $cc_parts[] = $this->cacheVisibility; } if ($this->noCache) { $cc_parts[] = 'no-cache'; } $headers[] = sprintf('Cache-Control: %s', implode(', ', $cc_parts)); } foreach ($this->headers as $header => $value) { if ($value !== NULL) { $headers[] = $header . ': ' . $value; } } if ($headers_only && App\Core::checkSAPI('cli')) { foreach ($headers as $header) { print $header . LB; } } else { foreach ($headers as $header) { header($header); } } if (!$headers_only) { print $this->view; } return $this->code; }