Skip to content

Commit

Permalink
Merge pull request #72 from phpcr/clean-dump-command
Browse files Browse the repository at this point in the history
cleaning up the dump command parameters
  • Loading branch information
dbu committed Jun 28, 2013
2 parents 0a54685 + 84da397 commit 04f0b23
Show file tree
Hide file tree
Showing 8 changed files with 244 additions and 132 deletions.
61 changes: 25 additions & 36 deletions README.md
Expand Up @@ -28,36 +28,35 @@ NOTE: If you are using PHPCR inside of Symfony, the DoctrinePHPCRBundle
provides the commands inside the normal Symfony console and you don't need to
prepare anything special.

* ``phpcr:workspace:create <name>``: Create the workspace name in the configured repository
* ``phpcr:register-node-types --allow-update [cnd-file]``: Register namespaces and node types from a "Compact Node Type Definition" .cnd file
* ``phpcr:dump [--sys_nodes[="..."]] [--props[="..."]] [path]``: Show the node names
under the specified path. If you set sys_nodes=yes you will also see system nodes.
If you set props=yes you will additionally see all properties of the dumped nodes.
* ``phpcr:purge``: Remove all content from the configured repository in the
configured workspace
* ``phpcr:sql2``: Run a query in the JCR SQL2 language against the repository and dump
the resulting rows to the console.

**TODO:**

* Implement commands for phpcr:import and phpcr:export to import and export the
PHPCR document view and system view XML dumps.
* Implement a simple .cnd parser in PHP and use it to make register-node-types
work with all repositories

To get a list of the available commands, run `bin/phpcr` or set the commands up
in your application. Running `bin/phpcr help <command-name>` outputs the
documentation of that command.

## Helper Classes

The helper classes provide implementations for basic common tasks to help users
and implementors of PHPCR. They are all in the namespace PHPCR\Util
and implementers of PHPCR. They are all in the namespace PHPCR\Util

### PathHelper

### TraversingItemVisitor
Used to manipulate paths. Implementations are recommended to use this, and
applications also profit from it. Using `dirname` and similar file system
operations on paths is not compatible with Microsoft Windows systems, thus you
should always use the methods in PathHelper.

This ``ItemVisitorInterface`` implementation is a basic implementation of crawling
a PHPCR tree. You can extend it to define what it should do while crawling the
tree.
### NodeHelper

This helper has some generally useful methods like one to generate empty
`nt:unstructured` nodes to make sure a parent path exists. It also provides
some useful helper methods for implementations.

### UUIDHelper

This little helper is mainly of interest for PHPCR implementers. It generates
valid *Universally Unique IDs* and can determine whether a given string is a
valid UUID.
We recommend all implementations to use this implementation to guarantee
consistent behaviour.

### QOM QueryBuilder

Expand All @@ -66,25 +65,15 @@ The ``QueryBuilder`` is a fluent query builder with method names matching the
on top of the QOM factory. It is the easiest way to programmatically build a
PHPCR query.


### Query Object Model Converter

In the PHPCR\Util\QOM namespace we provide, implementation-independant code to
convert between SQL2 and QOM. ``Sql2ToQomQueryConverter`` parses SQL2 queries
into QOM . ``QomToSql2QueryConverter`` generates SQL2 out of a QOM.

### TraversingItemVisitor

### UUIDHelper

This little helper is mainly of interest for PHPCR implementors. It generates
valid *Universally Unique IDs* and can determine wheter a given string is a
valid UUID.
We recommend all implementations to use this implementation to guarantee
constistent behaviour.


# TODO

Move tests about the query converter from phpcr-api-tests tests/06_Query/QOM to
the tests folder. How to do the tests without a QOM factory implementation?
This ``ItemVisitorInterface`` implementation is a basic implementation of crawling
a PHPCR tree. You can extend it to define what it should do while crawling the
tree.

7 changes: 4 additions & 3 deletions src/PHPCR/Util/Console/Command/BaseCommand.php
Expand Up @@ -2,26 +2,27 @@

namespace PHPCR\Util\Console\Command;

use PHPCR\SessionInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use PHPCR\Util\Console\Helper\PhpcrCliHelper;
use Symfony\Component\Console\Input\InputOption;

