1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
21:
22: App::uses('AppShell', 'Console/Command');
23: App::uses('File', 'Utility');
24:
25: 26: 27: 28: 29: 30: 31:
32: class ApiShell extends AppShell {
33:
34: 35: 36: 37: 38:
39: public $paths = array();
40:
41: 42: 43: 44: 45:
46: public function initialize() {
47: $this->paths = array_merge($this->paths, array(
48: 'behavior' => CAKE . 'Model' . DS . 'Behavior' . DS,
49: 'cache' => CAKE . 'Cache' . DS,
50: 'controller' => CAKE . 'Controller' . DS,
51: 'component' => CAKE . 'Controller' . DS . 'Component' . DS,
52: 'helper' => CAKE . 'View' . DS . 'Helper' . DS,
53: 'model' => CAKE . 'Model' . DS,
54: 'view' => CAKE . 'View' . DS,
55: 'core' => CAKE
56: ));
57: }
58:
59: 60: 61: 62: 63:
64: public function main() {
65: if (empty($this->args)) {
66: return $this->out($this->OptionParser->help());
67: }
68:
69: $type = strtolower($this->args[0]);
70:
71: if (isset($this->paths[$type])) {
72: $path = $this->paths[$type];
73: } else {
74: $path = $this->paths['core'];
75: }
76:
77: $count = count($this->args);
78: if ($count > 1) {
79: $file = Inflector::underscore($this->args[1]);
80: $class = Inflector::camelize($this->args[1]);
81: } elseif ($count) {
82: $file = $type;
83: $class = Inflector::camelize($type);
84: }
85: $objects = App::objects('class', $path);
86: if (in_array($class, $objects)) {
87: if (in_array($type, array('behavior', 'component', 'helper')) && $type !== $file) {
88: if (!preg_match('/' . Inflector::camelize($type) . '$/', $class)) {
89: $class .= Inflector::camelize($type);
90: }
91: }
92:
93: } else {
94: $this->error(__d('cake_console', '%s not found', $class));
95: }
96:
97: $parsed = $this->_parseClass($path . $class . '.php', $class);
98:
99: if (!empty($parsed)) {
100: if (isset($this->params['method'])) {
101: if (!isset($parsed[$this->params['method']])) {
102: $this->err(__d('cake_console', '%s::%s() could not be found', $class, $this->params['method']));
103: return $this->_stop();
104: }
105: $method = $parsed[$this->params['method']];
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(__d('cake_console', 'Select a number to see the more information about a specific method. q to quit. l to list.'), null, 'q'))) {
120: if ($number === 'q') {
121: $this->out(__d('cake_console', 'Done'));
122: return $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: public function getOptionParser() {
147: $parser = parent::getOptionParser();
148: $parser->addArgument('type', array(
149: 'help' => __d('cake_console', 'Either a full path or type of class (model, behavior, controller, component, view, helper)')
150: ))->addArgument('className', array(
151: 'help' => __d('cake_console', 'A CakePHP core class name (e.g: Component, HtmlHelper).')
152: ))->addOption('method', array(
153: 'short' => 'm',
154: 'help' => __d('cake_console', 'The specific method you want help on.')
155: ))->description(__d('cake_console', 'Lookup doc block comments for classes in CakePHP.'));
156: return $parser;
157: }
158:
159: 160: 161: 162: 163:
164: public function help() {
165: $head = "Usage: cake api [<type>] <className> [-m <method>]\n";
166: $head .= "-----------------------------------------------\n";
167: $head .= "Parameters:\n\n";
168:
169: $commands = array(
170: 'path' => "\t<type>\n" .
171: "\t\tEither a full path or type of class (model, behavior, controller, component, view, helper).\n" .
172: "\t\tAvailable values:\n\n" .
173: "\t\tbehavior\tLook for class in CakePHP behavior path\n" .
174: "\t\tcache\tLook for class in CakePHP cache path\n" .
175: "\t\tcontroller\tLook for class in CakePHP controller path\n" .
176: "\t\tcomponent\tLook for class in CakePHP component path\n" .
177: "\t\thelper\tLook for class in CakePHP helper path\n" .
178: "\t\tmodel\tLook for class in CakePHP model path\n" .
179: "\t\tview\tLook for class in CakePHP view path\n",
180: 'className' => "\t<className>\n" .
181: "\t\tA CakePHP core class name (e.g: Component, HtmlHelper).\n"
182: );
183:
184: $this->out($head);
185: if (!isset($this->args[1])) {
186: foreach ($commands as $cmd) {
187: $this->out("{$cmd}\n\n");
188: }
189: } elseif (isset($commands[strtolower($this->args[1])])) {
190: $this->out($commands[strtolower($this->args[1])] . "\n\n");
191: } else {
192: $this->out(__d('cake_console', 'Command %s not found', $this->args[1]));
193: }
194: }
195:
196: 197: 198: 199: 200: 201: 202: 203:
204: protected function _parseClass($path, $class) {
205: $parsed = array();
206:
207: if (!class_exists($class)) {
208: if (!include_once $path) {
209: $this->err(__d('cake_console', '%s could not be found', $path));
210: }
211: }
212:
213: $reflection = new ReflectionClass($class);
214:
215: foreach ($reflection->getMethods() as $method) {
216: if (!$method->isPublic() || strpos($method->getName(), '_') === 0) {
217: continue;
218: }
219: if ($method->getDeclaringClass()->getName() != $class) {
220: continue;
221: }
222: $args = array();
223: foreach ($method->getParameters() as $param) {
224: $paramString = '$' . $param->getName();
225: if ($param->isDefaultValueAvailable()) {
226: $paramString .= ' = ' . str_replace("\n", '', var_export($param->getDefaultValue(), true));
227: }
228: $args[] = $paramString;
229: }
230: $parsed[$method->getName()] = array(
231: 'comment' => str_replace(array('/*', '*/', '*'), '', $method->getDocComment()),
232: 'method' => $method->getName(),
233: 'parameters' => '(' . implode(', ', $args) . ')'
234: );
235: }
236: ksort($parsed);
237: return $parsed;
238: }
239:
240: }
241: