Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 373 lines (334 sloc) 8.138 kb
f8ec9deb »
2010-01-28 Initial version
1 <?php
2 /**
3 * PHP CLI Framework
4 *
5 * An open source command line interface framework for PHP 5.0 or newer.
6 *
7 * @package PHP CLI
8 * @author Tj Holowaychuk <tj@vision-media.ca>
9 * @copyright Copyright (c) 2008 Tj Holowaychuk
10 * @link http://cliframework.com
11 */
fc55434d »
2010-08-06 * White space
12
f8ec9deb »
2010-01-28 Initial version
13 class CLI {
fc55434d »
2010-08-06 * White space
14 /**
569eaf25 »
2010-08-06 * Move list constants into the class
15 * Bullet Lists.
16 */
17 const LIST_BULLET = 1;
18 const LIST_NUMERIC = 2;
19 const LIST_ALPHA = 3;
20
21 /**
fc55434d »
2010-08-06 * White space
22 * Version.
23 *
24 * @var string
25 */
26 const VERSION = '0.1';
27
28 /**
29 * Options.
30 *
31 * @var array
32 * @access public
33 * @since Version 0.1
34 */
35 static public $o;
569eaf25 »
2010-08-06 * Move list constants into the class
36
fc55434d »
2010-08-06 * White space
37 /**
38 * Option descriptions.
39 *
40 * @var array
41 * @access public
42 * @since Version 0.1
43 */
44 static public $od;
45
46 /**
47 * Set options.
48 *
49 * @param array $options
50 * Array of assoc options; option => description
51 * - Optional: 'v'
52 * - Requires value: 'd:'
53 * - Optional value: 'h::'
54 * - Note: only supported in PHP 5.3.x and greater
55 * @access public
56 * @since Version 0.1
57 * @todo support long options
58 * @todo format help better
59 */
60 static public function seto($options) {
61 self::$od = $options;
62 self::$o = getopt((string) implode((array) array_keys($options)));
63 }
64
65 /**
66 * Get option.
67 *
68 * @param string $option
69 *
70 * @return mixed
71 * - Option set without value required: TRUE
72 * - Option set value: Value returned
73 * - Required option set with value: Value returned
74 * - Option not set or value is not present: FALSE
75 *
76 * @access public
77 * @since Version 0.1
78 */
79 static public function geto($option) {
80 if (isset(self::$o[$option]) && $value = self::$o[$option]) {
81 return $value;
82 }
83
84 return array_key_exists($option, self::$o);
85 }
86
87 /**
88 * Get an argument value by index.
89 *
90 * @param int $i
91 * @return mixed
92 * - success: String
93 * - failure: FALSE
94 * @access public
95 * @since Version 0.1
96 * @todo check if the argument is an option, or how to handle this better
97 */
98 static public function getv($i) {
99 global $argv;
100 return (!empty($argv[$i])) ? $argv[$i] : FALSE;
101 }
102
103 /**
104 * Display help information.
105 *
106 * @access public
107 * @since Version 0.1
108 * @todo: hook for additional help, or global
109 * @todo: support php 5.30's :: optional values
110 * @todo: make a spacer theme, theme_list, theme_table, theme_spacer
111 */
112 static public function gethelp() {
113 $additional = array();
114
115 // Display options
116 echo self::theme_spacer('Options');
117
118 foreach ((array) self::$od AS $option => $description) {
119 if (strpos($option, '+') === 0) {
120 $additional[str_replace('+', '', $option)] = $description;
121 continue;
122 }
123 if (strstr($option, ':')) {
124 echo "\n -" . str_replace(':', '', $option) . " : {$description}";
125 } else {
126 echo "\n -" . $option . " : {$description}";
127 }
128 }
129
130 echo "\n" . self::theme_spacer() . "\n";
131
132 // Display additional
133 foreach ((array) $additional AS $caption => $description) {
134 echo self::theme_spacer($caption);
135 echo $description;
136 echo self::theme_spacer() . "\n";
137 }
138 }
139
140 /**
141 * Table output.
142 *
143 * @param array $rows
144 * @param array $headers
145 * (optional) Column headers.
146 * @param string $caption
147 * (optional) Table caption.
148 * @param $pad_type_headers
149 * (optional) Padding method.
150 * - STR_PAD_LEFT
151 * - STR_PAD_RIGHT
152 * - STR_PAD_BOTH
153 * @param $pad_type_cells
154 * (optional) Padding method.
155 * - STR_PAD_LEFT
156 * - STR_PAD_RIGHT
157 * - STR_PAD_BOTH
158 * @return string
159 * @access public
160 * @since Version 0.1
161 * @todo support and detect colspans
162 */
163 static public function theme_table($rows, $headers = array(), $caption = NULL, $pad_type_headers = STR_PAD_BOTH, $pad_type_cells = STR_PAD_RIGHT) {
164 $output = '';
165 $cl = array();
166 $clp = 0;
167
168 // Rows are manditory for the table to print
169 if (!count($rows)) {
170 return FALSE;
171 }
172
173 // Determine each columns length
174 foreach ((array) $headers AS $i => $header) {
175 $cl[$i] = strlen($header) > $cl[$i] ? strlen($header) : $cl[$i];
176 }
177 foreach ((array) $rows AS $row) {
178 foreach ((array) $row AS $i => $cell) {
179 $cl[$i] = strlen($cell) > $cl[$i] ? strlen($cell) : $cl[$i];
180 }
181 }
182
183 // Column length product
184 foreach ((array) $cl AS $l) {
185 $clp += $l;
186 }
187
188 // Caption
189 if ($caption) {
190 $output .= "\n ";
191 $output .= str_pad(" {$caption} ", $clp + ((count($cl) * 2) + 2), '-', STR_PAD_BOTH);
192 }
193 // Headers
194 if (count($headers)) {
195 $output .= "\n | ";
196 foreach ((array) $headers AS $i => $header) {
197 $output .= str_pad($header, $cl[$i], ' ', $pad_type_headers) . " | ";
198 }
199 }
200 // Rows
201 foreach ((array) $rows AS $row) {
202 $output .= "\n | ";
203 foreach ((array) $row AS $i => $cell) {
204 $output .= str_pad($cell, $cl[$i], ' ', $pad_type_cells) . " | ";
205 }
206 }
207 $output .= "\n";
208
209 return $output;
210 }
211
212 /**
213 * Spacer.
214 *
215 * @param string $caption
216 * (optional) Spacer caption.
217 * @return string
218 * @access public
219 * @since Version 0.1
220 */
221 static public function theme_spacer($caption = '') {
222 $caption = !empty($caption) ? $caption . ' ' : '';
223 return "\n " . str_pad($caption, 45, '-', STR_PAD_RIGHT) . "\n";
224 }
225
226 /**
227 * List.
228 *
229 * @param array $items
230 * @param string $caption
231 * (optional) List caption.
232 * @param int $list_type
233 * (optional) List style type.
569eaf25 »
2010-08-06 * Move list constants into the class
234 * - CLI::LIST_ALPHA
235 * - CLI::LIST_BULLET
236 * - CLI::LIST_NUMERIC
fc55434d »
2010-08-06 * White space
237 * @return string
238 * @access public
239 * @since Version 0.1
240 */
569eaf25 »
2010-08-06 * Move list constants into the class
241 static public function theme_list($items, $caption = NULL, $list_type = self::LIST_BULLET) {
fc55434d »
2010-08-06 * White space
242 $output = "\n";
243
244 // Caption
245 if ($caption) {
246 $output .= " {$caption} \n";
247 }
248
249 // List items
250 $output .= self::_list($items, $list_type);
251
252 return $output;
253 }
254
255 /**
256 * Item list helper.
257 *
258 * Loop menu items recursively to generate
259 * a item list formated via $list_type
260 *
261 * @see self::item_list
262 * @access protected
263 * @since Version 0.1
264 */
569eaf25 »
2010-08-06 * Move list constants into the class
265 static protected function _list($items, $list_type = self::LIST_BULLET, $depth = 0) {
fc55434d »
2010-08-06 * White space
266 static $list_id = 0;
267 $output = '';
268 $list_id++;
269
270 foreach ((array) $items AS $i => $item) {
271 if (is_array($item)) {
272 $output .= self::_list($item, $list_type, $depth + 1);
273 } else {
274 $output .= str_repeat(' ', $depth + 1) . self::_list_type($i, $list_id, $list_type, $depth) . ' ' . $item . " \n";
275 }
276 }
277
278 return $output;
279 }
280
281 /**
282 * Item list type helper.
283 *
284 * Based on the current depth of an item list
285 * return the proper bullet format based on
286 * the $list_type pram
287 *
288 * @see self::_list
289 * @access protected
290 * @since Version 0.1
291 */
569eaf25 »
2010-08-06 * Move list constants into the class
292 static protected function _list_type($i, $list_id, $list_type = self::LIST_BULLET, $depth = 0) {
fc55434d »
2010-08-06 * White space
293 static $lists;
294
295 $lists[$list_id][$depth]++;
296
297 switch ($list_type) {
569eaf25 »
2010-08-06 * Move list constants into the class
298 case self::LIST_ALPHA:
fc55434d »
2010-08-06 * White space
299 $output = !$depth ? chr(96 + (int) $lists[$list_id][$depth]) : '-';
300 break;
301
569eaf25 »
2010-08-06 * Move list constants into the class
302 case self::LIST_BULLET:
fc55434d »
2010-08-06 * White space
303 $output = '-';
304 break;
305
569eaf25 »
2010-08-06 * Move list constants into the class
306 case self::LIST_NUMERIC:
fc55434d »
2010-08-06 * White space
307 $output = !$depth ? (int) $lists[$list_id][$depth] : chr(96 + (int) $lists[$list_id][$depth]);
308 break;
309 }
310
569eaf25 »
2010-08-06 * Move list constants into the class
311 if ($list_type != self::LIST_BULLET) {
fc55434d »
2010-08-06 * White space
312 $output .= '.';
313 }
314
315 return $output;
316 }
317
318 /**
319 * Prompt user input.
320 *
321 * @param string $message
569eaf25 »
2010-08-06 * Move list constants into the class
322 * @return string Response.
fc55434d »
2010-08-06 * White space
323 * @access public
324 * @since Version 0.1
325 */
326 static public function prompt($message) {
327 echo $message . " \n";
328 return fgets(STDIN, 128);
329 }
330
331 /**
332 * Prompt user for password input
333 *
334 * @param string $message
569eaf25 »
2010-08-06 * Move list constants into the class
335 * @return string Response.
fc55434d »
2010-08-06 * White space
336 * @access public
337 * @since Version 0.2-dev
338 */
339 static public function password_prompt($message) {
340 echo $message . ' ';
341 system('stty -echo');
342 $password = trim(fgets(STDIN));
343 system('stty echo');
344 echo "\n";
345 return $password;
346 }
347
348 /**
349 * Output an error message, halting the program.
350 *
351 * @param string $message
352 * @access public
353 * @since Version 0.1
354 * @todo: support errorno's
355 * @todo: errorno map
356 */
357 static public function error($message) {
358 fwrite(STDERR, "\nError: {$message}\n");
359 exit;
360 }
361
362 /**
363 * Debug.
364 *
365 * @param mixed $var
366 * @access public
367 * @since Version 0.1
368 */
369 static public function dbg($var) {
370 echo "\n" . print_r($var) . "\n";
371 }
372
373 }
f8ec9deb »
2010-01-28 Initial version
374
Something went wrong with that request. Please try again.