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