diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 7e58b21b..7b9973e3 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -61,7 +61,6 @@ public function beforeScenario() /** * Cleans test folders in the temporary directory. * - * @BeforeSuite * @AfterSuite */ public static function cleanTestFolders() @@ -150,6 +149,17 @@ public function iExecuteTheCommand($args) $this->executeCommand($args); } + /** + * @Given /^I execute the following commands:$/ + */ + public function iExecuteTheFollowingCommands(TableNode $table) + { + foreach ($table->getRows() as $row) { + $this->executeCommand($row[0]); + $this->theCommandShouldNotFail(); + } + } + /** * @Then /^I should see a table containing the following rows:$/ */ @@ -190,6 +200,15 @@ public function iShouldSeeTheFollowing(PyStringNode $string) PHPUnit_Framework_Assert::assertContains($string->getRaw(), $output); } + /** + * @Then /^I should not see the following:$/ + */ + public function iShouldNotSeeTheFollowing(PyStringNode $string) + { + $output = $this->getOutput(); + PHPUnit_Framework_Assert::assertNotContains($string->getRaw(), $output); + } + /** * @Given /^the "([^"]*)" fixtures are loaded$/ */ @@ -765,4 +784,13 @@ public function theNodeShouldNotBeLocked($arg1) PHPUnit_Framework_Assert::assertFalse($isLocked); } + + /** + * @Given /^I purge the current workspace$/ + */ + public function iPurgeTheCurrentWorkspace() + { + $session = $this->getSession(); + NodeHelper::purgeWorkspace($session); + } } diff --git a/features/lock_token_remove.feature b/features/lock_token_remove.feature index 5bc9770c..5f603bed 100644 --- a/features/lock_token_remove.feature +++ b/features/lock_token_remove.feature @@ -9,7 +9,7 @@ Feature: Remove a lock token in the current session Scenario: Create a new node Given I execute the "lock:token:remove foobar" command Then the command should fail - Then I should not see the following: + Then I should see the following: """ Not implemented """ diff --git a/features/node_info.feature b/features/node_info.feature index 8faa0c48..db0790a0 100644 --- a/features/node_info.feature +++ b/features/node_info.feature @@ -19,7 +19,7 @@ Feature: Show information about node | Index | 1 | | Primary node type | nt:unstructured | | Mixin node types | | - | Checked out? | [ERROR] Not implemented by jackalope | + | Checked out? | N/A | | Locked? | [ERROR] Not implemented by jackalope | +-------------------+--------------------------------------+ """ diff --git a/features/version_checkout.feature b/features/version_checkout.feature index 110c8153..65c0dad0 100644 --- a/features/version_checkout.feature +++ b/features/version_checkout.feature @@ -10,7 +10,13 @@ Feature: Checkout a version Scenario: Checkout a a given node Given I execute the "version:checkout /tests_version_base/versioned" command Then the command should not fail - And the node "/tests_version_base/verionable" should be checked out + And the current node is "/tests_version_base/versioned" + And I execute the "node:info" command + Then I should see the following: + """ + | Checked out? | yes + """ + Scenario: Checkout a non-versionable node Given I execute the "version:checkout /tests_version_base" command diff --git a/features/version_checkpoint.feature b/features/version_checkpoint.feature index 3131a817..663790de 100644 --- a/features/version_checkpoint.feature +++ b/features/version_checkpoint.feature @@ -8,12 +8,23 @@ Feature: Checkpoint And the "versionable.xml" fixtures are loaded Scenario: Checkpoint a a given node - Given I execute the "version:checkpoint /tests_version_base/versioned" command + Given I execute the following commands: + | cd /tests_version_base/versioned | + | node:set foo bar | + | session:save | + | version:checkpoint /tests_version_base/versioned | + | node:set foo baz | + | session:save | + | version:checkpoint /tests_version_base/versioned | Then the command should not fail - And the node "/tests_version_base/verionable" should be checked out And I should see the following: """ - Version: + Version: 1.1 + """ + And I execute the "node:info" command + Then I should see the following: + """ + | Checked out? | yes """ Scenario: Checkpoint a non versionable node diff --git a/features/version_remove.feature b/features/version_remove.feature index b020b6eb..a7772f8b 100644 --- a/features/version_remove.feature +++ b/features/version_remove.feature @@ -5,10 +5,23 @@ Feature: Remove node version Background: Given that I am logged in as "testuser" - And the "session_data.xml" fixtures are loaded + And the "versionable.xml" fixtures are loaded Scenario: Checkout a a given node - Given the node "/tests_general_base" has a version with label "mylabel" - And I execute the "version:remove /tests_general_base mylabel" command + Given I execute the following commands: + | cd /tests_version_base/versioned | + | version:checkout /tests_version_base/versioned | + | node:set foo baz | + | session:save | + | version:checkin /tests_version_base/versioned | + | version:checkout /tests_version_base/versioned | + | node:set foo bar | + | session:save | + | version:checkin /tests_version_base/versioned | + And I execute the "version:remove /tests_version_base/versioned 1.0" command Then the command should not fail - And the node "/tests_general_base" should have a node version labeled "mylabel" + And I execute the "version:history /tests_version_base/versioned" command + Then I should not see the following: + """ + | 1.0 | + """ diff --git a/features/version_restore.feature b/features/version_restore.feature index 8da6e209..ace7bb74 100644 --- a/features/version_restore.feature +++ b/features/version_restore.feature @@ -5,22 +5,21 @@ Feature: Restore a version Background: Given that I am logged in as "testuser" - And the "session_data.xml" fixtures are loaded + And the "versionable.xml" fixtures are loaded Scenario: Restore node version - Given there exists a node version "asd" for node "/tests_general_base" - And I execute the "version:restore --version=asd" command + Given I execute the following commands: + | cd /tests_version_base/versioned | + | node:set foo initalbar | + | session:save | + | version:checkpoint /tests_version_base/versioned | + | node:set foo baz | + | session:save | + | version:checkpoint /tests_version_base/versioned | + And I execute the "version:restore /tests_version_base/versioned 1.0" command Then the command should not fail - And the version of "/tests_general_base" should be "asd" - - Scenario: Restore node version by label - Given there exists a node version "asd" for node "/tests_general_base" - And I execute the "version:restore --label=asd" command - Then the command should not fail - And the version of "/tests_general_base" should be "asd" - - Scenario: Restore multiple node versions - Given there exists a node version "asd" for node "/tests_general_base" - And I execute the "version:restore --version=asd --version=dsa" command - Then the command should not fail - And the version of "/tests_general_base" should be "asd" + And I execute the "ls" command + Then I should see the following: + """ + | foo | STRING | inital + """ diff --git a/features/workspace_namespace_register.feature b/features/workspace_namespace_register.feature index 2dda5aa6..995ffac6 100644 --- a/features/workspace_namespace_register.feature +++ b/features/workspace_namespace_register.feature @@ -5,8 +5,14 @@ Feature: Register a namespace on the workspace Background: Given that I am logged in as "testuser" - And the "clean.xml" system view fixtures are loaded - Scenario: List namespaces - Given I execute the "workspace:namespace:register dcms http://foobar.com/ns" command - Then the command should not fail + # We cannot test namespace registration because jackrabbit does not support + # namespace unregistration, so we simply try doing something which provokes + # to throw an exception. + Scenario: Attemp to register a default namespace + Given I execute the "workspace:namespace:register foo http\://www.jcp.org/jcr/nt/1.0" command + Then the command should fail + And I should see the following: + """ + Can not change default namespace + """ diff --git a/features/workspace_namespace_unregister.feature b/features/workspace_namespace_unregister.feature index cec68b2d..f2b80aaf 100644 --- a/features/workspace_namespace_unregister.feature +++ b/features/workspace_namespace_unregister.feature @@ -5,13 +5,14 @@ Feature: Unregister a namespace on the workspace Background: Given that I am logged in as "testuser" - And the "session_data.xml" fixtures are loaded - Scenario: List namespaces - Given the namespace "http://foobar.com/ns" with prefix "foo" exists - And I execute the "workspace:namespace:unregister http://foobar.com/ns" command + # We cannot test namespace registration because jackrabbit does not support + # namespace unregistration, so we simply try doing something which provokes + # to throw an exception. + Scenario: Attemp to unregister a default namespace + Given I execute the "workspace:namespace:unregister internal" command Then the command should fail And I should see the following: """ - not supported by jackrabbit backend + Unregistering namespace not supported by jackrabbit backend """ diff --git a/features/workspace_node_clone.feature b/features/workspace_node_clone.feature index 64551500..ad1d30fe 100644 --- a/features/workspace_node_clone.feature +++ b/features/workspace_node_clone.feature @@ -10,16 +10,20 @@ Feature: Clone a node from a given workspace to the current workspace And the current workspace is "default" And the "cms.xml" fixtures are loaded - # Scenario: Clone node - # Given the current workspace is "default" - # And I execute the "workspace:node:clone default_1 /cms/articles/article1 /cms/clone" command - # Then the command should not fail - # And I save the session - # And there should exist a node at "/cms/clone" + Scenario: Clone node + Given the current workspace is "default" + And I execute the "workspace:node:clone default_1 /cms/articles/article1 /cms/clone" command + Then the command should not fail + And I save the session + And there should exist a node at "/cms/clone" Scenario: Clone onto existing Given I execute the "workspace:node:clone default_1 /cms/articles/article1 /cms/articles" command Then the command should fail + And I should see the following: + """ + Node already exists at destination + """ Scenario: Clone onto existing but remove Given I execute the "workspace:node:clone --remove-existing default_1 /cms/articles/article1 /cms/articles/article1" command diff --git a/features/workspace_node_copy.feature b/features/workspace_node_copy.feature index dea07b62..e216434b 100644 --- a/features/workspace_node_copy.feature +++ b/features/workspace_node_copy.feature @@ -7,17 +7,16 @@ Feature: Copy a node from a given workspace to the current workspace Given that I am logged in as "testuser" And the current workspace is "default_1" And the "session_data.xml" fixtures are loaded - And the "all_property_types.xml" fixtures are loaded And the current workspace is "default" And I purge the current workspace Scenario: Copy node from a different workspace - Given I execute the "workspace:node:copy /tests_general_base/index.txt /index.txt test" command + Given I execute the "workspace:node:copy /tests_general_base/index.txt /index.txt default_1" command Then the command should not fail And there should exist a node at "/index.txt" Scenario: Copy node in the same workspace - And I execute the "workspace:node:copy /tests_general_base/index.txt /index.txt" command + And I execute the "workspace:node:copy /tests_general_base/index.txt /tests_general_base/index.txt.2" command Then the command should not fail And I save the session - And there should exist a node at "/index.txt" + And there should exist a node at "/tests_general_base/index.txt.2" diff --git a/src/PHPCR/Shell/Console/Command/NodeInfoCommand.php b/src/PHPCR/Shell/Console/Command/NodeInfoCommand.php index 2b6d773a..f2cfa079 100644 --- a/src/PHPCR/Shell/Console/Command/NodeInfoCommand.php +++ b/src/PHPCR/Shell/Console/Command/NodeInfoCommand.php @@ -26,6 +26,7 @@ protected function configure() public function execute(InputInterface $input, OutputInterface $output) { $session = $this->getHelper('phpcr')->getSession(); + $nodeHelper = $this->getHelper('node'); $currentNode = $session->getCurrentNode(); $formatter = $this->getHelper('result_formatter'); @@ -36,10 +37,14 @@ public function execute(InputInterface $input, OutputInterface $output) $mixinNodeTypeNames[] = $mixin->getName(); } - try { - $isCheckedOut = $currentNode->isCheckedOut() ? 'yes' : 'no'; - } catch (\Exception $e) { - $isCheckedOut = $formatter->formatException($e); + if ($nodeHelper->nodeHasMixinType($currentNode, 'mix:versionable')) { + try { + $isCheckedOut = $currentNode->isCheckedOut() ? 'yes' : 'no'; + } catch (\Exception $e) { + $isCheckedOut = $formatter->formatException($e); + } + } else { + $isCheckedOut = 'N/A'; } try { diff --git a/src/PHPCR/Shell/Console/Command/VersionRemoveCommand.php b/src/PHPCR/Shell/Console/Command/VersionRemoveCommand.php index 2c7a0f7a..833ae440 100644 --- a/src/PHPCR/Shell/Console/Command/VersionRemoveCommand.php +++ b/src/PHPCR/Shell/Console/Command/VersionRemoveCommand.php @@ -14,20 +14,36 @@ protected function configure() $this->setName('version:remove'); $this->setDescription('Remove a node version'); $this->addArgument('absPath', null, InputArgument::REQUIRED, 'Absolute path to node'); + $this->addArgument('versionName', null, InputArgument::REQUIRED, 'Name of version to remove'); $this->setHelp(<<Note that this change is made immediately; there is no need to +call save. In fact, since the the version storage is read-only with +respect to normal repository methods, save does not even function in +this context. HERE ); } public function execute(InputInterface $input, OutputInterface $output) { - $session = $this->getHelper('phpcr')->getSession(); $absPath = $input->getArgument('absPath'); + $versionName = $input->getArgument('versionName'); + $session = $this->getHelper('phpcr')->getSession(); $workspace = $session->getWorkspace(); - $versionManager = $workspace->getVersionManager(); - $version = $versionManager->checkin($absPath); - $output->writeln('Version: ' . $version); + $history = $versionManager->getVersionHistory($absPath); + $history->removeVersion($versionName); } } diff --git a/src/PHPCR/Shell/Console/Command/VersionRestoreCommand.php b/src/PHPCR/Shell/Console/Command/VersionRestoreCommand.php index c385ae73..6b3a88d0 100644 --- a/src/PHPCR/Shell/Console/Command/VersionRestoreCommand.php +++ b/src/PHPCR/Shell/Console/Command/VersionRestoreCommand.php @@ -6,6 +6,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; class VersionRestoreCommand extends Command { @@ -13,13 +14,91 @@ protected function configure() { $this->setName('version:restore'); $this->setDescription('Restore a node version'); + $this->addArgument('absPath', null, InputArgument::REQUIRED, 'Absolute path to node'); + $this->addArgument('versionName', null, InputArgument::REQUIRED, 'Name of version to retore'); + $this->addOption('remove-existing', null, InputOption::VALUE_NONE, 'Flag that governs what happens in case of identifier collision'); $this->setHelp(<<If absPath is given and versionName is a version name: + Restores the node at absPath to the state defined by the version with + the specified version name (versionName). + This method will work regardless of whether the node at absPath is + checked-in or not. + + +If absPath is given and versionName is a VersionInterface instance: + + Restores the specified version to absPath. There must be no existing + node at absPath. If one exists, a VersionException is thrown. + There must be a parent node to the location at absPath, otherwise a + PathNotFoundException is thrown. + If the would-be parent of the location absPath is actually a property, + or if a node type restriction would be violated, then a + ConstraintViolationException is thrown. + + +If versionName is VersionInterface instance: + Restores the node in the current workspace that is the versionable node + of the specified version to the state reflected in that version. + This method ignores checked-in status. + + +If versionName is an array of VersionInterface instances: + Restores a set of versions at once. Used in cases where a "chicken and + egg" problem of mutually referring REFERENCE properties would prevent + the restore in any serial order. + The following restrictions apply to the set of versions specified: If S + is the set of versions being restored simultaneously, + - For every version V in S that corresponds to a missing node, there + must also be a parent of V in S. + - S must contain at least one version that corresponds to an existing + node in the workspace. + - No V in S can be a root version (jcr:rootVersion). + If any of these restrictions does not hold, the restore will fail + because the system will be unable to determine the path locations to + which one or more versions are to be restored. In this case a + VersionException is thrown. + The versionable nodes in the current workspace that correspond to the + versions being restored define a set of (one or more) subgraphs. + +If the restore succeeds the changes made are dispatched immediately; + +there is no need to call save. + +If an array of VersionInterface instances is restored, an identifier +collision occurs when the current workspace contains a node outside these +subgraphs that has the same identifier as one of the nodes that would be +introduced by the restore operation into one of these subgraphs. +Else, an identifier collision occurs when a node exists outside the +subgraph rooted at absPath with the same identifier as a node that would +be introduced by the restore operation into the affected subgraph. +The result in such a case is governed by the removeExisting flag. If +removeExisting is true, then the incoming node takes precedence, and the +existing node (and its subgraph) is removed (if possible; otherwise a +RepositoryException is thrown). If removeExisting is false, then an +ItemExistsException is thrown and no changes are made. Note that this +applies not only to cases where the restored node itself conflicts with +an existing node but also to cases where a conflict occurs with any node +that would be introduced into the workspace by the restore operation. In +particular, conflicts involving subnodes of the restored node that have +OnParentVersion settings of COPY or VERSION are also governed by the +removeExisting flag. + +Note: The Java API defines this with multiple differing +signatures, you need to act accordingly in your implementation. HERE ); } public function execute(InputInterface $input, OutputInterface $output) { - throw new \Exception('TODO'); + $absPath = $input->getArgument('absPath'); + $versionName = $input->getArgument('versionName'); + $removeExisting = $input->getOption('remove-existing'); + $session = $this->getHelper('phpcr')->getSession(); + $workspace = $session->getWorkspace(); + $versionManager = $workspace->getVersionManager(); + $versionManager->restore($removeExisting, $versionName, $absPath); } }