Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 25 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
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.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the list of commands was totally outdated. better point to the self-doc than trying to replicate it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1


## 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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)')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was leftover from the refactoring, it is now in the console dumper helper.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is kind of a BC break but before we already checked for sys-nodes, so it stopped working. and the convention is -, not _

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

->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
Original file line number Diff line number Diff line change
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 */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is a IDE helper comment. Why doesn't the IDE pick up the right typing here? Are there missing doc blocks for return types or something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah thats because of the foreach that the ide does not see what it will get

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;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a change in behaviour, but i think it makes sense. before we skipped things like the jcr:resource of an nt:file node, which is stupid and confusing. the intention was to not dump the version history and similar things by default, and to not delete that in the purge operation.

@dantleech so now this would be the place for your input as i closed #73 and merged into here to avoid the testing chaos i produced. ok if we do that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the road atm, not quite sure of implications of the sys node change, but if you and lukas agree thats ok by me. One thing i was going to suggest was maybe moving the repository exception to a method to avoide the several "if throw" methods.

Can try and have a proper look thos evening if I manage to plug my laptop in!

David Buchmann notifications@github.com a écrit :

  *
  * @param ItemInterface $item
  */
 public static function isSystemItem(ItemInterface $item)
 {
  •    if ($item->getDepth() > 1) {
    
  •        return false;
    
  •    }
    

this is a change in behaviour, but i think it makes sense. before we
skipped things like the jcr:resource of an nt:file node, which is
stupid and confusing. the intention was to not dump the version history
and similar things by default, and to not delete that in the purge
operation.

@dantleech so now this would be the place for your input as i closed
#73 and merged into here to avoid the testing chaos i produced. ok if
we do that?


Reply to this email directly or view it on GitHub:
https://github.com/phpcr/phpcr-utils/pull/72/files#r4884943

Envoyé de mon téléphone Android avec K-9 Mail. Excusez la brièveté.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, will move that check to a method.

$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
Original file line number Diff line number Diff line change
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;
}
}
Loading