1: <?php
2:
3: /**
4: * Output content
5: * @package framework
6: * @subpackage output
7: */
8:
9: /**
10: * Base class that controls how data is output
11: * @abstract
12: */
13: abstract class Hm_Output {
14:
15: /**
16: * Extended classes must override this method to output content
17: * @param mixed $content data to output
18: * @param array $headers headers to send
19: * @return void
20: */
21: abstract protected function output_content($content, $headers);
22:
23: /**
24: * Wrapper around extended class output_content() calls
25: * @param mixed $response data to output
26: * @param array $input raw module data
27: * @return void
28: */
29: public function send_response($response, $input = []) {
30: $this->output_content($response, $input['http_headers'] ?? []);
31: }
32: }
33:
34: /**
35: * Output request responses using HTTP
36: */
37: class Hm_Output_HTTP extends Hm_Output {
38:
39: /**
40: * Send HTTP headers
41: * @param array $headers headers to send
42: * @return void
43: */
44: protected function output_headers($headers) {
45: foreach ($headers as $name => $value) {
46: Hm_Functions::header($name.': '.$value);
47: }
48: }
49:
50: /**
51: * Send response content to the browser
52: * @param mixed $content data to send
53: * @param array $headers HTTP headers to set
54: * @return void
55: */
56: protected function output_content($content, $headers = []) {
57: $this->output_headers($headers);
58: ob_end_clean();
59: echo $content;
60: }
61: }
62:
63: /**
64: * Message list struct used for user notices and system debug
65: */
66: trait Hm_List {
67:
68: /* message list */
69: private static $msgs = [];
70:
71: /**
72: * Add a message
73: * @param string $string message to add
74: * @return void
75: */
76: public static function add($string, $type = 'success') {
77: $string = self::str($string, false);
78: $texts = self::get();
79: if (! in_array($string, $texts, true)) {
80: self::$msgs[] = ['type' => $type, 'text' => $string];
81: }
82: }
83:
84: /**
85: * Return all messages
86: * @return array all messages
87: */
88: public static function getRaw() {
89: return self::$msgs;
90: }
91:
92: /**
93: * Flush all messages
94: * @return null
95: */
96: public static function flush() {
97: self::$msgs = [];
98: }
99:
100: /**
101: * Stringify a value
102: * @param mixed $mixed value to stringify
103: * @return string
104: */
105: public static function str($mixed, $return_type = true) {
106: $type = gettype($mixed);
107: if (in_array($type, array('array', 'object'), true)) {
108: $str = print_r($mixed, true);
109: } elseif ($return_type) {
110: $str = sprintf("%s: %s", $type, $mixed);
111: } else {
112: $str = (string) $mixed;
113: }
114: return $str;
115: }
116:
117: public static function get() {
118: return array_map(function ($msg) {
119: return $msg['text'];
120: }, self::$msgs);
121: }
122:
123: /**
124: * Log all messages
125: * @return bool
126: */
127: public static function show() {
128: $msgs = array_map(function ($msg) {
129: return strtoupper($msg['type']) . ': ' . $msg['text'];
130: }, self::$msgs);
131: return Hm_Functions::error_log(print_r($msgs, true));
132: }
133: }
134:
135: /**
136: * Notices the user sees
137: */
138: class Hm_Msgs { use Hm_List; }
139:
140: /**
141: * System debug notices
142: */
143: class Hm_Debug {
144:
145: use Hm_List {
146: add as protected self_add;
147: }
148:
149: /**
150: * @override
151: */
152: public static function add($string, $type = 'danger') {
153: self::self_add($string, $type);
154: }
155:
156: /**
157: * Add page execution stats to the Hm_Debug list
158: * @return void
159: */
160: public static function load_page_stats() {
161: self::add(sprintf("PHP version %s", phpversion()), 'info');
162: self::add(sprintf("Zend version %s", zend_version()), 'info');
163: self::add(sprintf("Peak Memory: %d", (memory_get_peak_usage(true)/1024)), 'info');
164: self::add(sprintf("PID: %d", getmypid()), 'info');
165: self::add(sprintf("Included files: %d", count(get_included_files())), 'info');
166: }
167: }
168:
169: /**
170: * Easy to use error logging
171: * @param mixed $mixed vaule to send to the log
172: * @return boolean|null
173: */
174: function elog($mixed) {
175: if (DEBUG_MODE) {
176: $bt = debug_backtrace();
177: $caller = array_shift($bt);
178: Hm_Debug::add(sprintf('ELOG called in %s at line %d', $caller['file'], $caller['line']));
179: return Hm_Functions::error_log(Hm_Debug::str($mixed));
180: }
181: }
182: