a tiny mvc framework for php using php-activerecord
1<?php
2/*
3 based on phpa by David Phillips <david@acz.org>
4 http://david.acz.org/phpa/ says "This software is public domain."
5*/
6
7namespace HalfMoon;
8
9class Console {
10 private $args;
11 public static $have_readline;
12 public $line;
13 public $history;
14
15 public function __construct($args) {
16 $this->args = $args;
17
18 Console::$have_readline = function_exists("readline");
19
20 for ($x = 1; $x < count($args); $x++)
21 switch ($args[$x]) {
22 case "-h":
23 case "--help":
24 $this->usage();
25 break;
26
27 default:
28 if (substr($args[$x], 0, 1) == "-")
29 $this->usage();
30 elseif (defined("HALFMOON_ENV"))
31 $this->usage();
32 else
33 define("HALFMOON_ENV", $args[$x]);
34 }
35
36 require_once(__DIR__ . "/../halfmoon.php");
37
38 error_reporting(E_ALL | E_STRICT);
39
40 ini_set("error_log", NULL);
41 ini_set("log_errors", 1);
42 ini_set("html_errors", 0);
43 ini_set("display_errors", 0);
44
45 while (ob_get_level())
46 ob_end_clean();
47
48 ob_implicit_flush(true);
49
50 /* TODO: forcibly load models so they're in the tab-completion cache */
51
52 print "Loaded " . HALFMOON_ENV . " environment (halfmoon)\n";
53
54 $this->loop();
55 }
56
57 public function usage() {
58 die("usage: " . $this->args[0] . " [-h] [environment]\n");
59 }
60
61 public function readline_complete($line, $pos, $cursor) {
62 $consts = array_keys(get_defined_constants());
63 $vars = array_keys($GLOBALS);
64 $funcs = get_defined_functions();
65 $classes = get_declared_classes();
66
67 return array_merge($consts, $vars, $funcs, $classes);
68 }
69
70 public function loop() {
71 for (;;) {
72 if (Console::$have_readline) {
73 readline_completion_function(array($this,
74 "readline_complete"));
75 $this->line = @readline(">> ");
76 } else {
77 print ">> ";
78 $this->line = trim(fgets(STDIN));
79 }
80
81 if ($this->line === false ||
82 (!Console::$have_readline && feof(STDIN))) {
83 echo "\n";
84 break;
85 }
86
87 if (strlen($this->line) == 0)
88 continue;
89
90 if (Console::$have_readline && (!isset($this->history) ||
91 ($this->line != $this->history))) {
92 readline_add_history($this->line);
93 $this->history = $this->line;
94 }
95
96 if ($this->is_immediate($this->line))
97 $this->line = "return (" . $this->line . ")";
98
99 ob_start();
100
101 try {
102 $ret = @eval($this->line . ";");
103
104 if (ob_get_length() == 0) {
105 if (is_bool($ret))
106 echo ($ret ? "true" : "false");
107 else if (is_string($ret))
108 echo "'" . addcslashes($ret, "\0..\37\177..\377") . "'";
109 else if (!is_null($ret))
110 print_r($ret);
111 }
112
113 unset($ret);
114 } catch (\Exception $exception) {
115 $title = get_class($exception);
116
117 /* activerecord includes the stack trace in the message, so strip
118 * it out */
119 if ($exception instanceof \ActiveRecord\DatabaseException)
120 $title .= ": " . preg_replace("/\nStack trace:.*/s", "",
121 $exception->getMessage());
122 elseif ($exception->getMessage())
123 $title .= ": " . $exception->getMessage() . " in "
124 . $exception->getFile() . " on line "
125 . $exception->getLine();
126
127 print $title . "\n";
128
129 foreach ($exception->getTrace() as $call)
130 print " "
131 . (isset($call["file"]) ? $call["file"] : $call["class"])
132 . ":"
133 . (isset($call["line"]) ? $call["line"] : "")
134 . " in " . $call["function"] . "()\n";
135 }
136
137 $out = ob_get_contents();
138 ob_end_clean();
139
140 if ((strlen($out) > 0) && (substr($out, -1) != "\n"))
141 $out .= "\n";
142
143 echo $out;
144
145 unset($out);
146 }
147 }
148
149 public function is_immediate($line) {
150 $skip = array("class", "declare", "die", "echo", "exit", "for",
151 "foreach", "function", "global", "if", "include",
152 "include_once", "print", "require", "require_once",
153 "return", "static", "switch", "unset", "while");
154 $okeq = array("===", "!==", "==", "!=", "<=", ">=");
155 $code = "";
156 $sq = false;
157 $dq = false;
158 for ($i = 0; $i < strlen($line); $i++) {
159 $c = $line{$i};
160 if ($c == "'")
161 $sq = !$sq;
162 else if ($c == '"')
163 $dq = !$dq;
164 else if (($sq) || ($dq)) {
165 if ($c == "\\")
166 $i++;
167 } else
168 $code .= $c;
169 }
170
171 $code = str_replace($okeq, "", $code);
172
173 if (strcspn($code, ";{=") != strlen($code))
174 return false;
175
176 foreach (preg_split("/[^A-Za-z0-9_]/", $code) as $i)
177 if (in_array($i, $skip))
178 return false;
179
180 return true;
181 }
182}
183
184?>