Resulting level can be greater than target level if a non-removable buffer has been encountered.
public static closeOutputBuffers ( integer $targetLevel, boolean $flush ) | ||
$targetLevel | integer | The target output buffering level |
$flush | boolean | Whether to flush or clean the buffers |
/** * @param int $startObLevel * * @return string */ protected function getAndCleanOutputBuffering($startObLevel) { if (ob_get_level() <= $startObLevel) { return ''; } Response::closeOutputBuffers($startObLevel + 1, true); return ob_get_clean(); }
/** * {@inheritdoc} * * Additional available options: * * * alt: an alternative URI to render in case of an error */ public function render($uri, Request $request, array $options = array()) { $reference = null; if ($uri instanceof ControllerReference) { $reference = $uri; // Remove attributes from the generated URI because if not, the Symfony // routing system will use them to populate the Request attributes. We don't // want that as we want to preserve objects (so we manually set Request attributes // below instead) $attributes = $reference->attributes; $reference->attributes = array(); // The request format and locale might have been overridden by the user foreach (array('_format', '_locale') as $key) { if (isset($attributes[$key])) { $reference->attributes[$key] = $attributes[$key]; } } $uri = $this->generateFragmentUri($uri, $request, false, false); $reference->attributes = array_merge($attributes, $reference->attributes); } $subRequest = $this->createSubRequest($uri, $request); // override Request attributes as they can be objects (which are not supported by the generated URI) if (null !== $reference) { $subRequest->attributes->add($reference->attributes); } $level = ob_get_level(); try { return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false); } catch (\Exception $e) { // we dispatch the exception event to trigger the logging // the response that comes back is simply ignored if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) { $event = new GetResponseForExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e); $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event); } // let's clean up the output buffers that were created by the sub-request Response::closeOutputBuffers($level, false); if (isset($options['alt'])) { $alt = $options['alt']; unset($options['alt']); return $this->render($alt, $request, $options); } if (!isset($options['ignore_errors']) || !$options['ignore_errors']) { throw $e; } return new Response(); } }
/** * Build a valid AJAX response for in-place saves that account for pre/post * save events. * * @param array $contenttype * @param integer $id * @param boolean $flush * * @return JsonResponse */ private function createJsonUpdate($contenttype, $id, $flush) { /* * Flush any buffers from saveConent() dispatcher hooks * and make sure our JSON output is clean. * * Currently occurs due to exceptions being generated in the dispatchers * in \Bolt\Storage::saveContent() * StorageEvents::PRE_SAVE * StorageEvents::POST_SAVE */ if ($flush) { Response::closeOutputBuffers(0, false); } // Get our record after POST_SAVE hooks are dealt with and return the JSON $content = $this->app['storage']->getContent($contenttype['slug'], ['id' => $id, 'returnsingle' => true, 'status' => '!undefined']); $val = []; foreach ($content->values as $key => $value) { // Some values are returned as \Twig_Markup and JSON can't deal with that if (is_array($value)) { foreach ($value as $subkey => $subvalue) { if (gettype($subvalue) === 'object' && get_class($subvalue) === 'Twig_Markup') { $val[$key][$subkey] = (string) $subvalue; } } } else { $val[$key] = $value; } } if (isset($val['datechanged'])) { $val['datechanged'] = date_format(new \DateTime($val['datechanged']), 'c'); } $lc = localeconv(); foreach ($contenttype['fields'] as $key => $values) { switch ($values['type']) { case 'float': // Adjust decimal point dependent on locale if ($lc['decimal_point'] === ',') { $val[$key] = str_replace('.', ',', $val[$key]); } break; } } // Unset flashbag for ajax $this->app['logger.flash']->clear(); return new JsonResponse($val); }
/** * Callback for register_shutdown_function() to handle fatal errors. * * @param \Silex\Application $app * @param boolean $flush */ public static function catchFatalErrors(Application $app, $flush = true) { if (self::$screen !== null) { echo self::$screen; return; } // Get last error, if any $error = error_get_last(); // Let Whoops handle AJAX requested fatal errors if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { return; } if ($error['type'] === E_ERROR || $error['type'] === E_PARSE) { $html = self::$html; // Flush the early error data buffered output from catchFatalErrorsEarly() if ($flush) { Response::closeOutputBuffers(0, false); } // Detect if we're being called from a core, an extension or vendor $isBoltCoreError = strpos($error['file'], $app['resources']->getPath('rootpath/src')); $isVendorError = strpos($error['file'], $app['resources']->getPath('rootpath/vendor')); $isExtensionError = strpos($error['file'], $app['resources']->getPath('extensions')); // Assemble error trace $errorblock = '<code style="display:block; white-space: pre-wrap;">Error: ' . $error['message'] . '</code><br>'; $errorblock .= '<code>File: ' . $error['file'] . '</code><br>'; $errorblock .= '<code>Line: ' . $error['line'] . '</code><br><br>'; if ($isBoltCoreError === 0) { $html = str_replace('%error_title%', 'PHP Fatal error: Bolt core', $html); $html = str_replace('%info%', '', $html); $message = $errorblock; } elseif ($isVendorError === 0) { $html = str_replace('%error_title%', 'PHP Fatal error: Vendor library', $html); $html = str_replace('%info%', '', $html); $message = $errorblock; } elseif ($isExtensionError === 0) { $base = str_replace($app['resources']->getPath('extensions'), '', $error['file']); $parts = explode(DIRECTORY_SEPARATOR, ltrim($base, '/')); $package = $parts[1] . '/' . $parts[2]; $html = str_replace('%error_title%', 'PHP Fatal error: Bolt extensions', $html); $html = str_replace('%info%', '<p>You will only be able to continue by disabling the extension by adding the following to app/config/extensions.yml:</p>' . '<p><code style="display:block;">' . $parts[1] . ':<br>' . ' ' . $parts[2] . ': false</code></p>', $html); $message = '<h4>There is a fatal error in the \'' . $package . '\' extension ' . 'loaded on your Bolt Installation.<h4>'; $message .= $errorblock; } else { // Unknown $html = str_replace('%error_title%', 'PHP Fatal error: Bolt generic', $html); $html = str_replace('%info%', '', $html); $message = $errorblock; } $message = nl2br($message); $html = str_replace('%error%', $message, $html); // Determine if we're on the command line. If so, don't output HTML. if (php_sapi_name() == 'cli') { $html = self::cleanHTML($html); } echo str_replace($app['resources']->getPath('rootpath'), '', $html); } echo self::$screen; }
/** * Fires `afterCommand` events. * * @param FilterResponseEvent $event * * @return \Symfony\Component\HttpFoundation\Response|static */ public function afterCommand(FilterResponseEvent $event) { /* @var $dispatcher EventDispatcher */ $dispatcher = $this['dispatcher']; $commandName = $event->getRequest()->get('command'); $eventName = CKFinderEvent::AFTER_COMMAND_PREFIX . lcfirst($commandName); $afterCommandEvent = new AfterCommandEvent($this, $commandName, $event->getResponse()); $dispatcher->dispatch($eventName, $afterCommandEvent); // #161 Clear any garbage from the output Response::closeOutputBuffers(0, false); $event->setResponse($afterCommandEvent->getResponse()); }
/** * Build a valid AJAX response for in-place saves that account for pre/post * save events. * * @param Content $content * @param boolean $flush * * @return JsonResponse */ private function createJsonUpdate(Content $content, $flush) { /* * Flush any buffers from saveConent() dispatcher hooks * and make sure our JSON output is clean. * * Currently occurs due to exceptions being generated in the dispatchers * in \Bolt\Storage::saveContent() * StorageEvents::PRE_SAVE * StorageEvents::POST_SAVE */ if ($flush) { Response::closeOutputBuffers(0, false); } $val = $content->toArray(); if (isset($val['datechanged'])) { $val['datechanged'] = (new Carbon($val['datechanged']))->toIso8601String(); } // Adjust decimal point as some locales use a comma and… JavaScript $lc = localeconv(); $fields = $this->app['config']->get('contenttypes/' . $content->getContenttype() . '/fields'); foreach ($fields as $key => $values) { if ($values['type'] === 'float' && $lc['decimal_point'] === ',') { $val[$key] = str_replace('.', ',', $val[$key]); } } // Unset flashbag for ajax $this->app['logger.flash']->clear(); return new JsonResponse($val); }
/** * {@inheritdoc} */ public function terminate(Request $request, Response $response) { if (false === $this->booted) { return; } if ($this->getHttpKernel() instanceof TerminableInterface) { if (!$this->debug) { if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } elseif ('cli' !== PHP_SAPI) { Response::closeOutputBuffers(0, true); } } $this->getHttpKernel()->terminate($request, $response); } }
/** * Extends the execution time of the script * * @param int $currentTime current timestamp */ protected function extendExecutionTime($currentTime) { if ($currentTime - $this->lastExtendExecutionTime >= self::EXTEND_EXECUTION_INTERVAL) { set_time_limit(30); $this->lastExtendExecutionTime = $currentTime; // Emit some whitespaces for Nginx + FPM configuration to avoid 504 Gateway Timeout error if (function_exists('fastcgi_finish_request')) { // Clear the buffer to remove any garbage before flushing Response::closeOutputBuffers(0, false); echo ' '; @ob_end_flush(); @flush(); } } }