PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/sites/all/modules/azure/phpazure/library/Microsoft/Console/Command.php

https://bitbucket.org/priyadarshan_salkar/thinkshaddi
PHP | 398 lines | 229 code | 44 blank | 125 comment | 29 complexity | 8438c54141425b7cbe15bd9b8350bf6d MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, AGPL-1.0
  1. <?php
  2. /**
  3. * Copyright (c) 2009 - 2011, RealDolmen
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * * Neither the name of RealDolmen nor the
  14. * names of its contributors may be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  26. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. *
  28. * @category Microsoft
  29. * @package Microsoft_Console
  30. * @version $Id: Exception.php 55733 2011-01-03 09:17:16Z unknown $
  31. * @copyright Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
  32. * @license http://phpazure.codeplex.com/license
  33. */
  34. /**
  35. * @see Microsoft_AutoLoader
  36. */
  37. require_once dirname(__FILE__) . '/../AutoLoader.php';
  38. /**
  39. * @category Microsoft
  40. * @package Microsoft_Console
  41. * @copyright Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
  42. * @license http://phpazure.codeplex.com/license
  43. */
  44. class Microsoft_Console_Command
  45. {
  46. /**
  47. * The handler.
  48. *
  49. * @var array
  50. */
  51. protected $_handler;
  52. /**
  53. * Gets the handler.
  54. *
  55. * @return array
  56. */
  57. public function getHandler()
  58. {
  59. return $this->_handler;
  60. }
  61. /**
  62. * Sets the handler.
  63. *
  64. * @param array $handler
  65. * @return Microsoft_Console_Command
  66. */
  67. public function setHandler($handler)
  68. {
  69. $this->_handler = $handler;
  70. return $this;
  71. }
  72. /**
  73. * Replaces PHP's error handler
  74. *
  75. * @param mixed $errno
  76. * @param mixed $errstr
  77. * @param mixed $errfile
  78. * @param mixed $errline
  79. */
  80. public static function phpstderr($errno, $errstr, $errfile, $errline)
  81. {
  82. self::stderr($errno . ': Error in ' . $errfile . ':' . $errline . ' - ' . $errstr);
  83. }
  84. /**
  85. * Replaces PHP's exception handler
  86. *
  87. * @param Exception $exception
  88. */
  89. public static function phpstdex($exception)
  90. {
  91. self::stderr('Error: ' . $exception->getMessage());
  92. }
  93. /**
  94. * Writes output to STDERR, followed by a newline (optional)
  95. *
  96. * @param string $errorMessage
  97. * @param string $newLine
  98. */
  99. public static function stderr($errorMessage, $newLine = true)
  100. {
  101. if (error_reporting() === 0) {
  102. return;
  103. }
  104. file_put_contents('php://stderr', $errorMessage . ($newLine ? "\r\n" : ''));
  105. }
  106. /**
  107. * Bootstrap the shell command.
  108. *
  109. * @param array $argv PHP argument values.
  110. */
  111. public static function bootstrap($argv)
  112. {
  113. // Abort bootstrapping depending on the MICROSOFT_CONSOLE_COMMAND_HOST constant.
  114. if (defined('MICROSOFT_CONSOLE_COMMAND_HOST') && strtolower(MICROSOFT_CONSOLE_COMMAND_HOST) != 'console') {
  115. return;
  116. }
  117. // Replace error handler
  118. set_error_handler(array('Microsoft_Console_Command', 'phpstderr'));
  119. set_exception_handler(array('Microsoft_Console_Command', 'phpstdex'));
  120. // Build the application model
  121. $model = self::_buildModel();
  122. // Find a class that corresponds to the $argv[0] script name
  123. $requiredHandlerName = str_replace('.bat', '', str_replace('.sh', '', str_replace('.php', '', strtolower(basename($argv[0])))));
  124. $handler = null;
  125. foreach ($model as $possibleHandler) {
  126. if ($possibleHandler->handler == strtolower($requiredHandlerName)) {
  127. $handler = $possibleHandler;
  128. break;
  129. }
  130. }
  131. if (is_null($handler)) {
  132. self::stderr("No class found that implements handler " . $requiredHandlerName . ".");
  133. die();
  134. }
  135. // Find a method that matches the command name
  136. $command = null;
  137. foreach ($handler->commands as $possibleCommand) {
  138. if (in_array(strtolower(isset($argv[1]) ? $argv[1] : '<default>'), $possibleCommand->aliases)) {
  139. $command = $possibleCommand;
  140. break;
  141. }
  142. }
  143. if (is_null($command)) {
  144. self::stderr("No method found that implements command " . (isset($argv[1]) ? $argv[1] : '<default>') . ".");
  145. die();
  146. }
  147. // Parse parameter values
  148. $parameterValues = array();
  149. $parameterInputs = array_splice($argv, 2);
  150. foreach ($command->parameters as $parameter) {
  151. // Default value: null
  152. $value = null;
  153. // Consult value providers for value. First one wins.
  154. foreach ($parameter->valueproviders as $valueProviderName) {
  155. $valueProvider = new $valueProviderName();
  156. $value = $valueProvider->getValueForParameter($parameter, $parameterInputs);
  157. if (!is_null($value)) {
  158. break;
  159. }
  160. }
  161. if (is_null($value) && $parameter->required) {
  162. self::stderr("Error: Missing parameter: " . $parameter->aliases[0]);
  163. die();
  164. }
  165. // Set value
  166. $parameterValues[] = $value;
  167. $argvValues[$parameter->aliases[0]] = $value;
  168. }
  169. // Supply argv in a nice way
  170. $parameterValues['argv'] = $parameterInputs;
  171. // Run the command
  172. $className = $handler->class;
  173. $classInstance = new $className();
  174. $classInstance->setHandler($handler);
  175. call_user_func_array(array($classInstance, $command->method), $parameterValues);
  176. // Restore error handler
  177. restore_exception_handler();
  178. restore_error_handler();
  179. }
  180. /**
  181. * Builds the handler model.
  182. *
  183. * @return array
  184. */
  185. protected static function _buildModel()
  186. {
  187. $model = array();
  188. $classes = get_declared_classes();
  189. foreach ($classes as $class) {
  190. $type = new ReflectionClass($class);
  191. $handlers = self::_findValueForDocComment('@command-handler', $type->getDocComment());
  192. $handlerDescriptions = self::_findValueForDocComment('@command-handler-description', $type->getDocComment());
  193. $handlerHeaders = self::_findValueForDocComment('@command-handler-header', $type->getDocComment());
  194. $handlerFooters = self::_findValueForDocComment('@command-handler-footer', $type->getDocComment());
  195. for ($hi = 0; $hi < count($handlers); $hi++) {
  196. $handler = $handlers[$hi];
  197. $handlerDescription = isset($handlerDescriptions[$hi]) ? $handlerDescriptions[$hi] : isset($handlerDescriptions[0]) ? $handlerDescriptions[0] : '';
  198. $handlerDescription = str_replace('\r\n', "\r\n", $handlerDescription);
  199. $handlerDescription = str_replace('\n', "\n", $handlerDescription);
  200. $handlerModel = (object)array(
  201. 'handler' => strtolower($handler),
  202. 'description' => $handlerDescription,
  203. 'headers' => $handlerHeaders,
  204. 'footers' => $handlerFooters,
  205. 'class' => $class,
  206. 'commands' => array()
  207. );
  208. $methods = $type->getMethods();
  209. foreach ($methods as $method) {
  210. $commands = self::_findValueForDocComment('@command-name', $method->getDocComment());
  211. for ($x = 0; $x < count($commands); $x++) {
  212. $commands[$x] = strtolower($commands[$x]);
  213. }
  214. $commandDescriptions = self::_findValueForDocComment('@command-description', $method->getDocComment());
  215. $commandExamples = self::_findValueForDocComment('@command-example', $method->getDocComment());
  216. if (count($commands) > 0) {
  217. $command = $commands[0];
  218. $commandDescription = isset($commandDescriptions[0]) ? $commandDescriptions[0] : '';
  219. $commandModel = (object)array(
  220. 'command' => $command,
  221. 'aliases' => $commands,
  222. 'description' => $commandDescription,
  223. 'examples' => $commandExamples,
  224. 'class' => $class,
  225. 'method' => $method->getName(),
  226. 'parameters' => array()
  227. );
  228. $parameters = $method->getParameters();
  229. $parametersFor = self::_findValueForDocComment('@command-parameter-for', $method->getDocComment());
  230. for ($pi = 0; $pi < count($parameters); $pi++) {
  231. // Initialize
  232. $parameter = $parameters[$pi];
  233. $parameterFor = null;
  234. // Is it a "catch-all" parameter?
  235. if ($parameter->getName() == 'argv') {
  236. continue;
  237. }
  238. // Find the $parametersFor with the same name defined
  239. foreach ($parametersFor as $possibleParameterFor) {
  240. $possibleParameterFor = explode(' ', $possibleParameterFor, 4);
  241. if ($possibleParameterFor[0] == '$' . $parameter->getName()) {
  242. $parameterFor = $possibleParameterFor;
  243. break;
  244. }
  245. }
  246. if (is_null($parameterFor)) {
  247. die('@command-parameter-for missing for parameter $' . $parameter->getName());
  248. }
  249. $parameterModel = (object)array(
  250. 'name' => '$' . $parameter->getName(),
  251. 'valueproviders' => explode('|', $parameterFor[1]),
  252. 'aliases' => explode('|', $parameterFor[2]),
  253. 'description' => (isset($parameterFor[3]) ? $parameterFor[3] : ''),
  254. 'required' => (isset($parameterFor[3]) ? strpos(strtolower($parameterFor[3]), 'required') !== false && strpos(strtolower($parameterFor[3]), 'required if') === false : false),
  255. );
  256. // Add to model
  257. $commandModel->parameters[] = $parameterModel;
  258. }
  259. // Add to model
  260. $handlerModel->commands[] = $commandModel;
  261. }
  262. }
  263. // Add to model
  264. $model[] = $handlerModel;
  265. }
  266. }
  267. return $model;
  268. }
  269. /**
  270. * Finds the value for a specific docComment.
  271. *
  272. * @param string $docCommentName Comment name
  273. * @param unknown_type $docComment Comment object
  274. * @return array
  275. */
  276. protected static function _findValueForDocComment($docCommentName, $docComment)
  277. {
  278. $returnValue = array();
  279. $commentLines = explode("\n", $docComment);
  280. foreach ($commentLines as $commentLine) {
  281. if (strpos($commentLine, $docCommentName . ' ') !== false) {
  282. $returnValue[] = trim(substr($commentLine, strpos($commentLine, $docCommentName) + strlen($docCommentName) + 1));
  283. }
  284. }
  285. return $returnValue;
  286. }
  287. /**
  288. * Display information on an object
  289. *
  290. * @param object $object Object
  291. * @param array $propertiesToDump Property names to display
  292. */
  293. protected function _displayObjectInformation($object, $propertiesToDump = array())
  294. {
  295. foreach ($propertiesToDump as $property) {
  296. printf('%-16s: %s' . "\r\n", $property, $object->$property);
  297. }
  298. printf("\r\n");
  299. }
  300. /**
  301. * Displays the help information.
  302. *
  303. * @command-name <default>
  304. * @command-name -h
  305. * @command-name -help
  306. * @command-description Displays the current help information.
  307. */
  308. public function helpCommand() {
  309. $handler = $this->getHandler();
  310. $newline = "\r\n";
  311. if (count($handler->headers) > 0) {
  312. foreach ($handler->headers as $header) {
  313. printf('%s%s', $header, $newline);
  314. }
  315. printf($newline);
  316. }
  317. printf('%s%s', $handler->description, $newline);
  318. printf($newline);
  319. printf('Available commands:%s', $newline);
  320. foreach ($handler->commands as $command) {
  321. $description = str_split($command->description, 50);
  322. printf(' %-25s %s%s', implode(', ', $command->aliases), $description[0], $newline);
  323. for ($di = 1; $di < count($description); $di++) {
  324. printf(' %-25s %s%s', '', $description[$di], $newline);
  325. }
  326. printf($newline);
  327. if (count($command->parameters) > 0) {
  328. foreach ($command->parameters as $parameter) {
  329. $description = str_split($parameter->description, 50);
  330. printf(' %-23s %s%s', implode(', ', $parameter->aliases), $description[0], $newline);
  331. for ($di = 1; $di < count($description); $di++) {
  332. printf(' %-23s %s%s', '', $description[$di], $newline);
  333. }
  334. printf($newline);
  335. }
  336. }
  337. printf($newline);
  338. if (count($command->examples) > 0) {
  339. printf(' Example usage:%s', $newline);
  340. foreach ($command->examples as $example) {
  341. printf(' %s%s', $example, $newline);
  342. }
  343. printf($newline);
  344. }
  345. }
  346. if (count($handler->footers) > 0) {
  347. printf($newline);
  348. foreach ($handler->footers as $footer) {
  349. printf('%s%s', $footer, $newline);
  350. }
  351. printf($newline);
  352. }
  353. }
  354. }