body; } public function jsonSerialize(){ return [ 'code'=> $this->code, 'headers'=> $this->headers, 'body'=> $this->body ]; } public function clear(){ if($this->open){ $this->fire('clear'); $this->body = ''; } return $this; } public function clear_headers(){ if($this->open){ $this->fire('clear_headers'); $this->headers = []; } return $this; } public function clear_header(string $name){ foreach($this->headers as $key => $header){ if($header[0] == $name){ $this->fire('clear_header', $name); array_splice($this->headers, $key, 1); } } return $this; } public function write(string $chunk){ $this->fire('write', $chunk); if($this->open){ $this->body .= $chunk; $this->clear_header('Content-Length') ->header('Content-Length', strlen($this->body)); } return $this; } public function json($json){ if(is_array($json)){ array_walk_recursive($json, function(&$item, $key){ if(!mb_detect_encoding($item, 'utf-8', true)){ $item = utf8_encode($item); } }); } $this->fire('json', $json); $this->write(json_encode($json)); if(json_last_error() != JSON_ERROR_NONE){ throw new \Exception(json_last_error_msg()); } return $this; } public function header(string $name, string $value = null){ if(is_null($value)){ $headers = array_filter($this->headers,function($header) use($name){ return $header[0] == $name; }); return end($headers)[1]; }else{ if($this->open){ if($this->fire('header', $name, $value) !== false){ $this->headers[] = [ $name, $value ]; } } } return $this; } public function redirect(string $url){ $this->fire('redirect', $url); $this->header('Location', Router::url($url)); return $this; } public function end(string $chunk=''){ if($this->open){ $this->write($chunk); $this->fire('end'); $this->open = false; } return $this; } public function img(Image $img, string $type = null){ if(!$type){ $type = $img->type; } $this->fire('image', $img, $type); $this->clear_header('Content-Type') ->header('Content-Type', 'image/'.$type); if(!is_a($img, 'Image')){ $img = new Image(100, 20); $img->text('Invalid Image',0,0,'black',12); } ob_start(); $img(); $this->write(ob_get_contents()); ob_end_clean(); return $this; } public function code(int $code=null){ if(is_null($code)){ return $this->code; } $this->fire('code', $code); $this->code = $code; return $this; } public function shutdown(){ if(!$this->shutdown){ $this->shutdown = true; $this->fire('beforeshutdown'); if($this->open){ $this->end(); } $this->fire('shutdown'); http_response_code($this->code); foreach($this->headers as $k => $header){ header("{$header[0]}: $header[1]", false); } echo $this->body; flush(); $this->fire('aftershutdown'); } return $this; } public function open(bool $force = false){ if($force){ $this->shutdown = false; } if(!$this->shutdown){ $this->open = true; } return $this; } public static function gen_locale(string $folder){ $path = realpath($folder); if($path !== false){ foreach(glob("{$path}/*/LC_MESSAGES/*.po") as $po_file){ $mo_file = dirname($po_file).'/'.basename($po_file, '.po').'.mo'; if(!file_exists($mo_file)){ MsgFmt::convert($po_file, $mo_file); } } }else{ trigger_error("Locale folder {$folder} missing", E_USER_WARNING); } } public static function locale(string $locale, string $domain, string $folder, string $codeset = 'UTF-8'){ $path = realpath($folder); if($path !== false){ bindtextdomain($domain, $path); textdomain($domain); bind_textdomain_codeset($domain, $codeset); $orig_locale = $locale; self::gen_locale($path); if(!file_exists("{$path}/$locale/LC_MESSAGES/{$domain}.mo")){ $locale = \Locale::getPrimaryLanguage($locale); if(!file_exists("{$path}/$locale/LC_MESSAGES/{$domain}.mo")){ $locale = \Locale::getDefault(); if(!file_exists("{$path}/$locale/LC_MESSAGES/{$domain}.mo")){ $dir = dir("{$path}/"); do{ $locale = $dir->read(); if($locale === false){ trigger_error("Unable to find fallback locale for {$orig_locale}", E_USER_WARNING); break; } }while(!file_exists("{$path}/$locale/LC_MESSAGES/{$domain}.mo")); } } } }else{ trigger_error("Locale folder {$folder} missing", E_USER_WARNING); } \Locale::setDefault($locale); } } ?>