diff --git a/.travis.yml b/.travis.yml index 863e121b..b39d3e9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,8 @@ php: - 5.4 before_script: - - composer install --dev + - composer require "symfony/symfony" "2.6.*" --no-update + - composer install - bash tests/bin/travis_jackrabbit.sh script: diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cd27451..2c43a6d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ dev-master ---------- - [transport] Added transport layer for experimental Jackalope FS implementation +- [misc] Wildcard (single asterisk) support in paths +- [node] Added wilcard support to applicable node commands, including "node:list", "node:remove" and "node:property:show" - [global] Refactored to use DI container and various general improvements - [node:references] Shows the referencing node paths instead of the referrered-to node path(s) diff --git a/composer.json b/composer.json index aa15b14d..ef4e63e2 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,8 @@ "symfony/finder": "~2.3", "symfony/serializer": "~2.3", "symfony/yaml": "~2.3", - "symfony/dependency-injection": "~2.3" + "symfony/dependency-injection": "~2.3", + "dantleech/glob-finder": "~0.1" }, "minimum-stability": "dev", "require-dev": { diff --git a/features/all/phpcr_node_info.feature b/features/all/phpcr_node_info.feature index 3881063e..453ced1f 100644 --- a/features/all/phpcr_node_info.feature +++ b/features/all/phpcr_node_info.feature @@ -14,7 +14,6 @@ Feature: Show information about node And I should see the following: """ +-------------------+--------------------------------------+ - | Path | /tests_general_base/daniel | | UUID | N/A | | Index | 1 | | Primary node type | nt:unstructured | diff --git a/features/all/phpcr_node_list.feature b/features/all/phpcr_node_list.feature index e3f5aa80..5a4ede2a 100644 --- a/features/all/phpcr_node_list.feature +++ b/features/all/phpcr_node_list.feature @@ -76,3 +76,62 @@ Feature: List properites and chidren of current nodeA """ One or more weak reference targets have not been found """ + + Scenario: Wildcard on name + Given I execute the "node:list /tests_general_base/numberPropertyNode/jcr:con*" command + Then the command should not fail + And I should see the following: + """ + +-------------+-----------------+--+ + | jcr:content | nt:unstructured | | + +-------------+-----------------+--+ + """ + + Scenario: Wildcard on directory + Given I execute the "node:list /tests_general_base/*/jcr:content" command + Then the command should not fail + And I should see the following: + """ +/tests_general_base/index.txt ++-------------+-----------------+--+ +| jcr:content | nt:unstructured | | ++-------------+-----------------+--+ +/tests_general_base/idExample ++--------------+-----------------+--+ +| jcr:content/ | nt:unstructured | | ++--------------+-----------------+--+ +/tests_general_base/numberPropertyNode ++-------------+-----------------+--+ +| jcr:content | nt:unstructured | | ++-------------+-----------------+--+ +/tests_general_base/NumberPropertyNodeToCompare1 ++-------------+-----------------+--+ +| jcr:content | nt:unstructured | | ++-------------+-----------------+--+ +/tests_general_base/NumberPropertyNodeToCompare2 ++-------------+-----------------+--+ +| jcr:content | nt:unstructured | | ++-------------+-----------------+--+ +""" + + Scenario: Wildcard from relative path + Given the current node is "/tests_general_base" + And I execute the "node:list numberPropertyNode/jcr:con*" command + Then the command should not fail + And I should see the following: + """ + +-------------+-----------------+--+ + | jcr:content | nt:unstructured | | + +-------------+-----------------+--+ + """ + + Scenario: Wildcard from relative path 2 + Given the current node is "/tests_general_base" + And I execute the "node:list num*" command + Then the command should not fail + And I should see the following: + """ + +---------------------+---------+--------------+ + | numberPropertyNode/ | nt:file | +jcr:content | + +---------------------+---------+--------------+ + """ diff --git a/features/all/phpcr_node_property_show.feature b/features/all/phpcr_node_property_show.feature index ec5da370..15a0afb9 100644 --- a/features/all/phpcr_node_property_show.feature +++ b/features/all/phpcr_node_property_show.feature @@ -41,7 +41,7 @@ hello world Then the command should fail And I should see the following: """ - Item at "/tests_general_base" is not a property + Could not find property(s) at path """ Scenario: Try to show non-existing property @@ -49,5 +49,13 @@ hello world Then the command should fail And I should see the following: """ - There is no property at the path "/this/path/does/not/exist" + Could not find property(s) at path + """ + + Scenario: Show properties using wildcard + Given I execute the "node:property:show /tests_general_base/idExample/jcr:*" command + Then the command should not fail + And I should see the following: + """ + /tests_general_base/idExample/jcr:primaryType: nt:file """ diff --git a/features/all/phpcr_node_remove.feature b/features/all/phpcr_node_remove.feature index acfb05eb..8636bc94 100644 --- a/features/all/phpcr_node_remove.feature +++ b/features/all/phpcr_node_remove.feature @@ -32,3 +32,8 @@ Feature: Remove a node You cannot delete the root node """ + Scenario: Delete root node by wildcard + Given I execute the "node:remove /tests_general_base/*" command + Then the command should not fail + And I save the session + And there should not exist a node at "/tests_general_base/daniel" diff --git a/src/PHPCR/Shell/Console/Application/ShellApplication.php b/src/PHPCR/Shell/Console/Application/ShellApplication.php index b864205d..65cbd2d4 100644 --- a/src/PHPCR/Shell/Console/Application/ShellApplication.php +++ b/src/PHPCR/Shell/Console/Application/ShellApplication.php @@ -9,6 +9,8 @@ use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; use PHPCR\Shell\Console\Command\Phpcr as CommandPhpcr; use PHPCR\Shell\Console\Command\Shell as CommandShell; @@ -18,8 +20,6 @@ use PHPCR\Shell\Event\PhpcrShellEvents; use PHPCR\Shell\Console\Command\Phpcr\PhpcrShellCommand; use PHPCR\Shell\Config\Profile; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; /** * Main application for PHPCRSH @@ -200,6 +200,12 @@ protected function registerShellCommands() */ private function configureFormatter(OutputFormatter $formatter) { + $style = new OutputFormatterStyle('yellow', null, array('bold')); + $formatter->setStyle('path', $style); + + $style = new OutputFormatterStyle('green'); + $formatter->setStyle('localname', $style); + $style = new OutputFormatterStyle(null, null, array('bold')); $formatter->setStyle('node', $style); diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/LockRefreshCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/LockRefreshCommand.php index 99ebedf2..c4c27993 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/LockRefreshCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/LockRefreshCommand.php @@ -33,9 +33,13 @@ public function execute(InputInterface $input, OutputInterface $output) $workspace = $session->getWorkspace(); $lockManager = $workspace->getLockManager(); - $path = $session->getAbsPath($input->getArgument('path')); + $path = $input->getArgument('path'); + $nodes = $session->findNodes($path); - $lock = $lockManager->getLock($path); - $lock->refresh(); + foreach ($nodes as $node) { + + $lock = $lockManager->getLock($node->getPath()); + $lock->refresh(); + } } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeInfoCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeInfoCommand.php index 2400e4e3..1858c2cb 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeInfoCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeInfoCommand.php @@ -14,7 +14,11 @@ protected function configure() $this->setDescription('Show information about the current node'); $this->addArgument('path', InputArgument::REQUIRED, 'Path of node'); $this->setHelp(<< node:info path/to/node + +The path can include wildcards. HERE ); } @@ -24,48 +28,51 @@ public function execute(InputInterface $input, OutputInterface $output) $session = $this->get('phpcr.session'); $path = $input->getArgument('path'); $nodeHelper = $this->get('helper.node'); - $currentNode = $session->getNodeByPathOrIdentifier($path); $formatter = $this->get('helper.result_formatter'); - $mixins = $currentNode->getMixinNodeTypes(); - $mixinNodeTypeNames = array(); + $nodes = $session->findNodes($path); - foreach ($mixins as $name => $mixin) { - $mixinNodeTypeNames[] = $mixin->getName(); - } + foreach ($nodes as $node) { + $mixins = $node->getMixinNodeTypes(); + $mixinNodeTypeNames = array(); + + foreach ($mixins as $mixin) { + $mixinNodeTypeNames[] = $mixin->getName(); + } + + if ($nodeHelper->nodeHasMixinType($node, 'mix:versionable')) { + try { + $isCheckedOut = $node->isCheckedOut() ? 'yes' : 'no'; + } catch (\Exception $e) { + $isCheckedOut = $formatter->formatException($e); + } + } else { + $isCheckedOut = 'N/A'; + } - if ($nodeHelper->nodeHasMixinType($currentNode, 'mix:versionable')) { try { - $isCheckedOut = $currentNode->isCheckedOut() ? 'yes' : 'no'; + $isLocked = $node->isLocked() ? 'yes' : 'no'; } catch (\Exception $e) { - $isCheckedOut = $formatter->formatException($e); + $isLocked = $formatter->formatException($e); } - } else { - $isCheckedOut = 'N/A'; - } - try { - $isLocked = $currentNode->isLocked() ? 'yes' : 'no'; - } catch (\Exception $e) { - $isLocked = $formatter->formatException($e); - } + $info = array( + 'UUID' => $node->hasProperty('jcr:uuid') ? $node->getProperty('jcr:uuid')->getValue() : 'N/A', + 'Index' => $node->getIndex(), + 'Primary node type' => $node->getPrimaryNodeType()->getName(), + 'Mixin node types' => implode(', ', $mixinNodeTypeNames), + 'Checked out?' => $isCheckedOut, + 'Locked?' => $isLocked, + ); - $info = array( - 'Path' => $currentNode->getPath(), - 'UUID' => $currentNode->hasProperty('jcr:uuid') ? $currentNode->getProperty('jcr:uuid')->getValue() : 'N/A', - 'Index' => $currentNode->getIndex(), - 'Primary node type' => $currentNode->getPrimaryNodeType()->getName(), - 'Mixin node types' => implode(', ', $mixinNodeTypeNames), - 'Checked out?' => $isCheckedOut, - 'Locked?' => $isLocked, - ); + $output->writeln('' . $node->getPath() . ''); + $table = $this->get('helper.table')->create(); - $table = $this->get('helper.table')->create(); + foreach ($info as $label => $value) { + $table->addRow(array($label, $value)); + } - foreach ($info as $label => $value) { - $table->addRow(array($label, $value)); + $table->render($output); } - - $table->render($output); } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeListCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeListCommand.php index c8ae510d..f6537a0b 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeListCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeListCommand.php @@ -15,7 +15,6 @@ class NodeListCommand extends BasePhpcrCommand { protected $formatter; - protected $filters; protected $textHelper; protected $maxLevel; @@ -26,7 +25,6 @@ protected function configure() $this->addArgument('path', InputArgument::OPTIONAL, 'Path of node', '.'); $this->addOption('children', null, InputOption::VALUE_NONE, 'List only the children of this node'); $this->addOption('properties', null, InputOption::VALUE_NONE, 'List only the properties of this node'); - $this->addOption('filter', 'f', InputOption::VALUE_REQUIRED|InputOption::VALUE_IS_ARRAY, 'Optional filter to apply'); $this->addOption('level', 'L', InputOption::VALUE_REQUIRED, 'Depth of tree to show'); $this->addOption('template', 't', InputOption::VALUE_NONE, 'Show template nodes and properties'); $this->setHelp(<<node:list command can also shows template nodes and properties as defined a nodes node-type by using the --template option. Template nodes and properties are prefixed with the "@" symbol. -The command accepts wither a path (relative or absolute) to the node or a UUID. +The command accepts either a path (relative or absolute) to the node, a UUID or a pattern: PHPCRSH> node:list 842e61c0-09ab-42a9-87c0-308ccc90e6f4 PHPCRSH> node:list /tests/foobar + PHPCRSH> node:list /tests/*/foobar + PHPCRSH> node:list /tests/*/foo* HERE ); } @@ -49,7 +49,6 @@ public function execute(InputInterface $input, OutputInterface $output) { $this->formatter = $this->get('helper.result_formatter'); $this->textHelper = $this->get('helper.text'); - $this->filters = $input->getOption('filter'); $this->maxLevel = $input->getOption('level'); $this->showChildren = $input->getOption('children'); @@ -59,34 +58,52 @@ public function execute(InputInterface $input, OutputInterface $output) $session = $this->get('phpcr.session'); $path = $input->getArgument('path'); - $currentNode = $session->getNodeByPathOrIdentifier($path); + try { + $nodes = array($session->getNodeByPathOrIdentifier($path)); + $filter = null; + } catch (\Exception $e) { + $parentPath = $this->get('helper.path')->getParentPath($path); + + $filter = substr($path, strlen($parentPath)); + + if ($filter[0] == '/') { + $filter = substr($filter, 1); + } + + $nodes = $session->findNodes($parentPath); + } if (!$this->showChildren && !$this->showProperties) { $this->showChildren = true; $this->showProperties = true; } - $table = $this->get('helper.table')->create(); + foreach ($nodes as $node) { + $table = $this->get('helper.table')->create(); + $this->renderNode($node, $table, array(), $filter); - $this->renderNode($currentNode, $table); + if ($table->getNumberOfRows() > 0) { + $output->writeln('' . $node->getPath() . ''); + $table->render($output); + } + } - $table->render($output); } - private function renderNode($currentNode, $table, $spacers = array()) + private function renderNode($currentNode, $table, $spacers = array(), $filter = null) { if ($this->showChildren) { - $this->renderChildren($currentNode, $table, $spacers); + $this->renderChildren($currentNode, $table, $spacers, $filter); } if ($this->showProperties) { - $this->renderProperties($currentNode, $table, $spacers); + $this->renderProperties($currentNode, $table, $spacers, $filter); } } - private function renderChildren($currentNode, $table, $spacers) + private function renderChildren($currentNode, $table, $spacers, $filter = null) { - $children = $currentNode->getNodes($this->filters ? : null); + $children = $currentNode->getNodes($filter ? : null); $nodeType = $currentNode->getPrimaryNodeType(); $childNodeDefinitions = $nodeType->getDeclaredChildNodeDefinitions(); @@ -147,9 +164,9 @@ private function renderChildren($currentNode, $table, $spacers) } } - private function renderProperties($currentNode, $table, $spacers) + private function renderProperties($currentNode, $table, $spacers, $filter = null) { - $properties = $currentNode->getProperties($this->filters ? : null); + $properties = $currentNode->getProperties($filter ? : null); try { $primaryItem = $currentNode->getPrimaryItem(); diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeMixinAddCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeMixinAddCommand.php index 281d62d0..cea60a18 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeMixinAddCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeMixinAddCommand.php @@ -12,11 +12,11 @@ class NodeMixinAddCommand extends BasePhpcrCommand protected function configure() { $this->setName('node:mixin:add'); - $this->setDescription('Add the named mixin to the node'); + $this->setDescription('Add the named mixin to the node (can include wildcards)'); $this->addArgument('path', InputArgument::REQUIRED, 'Path of node'); $this->addArgument('mixinName', InputArgument::REQUIRED, 'The name of the mixin node type to be added'); $this->setHelp(<<mixinName to this node. +Adds the mixin node type named mixinName to the node(s) inferred by the path. If this node is already of type mixinName (either due to a previously added mixin or due to its primary type, through inheritance) then this @@ -46,7 +46,11 @@ public function execute(InputInterface $input, OutputInterface $output) $session = $this->get('phpcr.session'); $path = $input->getArgument('path'); $mixinName = $input->getArgument('mixinName'); - $currentNode = $session->getNodeByPathOrIdentifier($path); - $currentNode->addMixin($mixinName); + + $nodes = $session->findNodes($path); + + foreach ($nodes as $node) { + $node->addMixin($mixinName); + } } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeMixinRemoveCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeMixinRemoveCommand.php index 9aee5da6..b536e433 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeMixinRemoveCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeMixinRemoveCommand.php @@ -13,7 +13,7 @@ protected function configure() { $this->setName('node:mixin:remove'); $this->setDescription('Remove the named mixin to the current node'); - $this->addArgument('path', InputArgument::REQUIRED, 'Path of node'); + $this->addArgument('path', InputArgument::REQUIRED, 'Path of node (can include wildcards)'); $this->addArgument('mixinName', InputArgument::REQUIRED, 'The name of the mixin node type to be removeed'); $this->setHelp(<<get('phpcr.session'); $mixinName = $input->getArgument('mixinName'); $path = $input->getArgument('path'); - $currentNode = $session->getNodeByPathOrIdentifier($path); - $currentNode->removeMixin($mixinName); + + $nodes = $session->findNodes($path); + + foreach ($nodes as $node) { + $node->removeMixin($mixinName); + } } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodePropertySetCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodePropertySetCommand.php index 7c690f9e..e79e15d8 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodePropertySetCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodePropertySetCommand.php @@ -16,7 +16,7 @@ protected function configure() { $this->setName('node:property:set'); $this->setDescription('Rename the node at the current path'); - $this->addArgument('path', InputArgument::REQUIRED, 'Path of property - can include the node name'); + $this->addArgument('path', InputArgument::REQUIRED, 'Path of property - parent path can include wildcards'); $this->addArgument('value', InputArgument::OPTIONAL, 'Value for named property'); $this->addOption('type', null, InputOption::VALUE_REQUIRED, 'Type of named property'); $this->setHelp(<<getParentPath($path); $propName = $pathHelper->getNodeName($path); - $node = $session->getNode($nodePath); - - $intType = null; - - if ($type) { - $intType = PropertyType::valueFromName($type); - } else { - try { - $property = $node->getProperty($propName); - $intType = $property->getType(); - } catch (PathNotFoundException $e) { - // property doesn't exist and no type specified, default to string - $intType = PropertyType::STRING; + + $nodes = $session->findNodes($nodePath); + + foreach ($nodes as $node) { + $intType = null; + + if ($type) { + $intType = PropertyType::valueFromName($type); + } else { + try { + $property = $node->getProperty($propName); + $intType = $property->getType(); + } catch (PathNotFoundException $e) { + // property doesn't exist and no type specified, default to string + $intType = PropertyType::STRING; + } } - } - $node->setProperty($propName, $value, $intType); + $node->setProperty($propName, $value, $intType); + } } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodePropertyShowCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodePropertyShowCommand.php index c0c174bd..6a203381 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodePropertyShowCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodePropertyShowCommand.php @@ -14,8 +14,8 @@ class NodePropertyShowCommand extends BasePhpcrCommand protected function configure() { $this->setName('node:property:show'); - $this->setDescription('Show the property at the given absolute path'); - $this->addArgument('absPath', InputArgument::REQUIRED, 'Absolute path to property'); + $this->setDescription('Show the property at the given path'); + $this->addArgument('path', InputArgument::REQUIRED, 'Path to property (can include wildcards)'); $this->setHelp(<<get('phpcr.session'); - $absPath = $session->getAbsPath($input->getArgument('absPath')); + $path = $session->getAbsPath($input->getArgument('path')); + $resultFormatHelper = $this->get('helper.result_formatter'); + $pathHelper = $this->get('helper.path'); $resultFormatHelper = $this->get('helper.result_formatter'); - try { - $property = $session->getItem($absPath); - } catch (PathNotFoundException $e) { - throw new \Exception(sprintf( - 'There is no property at the path "%s"', $absPath - )); - } - - if (!$property instanceof PropertyInterface) { - throw new \Exception(sprintf( - 'Item at "%s" is not a property.', - $absPath - )); + $parentPath = $pathHelper->getParentPath($path); + $filter = $pathHelper->getNodeName($path); + $nodes = $session->findNodes($parentPath); + if (0 === count($nodes)) { + throw new \Exception('Could not find property(s) at path ' . $path); } - $output->writeln($resultFormatHelper->formatValue($property, true)); + foreach ($nodes as $node) { + try { + $properties = array($node->getProperty($filter)); + } catch (PathNotFoundException $e) { + $properties = $node->getProperties($filter); + } + + if (0 === count($properties)) { + throw new \Exception('Could not find property(s) at path ' . $path); + } + + foreach ($properties as $property) { + $output->writeln(sprintf( + '%s/%s: %s', + $pathHelper->getParentPath($property->getPath()), + $pathHelper->getNodeName($property->getPath()), + $resultFormatHelper->formatValue($property, true) + )); + } + } } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeReferencesCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeReferencesCommand.php index 006a48fb..636585ab 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeReferencesCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeReferencesCommand.php @@ -13,7 +13,7 @@ protected function configure() { $this->setName('node:references'); $this->setDescription('Returns all REFERENCE properties that refer to this node'); - $this->addArgument('path', InputArgument::REQUIRED, 'Path of node'); + $this->addArgument('path', InputArgument::REQUIRED, 'Path of node (can include wildcard)'); $this->addArgument('name', InputArgument::OPTIONAL, 'Limit references to given name'); $this->setHelp(<<get('phpcr.session'); $path = $input->getArgument('path'); - $currentNode = $session->getNodeByPathOrIdentifier($path); $name = $input->getArgument('name'); - $references = array( - 'weak' => array(), - 'strong' => array(), - ); + $nodes = $session->findNodes($path); + + foreach ($nodes as $node) { + $references = array( + 'weak' => array(), + 'strong' => array(), + ); - $references['weak'] = $currentNode->getWeakReferences($name ? : null); - $references['strong'] = $currentNode->getReferences($name ? : null); + $references['weak'] = $node->getWeakReferences($name ? : null); + $references['strong'] = $node->getReferences($name ? : null); - $table = $this->get('helper.table')->create(); - $table->setHeaders(array( - 'Type', 'Property', 'Node Path' - )); + $table = $this->get('helper.table')->create(); + $table->setHeaders(array( + 'Type', 'Property', 'Node Path' + )); - foreach ($references as $type => $typeReferences) { - foreach ($typeReferences as $property) { - $nodePath = $property->getParent()->getPath(); + foreach ($references as $type => $typeReferences) { + foreach ($typeReferences as $property) { + $nodePath = $property->getParent()->getPath(); - $table->addRow(array( - $type, - $property->getName(), - $nodePath - )); + $table->addRow(array( + $type, + $property->getName(), + $nodePath + )); + } } - } - $table->render($output); + if (0 !== count($references['weak']) || 0 !== count($references['strong'])) { + $output->writeln('' . $node->getPath() . ''); + $table->render($output); + } + } } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeRemoveCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeRemoveCommand.php index 745ec638..1eb34005 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeRemoveCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeRemoveCommand.php @@ -12,7 +12,7 @@ class NodeRemoveCommand extends BasePhpcrCommand protected function configure() { $this->setName('node:remove'); - $this->setDescription('Remove the node at path'); + $this->setDescription('Remove the node at path (can include wildcards)'); $this->addArgument('path', InputArgument::REQUIRED, 'Path of node'); $this->setHelp(<<get('phpcr.session'); - $targetPath = $input->getArgument('path'); + $path = $input->getArgument('path'); $currentPath = $session->getCwd(); // verify that node exists by trying to get it.. - $targetNode = $session->getNodeByPathOrIdentifier($targetPath); + $nodes = $session->findNodes($path); - if ($targetNode->getPath() == '/') { - throw new \InvalidArgumentException( - 'You cannot delete the root node!' - ); - } + foreach ($nodes as $node) { + if ($node->getPath() == '/') { + throw new \InvalidArgumentException( + 'You cannot delete the root node!' + ); + } - $session->removeItem($targetPath); + $node->remove(); + } // if we deleted the current path, switch back to the parent node - if ($currentPath == $session->getAbsPath($targetPath)) { + if ($currentPath == $session->getAbsPath($path)) { $session->chdir('..'); } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeSetPrimaryTypeCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeSetPrimaryTypeCommand.php index 27bff944..b85f9b88 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeSetPrimaryTypeCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeSetPrimaryTypeCommand.php @@ -13,7 +13,7 @@ protected function configure() { $this->setName('node:set-primary-type'); $this->setDescription('Set the primary type of the current node'); - $this->addArgument('path', InputArgument::REQUIRED, 'Path of node'); + $this->addArgument('path', InputArgument::REQUIRED, 'Path of node (can include wildcard)'); $this->addArgument('nodeTypeName', InputArgument::REQUIRED, 'New primary node type name'); $this->setHelp(<<getArgument('path'); $nodeTypeName = $input->getArgument('nodeTypeName'); - $currentNode = $session->getNodeByPathOrIdentifier($path); - $currentNode->setPrimaryType($nodeTypeName); + $nodes = $session->findNodes($path); + + foreach ($nodes as $node) { + $node->setPrimaryType($nodeTypeName); + } } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeSharedRemoveCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeSharedRemoveCommand.php index a861969f..65d5ac37 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeSharedRemoveCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeSharedRemoveCommand.php @@ -14,7 +14,7 @@ protected function configure() { $this->setName('node:shared:remove'); $this->setDescription('Removes this node and every other node in the shared set of this node'); - $this->addArgument('path', InputArgument::REQUIRED, 'Path of node'); + $this->addArgument('path', InputArgument::REQUIRED, 'Path of node (can include wildcard)'); $this->setHelp(<<get('phpcr.session'); $path = $input->getArgument('path'); - $currentNode = $session->getNodeByPathOrIdentifier($path); - $sharedSet = $currentNode->removeSharedSet(); + + $nodes = $session->findNodes($path); + + foreach ($nodes as $node) { + $node->removeSharedSet(); + } } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeSharedShowCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeSharedShowCommand.php index 018917a4..77a8d10f 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeSharedShowCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeSharedShowCommand.php @@ -14,7 +14,7 @@ protected function configure() { $this->setName('node:shared:show'); $this->setDescription('Show all the nodes are in the shared set of this node'); - $this->addArgument('path', InputArgument::REQUIRED, 'Path of node'); + $this->addArgument('path', InputArgument::REQUIRED, 'Path of node (can include wildcard)'); $this->setHelp(<<get('phpcr.session'); $path = $input->getArgument('path'); - $currentNode = $session->getNodeByPathOrIdentifier($path); - $sharedSet = $currentNode->getSharedSet(); + $nodes = $session->findNodes($path); - foreach ($sharedSet as $sharedNode) { - $output->writeln($sharedNode->getPath()); + foreach ($nodes as $node) { + $output->writeln('' . $node->getPath() . ''); + $sharedSet = $node->getSharedSet(); + + foreach ($sharedSet as $sharedNode) { + $output->writeln($sharedNode->getPath()); + } } } } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeUpdateCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeUpdateCommand.php index 49927063..8a2ac272 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeUpdateCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeUpdateCommand.php @@ -12,8 +12,8 @@ class NodeUpdateCommand extends BasePhpcrCommand protected function configure() { $this->setName('node:update'); - $this->setDescription('Updates a node corresponding to the current one in the given workspace'); - $this->addArgument('path', InputArgument::REQUIRED, 'Path of node'); + $this->setDescription('Updates a node corresponding to the given path in the given workspace'); + $this->addArgument('path', InputArgument::REQUIRED, 'Path of node (can include wildcards)'); $this->addArgument('srcWorkspace', InputArgument::REQUIRED, 'The name of the source workspace'); $this->setHelp(<<get('phpcr.session'); $path = $input->getArgument('path'); + $srcWorkspace = $input->getArgument('srcWorkspace'); - $currentNode = $session->getNodeByPathOrIdentifier($path); - $currentNode->update($srcWorkspace); + + $nodes = $session->findNodes($path); + + foreach ($nodes as $node) { + $output->writeln('' . $node->getPath() . ''); + $node->update($srcWorkspace); + } } } diff --git a/src/PHPCR/Shell/Console/Helper/PhpcrHelper.php b/src/PHPCR/Shell/Console/Helper/PhpcrHelper.php index 5375ab54..d867198c 100644 --- a/src/PHPCR/Shell/Console/Helper/PhpcrHelper.php +++ b/src/PHPCR/Shell/Console/Helper/PhpcrHelper.php @@ -5,6 +5,7 @@ use Symfony\Component\Console\Helper\Helper; use PHPCR\Shell\Phpcr\SessionManager; use PHPCR\SessionInterface; +use PHPCR\Shell\Query\PhpcrRepository; /** * @deprecated diff --git a/src/PHPCR/Shell/Console/Helper/TableHelper.php b/src/PHPCR/Shell/Console/Helper/TableHelper.php index 11daad71..2ff09039 100644 --- a/src/PHPCR/Shell/Console/Helper/TableHelper.php +++ b/src/PHPCR/Shell/Console/Helper/TableHelper.php @@ -13,15 +13,28 @@ * * @author Daniel Leech */ -class TableHelper extends Helper +class TableHelper extends OriginalTableHelper { + private $numberOfRows = 0; + + public function __construct() + { + parent::__construct(false); + } + public function create() { - return new OriginalTableHelper(false); + return new self(false); + } + + public function addRow(array $row) + { + parent::addRow($row); + $this->numberOfRows++; } - public function getName() + public function getNumberOfRows() { - return 'table'; + return $this->numberOfRows; } } diff --git a/src/PHPCR/Shell/Phpcr/PhpcrSession.php b/src/PHPCR/Shell/Phpcr/PhpcrSession.php index 62094f01..9175b897 100644 --- a/src/PHPCR/Shell/Phpcr/PhpcrSession.php +++ b/src/PHPCR/Shell/Phpcr/PhpcrSession.php @@ -6,6 +6,7 @@ use PHPCR\CredentialsInterface; use PHPCR\Util\UUIDHelper; use PHPCR\PathNotFoundException; +use DTL\Glob\Finder\PhpcrTraversalFinder; /** * Custom session wrapper for PHPCR Shell @@ -18,10 +19,12 @@ class PhpcrSession implements SessionInterface { protected $session; protected $cwd = '/'; + protected $finder; - public function __construct(SessionInterface $session) + public function __construct(SessionInterface $session, $finder = null) { $this->session = $session; + $this->finder = $finder ? : new PhpcrTraversalFinder($session); } /** @@ -172,7 +175,7 @@ public function getNodeByPathOrIdentifier($pathOrId) return $this->getNodeByIdentifier($pathOrId); } - $path = $this->getAbsPath($pathOrId); + $pathOrId = $this->getAbsPath($pathOrId); return $this->getNode($pathOrId); } @@ -219,7 +222,7 @@ public function getNodeByIdentifier($id) public function getNodesByIdentifier($ids) { - return $this->session->getNodesByIdentifier($id); + return $this->session->getNodesByIdentifier($ids); } public function getItem($path) @@ -229,7 +232,7 @@ public function getItem($path) public function getNode($path, $depthHint = -1) { - return $this->session->getNode($this->getAbsPath($path)); + return $this->session->getNode($this->getAbsPath($path), $depthHint); } public function getNodes($paths) @@ -297,7 +300,7 @@ public function checkPermission($path, $actions) return $this->session->checkPermission($this->getAbsPath($path), $actions); } - public function hasCapability($methodName, $target, array $arguments) + public function hasCapability($methodNames, $target, array $arguments) { return $this->session->hasCapability($methodNames, $target, $arguments); } @@ -356,4 +359,15 @@ public function getRetentionManager() { return $this->session->getRetentionManager(); } + + public function findNodes($patternOrId) + { + if (true === UUIDHelper::isUUID($patternOrId)) { + return $this->getNodeByIdentifier($patternOrId); + } + + $res = $this->finder->find($this->getAbsPath($patternOrId)); + + return $res; + } }