1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27: 28: 29: 30: 31: 32:
33: class ApiShell extends Shell {
34: 35: 36: 37: 38: 39:
40: var $paths = array();
41: 42: 43: 44: 45:
46: function initialize () {
47: $this->paths = array_merge($this->paths, array(
48: 'behavior' => LIBS . 'model' . DS . 'behaviors' . DS,
49: 'cache' => LIBS . 'cache' . DS,
50: 'controller' => LIBS . 'controller' . DS,
51: 'component' => LIBS . 'controller' . DS . 'components' . DS,
52: 'helper' => LIBS . 'view' . DS . 'helpers' . DS,
53: 'model' => LIBS . 'model' . DS,
54: 'view' => LIBS . 'view' . DS,
55: 'core' => LIBS
56: ));
57: }
58: 59: 60: 61: 62:
63: function main() {
64: if (empty($this->args)) {
65: return $this->help();
66: }
67:
68: $type = strtolower($this->args[0]);
69:
70: if (isset($this->paths[$type])) {
71: $path = $this->paths[$type];
72: } else {
73: $path = $this->paths['core'];
74: }
75:
76: if (count($this->args) == 1) {
77: $file = $type;
78: $class = Inflector::camelize($type);
79: } elseif (count($this->args) > 1) {
80: $file = Inflector::underscore($this->args[1]);
81: $class = Inflector::camelize($file);
82: }
83:
84: $objects = Configure::listObjects('class', $path);
85: if (in_array($class, $objects)) {
86: if (in_array($type, array('behavior', 'component', 'helper')) && $type !== $file) {
87: if (!preg_match('/' . Inflector::camelize($type) . '$/', $class)) {
88: $class .= Inflector::camelize($type);
89: }
90: }
91:
92: } else {
93: $this->err(sprintf(__("%s not found", true), $class));
94: $this->_stop();
95: }
96:
97: $parsed = $this->__parseClass($path . $file .'.php');
98:
99: if (!empty($parsed)) {
100: if (isset($this->params['m'])) {
101: if (!isset($parsed[$this->params['m']])) {
102: $this->err(sprintf(__("%s::%s() could not be found", true), $class, $this->params['m']));
103: $this->_stop();
104: }
105: $method = $parsed[$this->params['m']];
106: $this->out($class .'::'.$method['method'] . $method['parameters']);
107: $this->hr();
108: $this->out($method['comment'], true);
109: } else {
110: $this->out(ucwords($class));
111: $this->hr();
112: $i = 0;
113: foreach ($parsed as $method) {
114: $list[] = ++$i . ". " . $method['method'] . $method['parameters'];
115: }
116: $this->out($list);
117:
118: $methods = array_keys($parsed);
119: while ($number = strtolower($this->in(__('Select a number to see the more information about a specific method. q to quit. l to list.', true), null, 'q'))) {
120: if ($number === 'q') {
121: $this->out(__('Done', true));
122: $this->_stop();
123: }
124:
125: if ($number === 'l') {
126: $this->out($list);
127: }
128:
129: if (isset($methods[--$number])) {
130: $method = $parsed[$methods[$number]];
131: $this->hr();
132: $this->out($class .'::'.$method['method'] . $method['parameters']);
133: $this->hr();
134: $this->out($method['comment'], true);
135: }
136: }
137: }
138: }
139: }
140:
141: 142: 143: 144: 145:
146: function help() {
147: $head = "Usage: cake api [<type>] <className> [-m <method>]\n";
148: $head .= "-----------------------------------------------\n";
149: $head .= "Parameters:\n\n";
150:
151: $commands = array(
152: 'path' => "\t<type>\n" .
153: "\t\tEither a full path or type of class (model, behavior, controller, component, view, helper).\n".
154: "\t\tAvailable values:\n\n".
155: "\t\tbehavior\tLook for class in CakePHP behavior path\n".
156: "\t\tcache\tLook for class in CakePHP cache path\n".
157: "\t\tcontroller\tLook for class in CakePHP controller path\n".
158: "\t\tcomponent\tLook for class in CakePHP component path\n".
159: "\t\thelper\tLook for class in CakePHP helper path\n".
160: "\t\tmodel\tLook for class in CakePHP model path\n".
161: "\t\tview\tLook for class in CakePHP view path\n",
162: 'className' => "\t<className>\n" .
163: "\t\tA CakePHP core class name (e.g: Component, HtmlHelper).\n"
164: );
165:
166: $this->out($head);
167: if (!isset($this->args[1])) {
168: foreach ($commands as $cmd) {
169: $this->out("{$cmd}\n\n");
170: }
171: } elseif (isset($commands[strtolower($this->args[1])])) {
172: $this->out($commands[strtolower($this->args[1])] . "\n\n");
173: } else {
174: $this->out("Command '" . $this->args[1] . "' not found");
175: }
176: }
177:
178: 179: 180: 181: 182: 183: 184: 185: 186:
187: function __parseClass($path) {
188: $parsed = array();
189:
190: $File = new File($path);
191: if (!$File->exists()) {
192: $this->err(sprintf(__("%s could not be found", true), $File->name));
193: $this->_stop();
194: }
195:
196: $contents = $File->read();
197:
198: if (preg_match_all('%(/\\*\\*[\\s\\S]*?\\*/)(\\s+function\\s+\\w+)(\\(.*\\))%', $contents, $result, PREG_PATTERN_ORDER)) {
199: foreach ($result[2] as $key => $method) {
200: $method = str_replace('function ', '', trim($method));
201:
202: if (strpos($method, '__') === false && $method[0] != '_') {
203: $parsed[$method] = array(
204: 'comment' => str_replace(array('/*', '*/', '*'), '', trim($result[1][$key])),
205: 'method' => $method,
206: 'parameters' => trim($result[3][$key])
207: );
208: }
209: }
210: }
211: ksort($parsed);
212: return $parsed;
213: }
214: }
215: ?>