Chris@0: presenter = $presenter; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function configure() Chris@0: { Chris@0: list($grep, $insensitive, $invert) = FilterOptions::getOptions(); Chris@0: Chris@0: $this Chris@0: ->setName('ls') Chris@0: ->setAliases(['list', 'dir']) Chris@0: ->setDefinition([ Chris@0: new CodeArgument('target', CodeArgument::OPTIONAL, 'A target class or object to list.'), Chris@0: Chris@0: new InputOption('vars', '', InputOption::VALUE_NONE, 'Display variables.'), Chris@0: new InputOption('constants', 'c', InputOption::VALUE_NONE, 'Display defined constants.'), Chris@0: new InputOption('functions', 'f', InputOption::VALUE_NONE, 'Display defined functions.'), Chris@0: new InputOption('classes', 'k', InputOption::VALUE_NONE, 'Display declared classes.'), Chris@0: new InputOption('interfaces', 'I', InputOption::VALUE_NONE, 'Display declared interfaces.'), Chris@0: new InputOption('traits', 't', InputOption::VALUE_NONE, 'Display declared traits.'), Chris@0: Chris@0: new InputOption('no-inherit', '', InputOption::VALUE_NONE, 'Exclude inherited methods, properties and constants.'), Chris@0: Chris@0: new InputOption('properties', 'p', InputOption::VALUE_NONE, 'Display class or object properties (public properties by default).'), Chris@0: new InputOption('methods', 'm', InputOption::VALUE_NONE, 'Display class or object methods (public methods by default).'), Chris@0: Chris@0: $grep, Chris@0: $insensitive, Chris@0: $invert, Chris@0: Chris@0: new InputOption('globals', 'g', InputOption::VALUE_NONE, 'Include global variables.'), Chris@0: new InputOption('internal', 'n', InputOption::VALUE_NONE, 'Limit to internal functions and classes.'), Chris@0: new InputOption('user', 'u', InputOption::VALUE_NONE, 'Limit to user-defined constants, functions and classes.'), Chris@0: new InputOption('category', 'C', InputOption::VALUE_REQUIRED, 'Limit to constants in a specific category (e.g. "date").'), Chris@0: Chris@0: new InputOption('all', 'a', InputOption::VALUE_NONE, 'Include private and protected methods and properties.'), Chris@0: new InputOption('long', 'l', InputOption::VALUE_NONE, 'List in long format: includes class names and method signatures.'), Chris@0: ]) Chris@0: ->setDescription('List local, instance or class variables, methods and constants.') Chris@0: ->setHelp( Chris@0: <<<'HELP' Chris@0: List variables, constants, classes, interfaces, traits, functions, methods, Chris@0: and properties. Chris@0: Chris@0: Called without options, this will return a list of variables currently in scope. Chris@0: Chris@0: If a target object is provided, list properties, constants and methods of that Chris@0: target. If a class, interface or trait name is passed instead, list constants Chris@0: and methods on that class. Chris@0: Chris@0: e.g. Chris@0: >>> ls Chris@0: >>> ls $foo Chris@0: >>> ls -k --grep mongo -i Chris@0: >>> ls -al ReflectionClass Chris@0: >>> ls --constants --category date Chris@0: >>> ls -l --functions --grep /^array_.*/ Chris@0: >>> ls -l --properties new DateTime() Chris@0: HELP Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function execute(InputInterface $input, OutputInterface $output) Chris@0: { Chris@0: $this->validateInput($input); Chris@0: $this->initEnumerators(); Chris@0: Chris@0: $method = $input->getOption('long') ? 'writeLong' : 'write'; Chris@0: Chris@0: if ($target = $input->getArgument('target')) { Chris@0: list($target, $reflector) = $this->getTargetAndReflector($target); Chris@0: } else { Chris@0: $reflector = null; Chris@0: } Chris@0: Chris@0: // @todo something cleaner than this :-/ Chris@0: if ($input->getOption('long')) { Chris@0: $output->startPaging(); Chris@0: } Chris@0: Chris@0: foreach ($this->enumerators as $enumerator) { Chris@0: $this->$method($output, $enumerator->enumerate($input, $reflector, $target)); Chris@0: } Chris@0: Chris@0: if ($input->getOption('long')) { Chris@0: $output->stopPaging(); Chris@0: } Chris@0: Chris@0: // Set some magic local variables Chris@0: if ($reflector !== null) { Chris@0: $this->setCommandScopeVariables($reflector); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Initialize Enumerators. Chris@0: */ Chris@0: protected function initEnumerators() Chris@0: { Chris@0: if (!isset($this->enumerators)) { Chris@0: $mgr = $this->presenter; Chris@0: Chris@0: $this->enumerators = [ Chris@0: new ClassConstantEnumerator($mgr), Chris@0: new ClassEnumerator($mgr), Chris@0: new ConstantEnumerator($mgr), Chris@0: new FunctionEnumerator($mgr), Chris@0: new GlobalVariableEnumerator($mgr), Chris@0: new PropertyEnumerator($mgr), Chris@0: new MethodEnumerator($mgr), Chris@0: new VariableEnumerator($mgr, $this->context), Chris@0: ]; Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Write the list items to $output. Chris@0: * Chris@0: * @param OutputInterface $output Chris@0: * @param null|array $result List of enumerated items Chris@0: */ Chris@0: protected function write(OutputInterface $output, array $result = null) Chris@0: { Chris@0: if ($result === null) { Chris@0: return; Chris@0: } Chris@0: Chris@0: foreach ($result as $label => $items) { Chris@4: $names = \array_map([$this, 'formatItemName'], $items); Chris@4: $output->writeln(\sprintf('%s: %s', $label, \implode(', ', $names))); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Write the list items to $output. Chris@0: * Chris@0: * Items are listed one per line, and include the item signature. Chris@0: * Chris@0: * @param OutputInterface $output Chris@0: * @param null|array $result List of enumerated items Chris@0: */ Chris@0: protected function writeLong(OutputInterface $output, array $result = null) Chris@0: { Chris@0: if ($result === null) { Chris@0: return; Chris@0: } Chris@0: Chris@0: $table = $this->getTable($output); Chris@0: Chris@0: foreach ($result as $label => $items) { Chris@0: $output->writeln(''); Chris@4: $output->writeln(\sprintf('%s:', $label)); Chris@0: Chris@0: $table->setRows([]); Chris@0: foreach ($items as $item) { Chris@0: $table->addRow([$this->formatItemName($item), $item['value']]); Chris@0: } Chris@0: Chris@0: if ($table instanceof TableHelper) { Chris@0: $table->render($output); Chris@0: } else { Chris@0: $table->render(); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Format an item name given its visibility. Chris@0: * Chris@0: * @param array $item Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: private function formatItemName($item) Chris@0: { Chris@4: return \sprintf('<%s>%s', $item['style'], OutputFormatter::escape($item['name']), $item['style']); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Validate that input options make sense, provide defaults when called without options. Chris@0: * Chris@0: * @throws RuntimeException if options are inconsistent Chris@0: * Chris@0: * @param InputInterface $input Chris@0: */ Chris@0: private function validateInput(InputInterface $input) Chris@0: { Chris@0: if (!$input->getArgument('target')) { Chris@0: // if no target is passed, there can be no properties or methods Chris@0: foreach (['properties', 'methods', 'no-inherit'] as $option) { Chris@0: if ($input->getOption($option)) { Chris@0: throw new RuntimeException('--' . $option . ' does not make sense without a specified target'); Chris@0: } Chris@0: } Chris@0: Chris@0: foreach (['globals', 'vars', 'constants', 'functions', 'classes', 'interfaces', 'traits'] as $option) { Chris@0: if ($input->getOption($option)) { Chris@0: return; Chris@0: } Chris@0: } Chris@0: Chris@0: // default to --vars if no other options are passed Chris@0: $input->setOption('vars', true); Chris@0: } else { Chris@0: // if a target is passed, classes, functions, etc don't make sense Chris@0: foreach (['vars', 'globals', 'functions', 'classes', 'interfaces', 'traits'] as $option) { Chris@0: if ($input->getOption($option)) { Chris@0: throw new RuntimeException('--' . $option . ' does not make sense with a specified target'); Chris@0: } Chris@0: } Chris@0: Chris@0: foreach (['constants', 'properties', 'methods'] as $option) { Chris@0: if ($input->getOption($option)) { Chris@0: return; Chris@0: } Chris@0: } Chris@0: Chris@0: // default to --constants --properties --methods if no other options are passed Chris@0: $input->setOption('constants', true); Chris@0: $input->setOption('properties', true); Chris@0: $input->setOption('methods', true); Chris@0: } Chris@0: } Chris@0: }