/** * Application PHP 5 constructor */ public function __construct() { parent::__construct(); /** * call Instance Error Handler */ ErrorHandler::singleton(); /** * Set Benchmark */ Benchmark::set('app', 'start'); /** * start buffer to make content overide */ ob_start(); /** * Check empty to prevent Multiple call */ if (empty(static::$x_record_app)) { /** * Prereserved Application * [APP, APPLICATION, ENPROJECT, CORE] */ // protect it static::$x_protected_app = array(static::$x_app_prefix . 'APP', static::$x_app_prefix . 'APPLICATION', static::$x_app_prefix . 'ENPROJECT', static::$x_app_prefix . 'CORE'); // set it foreach (static::$x_protected_app as $value) { static::$x_record_app[$value] = $this; } } }
/** * Agregate Display * * @return void */ private static final function displayRender() { // set 500 fatal error if (static::$x_is_fatal || Route::isFatalError()) { static::$x_is_fatal = true; // set again Route::setFatalError(); // set fatal error Response::setStatus(500); // set 500 } elseif (Route::isNoMatch()) { Response::setStatus(404); // set 404 } /** * check again if not set on boolean */ if (static::$x_is_request_head === null) { static::$x_is_request_head = Request::isHead(); } /** * Get Request * This as cached variable to prevent Being Overide */ $is_head_request = static::$x_is_request_head; /** * If not in Head request * get body content before and prepend it */ if (!$is_head_request) { // start buffer if not exists ob_get_level() || ob_start(); $body = ob_get_clean(); /** * Prepend The Body if there's some output before prepend it */ Response::prepend($body); } else { // if on head request set into empty string Response::setBody(''); } /** * Fetch status, header, and body */ list($status, $headers, $body) = Response::finalize(); /** * Serialize cookies (with optional encryption) * set cookie header into Response */ Response::serializeCookies($headers); /** * no headers hooks for fatal error */ if (!static::$x_is_fatal && !$is_head_request) { /** * Set OLD Header And status * for safe header request */ $old_headers = $headers->all(); $old_status = $headers->all(); /** * Doing Headers Hook * @var string */ $headers = Hook::apply('x_headers', $headers->all()); // if on hooks change headers has not array if (!is_array($headers)) { $headers = $old_headers; } /** * Doing Status Hook * @var string */ $status = (int) Hook::apply('x_header_status', $status); // if on hooks change status and that is invalid if (!Response::getMessageForCode($status)) { $status = $old_status; } // freed unset($old_headers, $old_status); } /** * for safe method, check if headers * has not already sent. * header will be send into client * that if header has been sent , the header set will be * thrown an error */ if (!headers_sent()) { /** * Send status header */ if (strpos(PHP_SAPI, 'cgi') === 0) { header(sprintf('Status: %s', Response::getMessageForCode($status))); } else { header(sprintf('HTTP/%s %s', Config::get('http_version', '1.1'), Response::getMessageForCode($status))); } /** * Send headers, getting all headers and set it */ foreach ($headers as $name => $value) { if (!is_string($value)) { continue; } $hValues = explode("\n", $value); foreach ($hValues as $hVal) { header("{$name}: {$hVal}", false); } } } /** * Hook Body / Output Content * @var string */ $body = Hook::apply('x_before_output', $body); /** * Send body, but only if it isn't a HEAD request */ if (!Request::isHead()) { /** * Hoks only available if no fatal */ if (!static::$x_is_fatal) { /** * Force tag Output */ if (Config::get('force_tag', false)) { // force balance the tags $body = Hook::apply('x_force_tag_output', Filter::forceBalanceTags($body), $body); } /** * Safe Output Check */ if (Config::get('safe_output', false)) { // Filtering multibyte entities and set entities into false $body = Hook::apply('x_safe_output', Filter::multibyteEntities($body, false), $body, false); } /** * Inject Error Info if on debug mode */ if (Config::get('debug', false)) { $error = ErrorHandler::HtmlError(); /** * Insert Into Body content if exists * if exist data-target='x_data_error' -> will be inserted here * or will be inserted into after open <body(.?)> tag */ if ($error && is_string($error)) { $body = Hook::apply('x_error_output', preg_match('/(<div\\s*(?:data\\-target\\=(\'|\\")([\\w:]*\\s+)?x_data_error(\\s+|$2)*)(?:[^>]*)>)/', $body) ? preg_replace('/(<div\\s*(?:data\\-target\\=(\'|\\")([\\w:]*\\s+)?x_data_error(\\s+|$2)*)(?:[^>]*)>(.*))/', "\$1{$error}\$2", $body) : (stripos($body, '<body') !== false && preg_match('/(<body\\s*(?:[^>]*)>)/i', $body) ? preg_replace('/(<body\\s*(?:[^>]*)>)/i', "\$1\n{$error}", $body) : preg_replace("/^\\s\\s(\\s*)/m", "\$1", $error) . "\n{$body}"), $body); } } } /** * set again end of application */ Benchmark::set('app', 'end'); /** * check if contains shortcode here about %[ * if exists will bereturning replace */ if (strpos($body, "%[") !== false) { $body = str_replace(array('%[benchmark]%', '%[memory]%', '%[real_memory]%', '%[\\benchmark\\]%', '%[\\memory\\]%', '%[\\real_memory\\]%'), array(round(Benchmark::get('app'), 6), StringHelper::sizeFormat(Benchmark::getMemory(), 2), StringHelper::sizeFormat(Benchmark::getRealMemory(), 2), '%[benchmark]%', '%[memory]%', '%[real_memory]%'), $body); /** * fix escaped * Above will be replace if only one */ strpos($body, "%[") !== false && ($body = preg_replace('/(\\%\\[)\\\\(\\\\+)(benchmark|memory|real\\_memory)\\\\(\\\\+)(\\]\\%)/', '$1$2$3$4$5', $body)); } /** * Clean Body Output from empty non ascii characters * set second parameters to false because this is not URL */ $body = StringHelper::removeInvisibleCharacters($body, false); /** * set response body */ Response::setBody(Hook::apply('x_before_output', $body)); if (!headers_sent() && in_array('Content-Length', headers_list())) { header('Content-Length: ' . Response::getLength(), true); } /** * freed memory */ unset($body, $headers); /** * starting buffer if buffer has been cleaned before */ ob_get_level() || ob_start(); /** * print output */ echo Response::getBody(); /** * Set Hook after output if not in Fatal */ if (!static::$x_is_fatal) { // do after Hook::doAction('x_after_output', Response::getBody()); /** * start buffer again if bugger is cleared */ ob_get_level() || ob_start(); /** * doing after all end of system */ Hook::doAction('x_after_all'); } /** * set response body to empty freed the memory * Reset Body */ Response::setBody(''); } // restore error handler -> end restore_error_handler(); }
/** * Serialize Response cookies into raw HTTP header * * @param \Enproject\ErSysDucation\Response\Header $header The Response header */ public static function serializeCookies(Headers &$header) { $instance = static::singleton(); $config = Config::singleton(); $cookies = $instance->cookies(); $prefix = $config->get('cookie_encrypt_prefix', 'enc|'); is_string($prefix) && trim($prefix) || ($prefix = 'enc|'); $config->cookie_encrypt = $config->get('cookie_encrypt', true); foreach ($cookies as $name => $settings) { if (is_string($settings['expires'])) { $expires = strtotime($settings['expires']); } else { $expires = (int) $settings['expires']; } /** * Check if is has encrypted value * if config cookie encrypt has true * and * (__ settings['encrypted'] = has null or not exists) * or not empty $settings['encrypted'] * @var boolean */ if (!empty($settings['encrypted']) || $config->cookie_encrypt && !isset($settings['encrypted'])) { // add prefix enc to make sure if cookie has encrypt $settings['value'] = $prefix . Security::encrypt($settings['value'], Sha1::hash($config->security_key . $config->security_salt . $config->session_hash)); } /** * Cookie only accept 4KB */ if (strlen($settings['value']) > 4096) { ErrorHandler::set(E_USER_WARNING, sprintf('Cookie %s has been generate more than 4KB failed to save! if there was cookie before, it will be not replaced!', $name), __FILE__, __LINE__); } else { // set header cookies static::setCookieHeader($header, $name, $settings); } } }