abstract class BaseCommand extends Command
{
protected $phpcrCliHelper;

/**
* @return PHPCR\SessionInterface
* @return SessionInterface
*/
protected function getPhpcrSession()
{
return $this->getHelper('phpcr')->getSession();
}

/**
* @return PHPCR\Util\Console\Helper\PhpcrCliHelper
* @return PhpcrCliHelper
*/
protected function getPhpcrCliHelper()
{
Expand Down
32 changes: 7 additions & 25 deletions src/PHPCR/Util/Console/Command/NodeDumpCommand.php
Expand Up @@ -21,20 +21,18 @@

namespace PHPCR\Util\Console\Command;

use PHPCR\Util\UUIDHelper;
use PHPCR\ItemNotFoundException;
use PHPCR\RepositoryException;
use PHPCR\PathNotFoundException;

use PHPCR\Util\UUIDHelper;
use PHPCR\Util\Console\Helper\PhpcrConsoleDumperHelper;

use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

use PHPCR\Util\TreeWalker;
use PHPCR\Util\Console\Helper\TreeDumper\ConsoleDumperNodeVisitor;
use PHPCR\Util\Console\Helper\TreeDumper\ConsoleDumperPropertyVisitor;
use PHPCR\Util\Console\Helper\TreeDumper\SystemNodeFilter;

/**
* Command subtrees under a path to the console
*
Expand All @@ -43,21 +41,14 @@
*/
class NodeDumpCommand extends BaseCommand
{
/**
* Limit after which to cut lines when dumping properties
*
* @var int
*/
private $dump_max_line_length = 120;

/**
* {@inheritDoc}
*/
protected function configure()
{
$this
->setName('phpcr:node:dump')
->addOption('sys_nodes', null, InputOption::VALUE_NONE, 'Also dump system nodes')
->addOption('sys-nodes', null, InputOption::VALUE_NONE, 'Also dump system nodes (recommended to use with a depth limit)')
->addOption('props', null, InputOption::VALUE_NONE, 'Also dump properties of the nodes')
->addOption('identifiers', null, InputOption::VALUE_NONE, 'Also output node UUID')
->addOption('depth', null, InputOption::VALUE_OPTIONAL, 'Limit how many level of children to show', "-1")
Expand All @@ -72,29 +63,20 @@ protected function configure()
displayed as yaml arrays.
By default the command filters out system nodes and properties (i.e. nodes and
properties with names starting with 'jcr:'), the <info>sys_nodes</info> option
properties with names starting with 'jcr:'), the <info>--sys-nodes</info> option
allows to turn this filter off.
HERE
)
;
}

/**
* Change at which length lines in the dump get cut.
*
* @param int $length maximum line length after which to cut the output.
*/
public function setDumpMaxLineLength($length)
{
$this->dump_max_line_length = $length;
}

/**
* {@inheritDoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$session = $this->getPhpcrSession();
/** @var $dumperHelper PhpcrConsoleDumperHelper */
$dumperHelper = $this->getHelper('phpcr_console_dumper');

// node to dump
Expand Down
13 changes: 10 additions & 3 deletions src/PHPCR/Util/NodeHelper.php
Expand Up @@ -23,6 +23,7 @@

use PHPCR\ItemInterface;
use PHPCR\NodeInterface;
use PHPCR\PropertyInterface;
use PHPCR\PropertyType;
use PHPCR\SessionInterface;
use PHPCR\RepositoryException;
Expand Down Expand Up @@ -50,7 +51,7 @@ private function __construct()
* @param SessionInterface $session the PHPCR session to create the path
* @param string $path full path, like /content/jobs/data
*
* @return \PHPCR\NodeInterface the last node of the path, i.e. data
* @return NodeInterface the last node of the path, i.e. data
*/
public static function createPath(SessionInterface $session, $path)
{
Expand Down Expand Up @@ -87,12 +88,14 @@ public static function purgeWorkspace(SessionInterface $session)
{
$root = $session->getRootNode();

/** @var $property PropertyInterface */
foreach ($root->getProperties() as $property) {
if (! self::isSystemItem($property)) {
$property->remove();
}
}

/** @var $node NodeInterface */
foreach ($root->getNodes() as $node) {
if (! self::isSystemItem($node)) {
$node->remove();
Expand All @@ -111,13 +114,17 @@ public static function deleteAllNodes(SessionInterface $session)
}

/**
* Determine whether this item has a namespace that is to be considered
* a system namespace
* Determine whether this item is to be considered a system item that you
* usually want to hide and that should not be removed when purging the
* repository.
*
* @param ItemInterface $item
*/
public static function isSystemItem(ItemInterface $item)
{
if ($item->getDepth() > 1) {
return false;
}
$name = $item->getName();

return strpos($name, 'jcr:') === 0 || strpos($name, 'rep:') === 0;
Expand Down
65 changes: 40 additions & 25 deletions src/PHPCR/Util/PathHelper.php
Expand Up @@ -36,9 +36,11 @@ class PathHelper
/**
* Do not create an instance of this class
*/
// @codeCoverageIgnoreStart
private function __construct()
{
}
// @codeCoverageIgnoreEnd

/**
* Check whether this is a syntactically valid absolute path.
Expand Down Expand Up @@ -66,19 +68,10 @@ public static function assertValidAbsolutePath($path, $destination = false, $thr
|| strlen($path) > 1 && '/' === $path[strlen($path) - 1]
|| preg_match('-//|/\./|/\.\./-', $path)
) {
if ($throw) {
throw new RepositoryException("Invalid path $path");
}

return false;
return self::error("Invalid path $path", $throw);
}
if ($destination && ']' === $path[strlen($path) - 1]) {
if ($throw) {
throw new RepositoryException("Destination path may not end with index $path");
}

return false;

return self::error("Destination path may not end with index $path", $throw);
}

return true;
Expand All @@ -95,7 +88,8 @@ public static function assertValidAbsolutePath($path, $destination = false, $thr
* encode and decode characters that are not natively allowed by a storage
* engine.
*
* @param string $name The name to check
* @param string $name The name to check
* @param boolean $throw whether to throw an exception on validation errors.
*
* @return bool true if valid, false if not valid and $throw was false
*
Expand All @@ -106,11 +100,11 @@ public static function assertValidAbsolutePath($path, $destination = false, $thr
public static function assertValidLocalName($name, $throw = true)
{
if ('.' == $name || '..' == $name) {
throw new RepositoryException('Name may not be parent or self identifier: ' . $name);
return self::error("Name may not be parent or self identifier: $name", $throw);
}

if (preg_match('/\\/|:|\\[|\\]|\\||\\*/', $name)) {
throw new RepositoryException('Name contains illegal characters: '.$name);
return self::error("Name contains illegal characters: $name", $throw);
}

return true;
Expand Down Expand Up @@ -141,24 +135,18 @@ public static function assertValidLocalName($name, $throw = true)
public static function normalizePath($path, $destination = false, $throw = true)
{
if (!is_string($path)) {
throw new RepositoryException('Expected string but got ' . gettype($path));
return self::error('Expected string but got ' . gettype($path), $throw);
}

if (strlen($path) === 0) {
throw new RepositoryException('Path must not be of zero length');
return self::error('Path must not be of zero length', $throw);
}

if ('/' === $path) {

return '/';
}

if ('/' !== $path[0]) {
if ($throw) {
throw new RepositoryException("Not an absolute path '$path'");
}

return false;
return self::error("Not an absolute path '$path'", $throw);
}

$finalParts= array();
Expand Down Expand Up @@ -211,9 +199,16 @@ public static function normalizePath($path, $destination = false, $throw = true)
*/
public static function absolutizePath($path, $context, $destination = false, $throw = true)
{
if (! $path) {
throw new RepositoryException('empty path');
if (!is_string($path)) {
return self::error('Expected string path but got ' . gettype($path), $throw);
}
if (!is_string($context)) {
return self::error('Expected string context but got ' . gettype($context), $throw);
}
if (strlen($path) === 0) {
return self::error('Path must not be of zero length', $throw);
}

if ('/' !== $path[0]) {
$path = ('/' === $context) ? "/$path" : "$context/$path";
}
Expand Down Expand Up @@ -270,4 +265,24 @@ public static function getPathDepth($path)
{
return substr_count(rtrim($path, '/'), '/');
}

/**
* If $throw is true, throw a RepositoryException with $msg. Otherwise
* return false.
*
* @param string $msg the exception message to use in case of throw being true
* @param boolean $throw whether to throw the exception or return false
*
* @return boolean false
*
* @throws RepositoryException
*/
private static function error($msg, $throw)
{
if ($throw) {
throw new RepositoryException($msg);
}

return false;
}
}

0 comments on commit 04f0b23

Please sign in to comment.