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