Skip to content

Commit 84814b2

Browse files
committed
Updated command
1 parent fa13ea3 commit 84814b2

File tree

4 files changed

+162
-32
lines changed

4 files changed

+162
-32
lines changed

features/bootstrap/FeatureContext.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,15 @@ public function thereExistsAPropertyAt($arg1)
471471
$session->getProperty($arg1);
472472
}
473473

474+
/**
475+
* @Given /^there should exist a property at "([^"]*)"$/
476+
*/
477+
public function thereShouldExistAPropertyAt($arg1)
478+
{
479+
$session = $this->getSession();
480+
$session->getProperty($arg1);
481+
}
482+
474483
/**
475484
* @Given /^there should not exist a property at "([^"]*)"$/
476485
*/

features/phpcr_file_import.feature

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
Feature: Import an external file as to a node
2+
In order to import an external file into the system
3+
As a user that is logged into the shell
4+
I should be able to run a command which does that
5+
6+
Background:
7+
Given that I am logged in as "testuser"
8+
And the "cms.xml" fixtures are loaded
9+
And the file "phpcr.png" contains the contents of "files/phpcrlogos.png"
10+
And the current node is "/"
11+
12+
Scenario: Import a file
13+
Given I execute the "file:import . phpcr.png" command
14+
Then the command should not fail
15+
And I save the session
16+
Then the command should not fail
17+
And there should exist a node at "/phpcr.png"
18+
And the node at "/phpcr.png/jcr:content" should have the property "jcr:mimeType" with value "image/png"
19+
20+
Scenario: Import a file onto existing file, no overwrite specified
21+
Given I execute the "file:import . phpcr.png" command
22+
And I execute the "file:import . phpcr.png" command
23+
Then the command should fail
24+
25+
Scenario: Import a file onto existing file, force not specified
26+
Given I execute the "file:import . phpcr.png --no-interaction" command
27+
And I execute the "file:import . phpcr.png" command
28+
Then the command should fail
29+
30+
Scenario: Import a file onto existing file, force specified
31+
Given I execute the "file:import . phpcr.png" command
32+
And I execute the "file:import . phpcr.png --force" command
33+
Then the command should not fail
34+
And I save the session
35+
Then the command should not fail
36+
And there should exist a node at "/phpcr.png"
37+
And the node at "/phpcr.png/jcr:content" should have the property "jcr:mimeType" with value "image/png"
38+
39+
Scenario: Import a file, override mime type
40+
Given I execute the "file:import . phpcr.png --mime-type=application/data" command
41+
Then the command should not fail
42+
And I save the session
43+
Then the command should not fail
44+
And there should exist a node at "/phpcr.png"
45+
And the node at "/phpcr.png/jcr:content" should have the property "jcr:mimeType" with value "application/data"
46+
47+
Scenario: Import a file, specify a name
48+
Given I execute the "file:import ./foobar.png phpcr.png --mime-type=application/data" command
49+
Then the command should not fail
50+
And I save the session
51+
Then the command should not fail
52+
And there should exist a node at "/foobar.png"
53+
54+
Scenario: Import a file to a specified property
55+
Given I execute the "file:import ./ phpcr.png --no-container" command
56+
Then the command should not fail
57+
And I save the session
58+
Then the command should not fail
59+
And there should exist a property at "/phpcr.png"
60+
61+
Scenario: Import overwrite a specified property
62+
Given I execute the "file:import ./ phpcr.png --no-container" command
63+
And I save the session
64+
And I execute the "file:import ./ phpcr.png --no-container" command
65+
Then the command should not fail
66+
And I save the session
67+
Then the command should not fail
68+
And there should exist a property at "/phpcr.png"

features/phpcr_node_file_import.feature

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/PHPCR/Shell/Console/Command/Phpcr/NodeFileImportCommand.php

Lines changed: 85 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,50 +7,120 @@
77
use Symfony\Component\Console\Output\OutputInterface;
88
use Symfony\Component\Console\Input\InputArgument;
99
use PHPCR\PropertyType;
10+
use Symfony\Component\Console\Input\InputOption;
11+
use PHPCR\PathNotFoundException;
1012

1113
class NodeFileImportCommand extends Command
1214
{
15+
/**
16+
* @var PHPCR\SessionInterface
17+
*/
18+
protected $session;
19+
1320
protected function configure()
1421
{
15-
$this->setName('node:file:import');
22+
$this->setName('file:import');
1623
$this->setDescription('Import a file at the given path');
1724
$this->addArgument('path', InputArgument::REQUIRED, 'Path to import file to');
1825
$this->addArgument('file', InputArgument::REQUIRED, 'Path to file to import');
26+
$this->addOption('mime-type', null, InputOption::VALUE_REQUIRED, 'Mime type (optional, auto-detected)');
27+
$this->addOption('force', null, InputOption::VALUE_NONE, 'Force overwriting any existing node');
28+
$this->addOption('no-container', null, InputOption::VALUE_NONE, 'Do not wrap in a JCR nt:file, but write directly to the specified property');
1929
$this->setHelp(<<<HERE
2030
Import an external file into the repository.
2131
22-
The file will be imported as a node of built-in type <comment>nt:file</comment>. The new
23-
node will be named after the file.
32+
The file will be imported as a node of built-in type <comment>nt:file</comment>.
33+
34+
If a Node is specified as <info>path</info> then the filename of the imported file will be used
35+
as the new node, otherwise, if the target <info>path</info> does not exist, then it is assumed
36+
that the path is the target path for the new file, including the filename.
37+
38+
PHPCRSH> file:import ./ foobar.png
39+
PHPCRSH> file:import ./barfoo.png foobar.png
40+
41+
In the first example above will create <info>/foobar.png</info>, whereas the second will create
42+
<info>./barfoo.png</info>.
43+
44+
By default the file will be imported in a container, i.e. a node with type <info>nt:file</info>. In
45+
addition to the file data, the node will contain metadata.
2446
25-
The mime-type will be inferred automatically..
47+
Alternatively you can specify the <info>--no-container</info> option to import directly to a single property.
48+
49+
The mime-type of the file (in the case where a container is used) will be automatically determined unless
50+
specified with <info>--mime-type</info>.
2651
HERE
2752
);
2853
}
2954

3055
public function execute(InputInterface $input, OutputInterface $output)
3156
{
32-
$session = $this->getHelper('phpcr')->getSession();
57+
$this->session = $this->getHelper('phpcr')->getSession();
3358

34-
$file = $input->getArgument('file');
35-
$path = $session->getAbsPath($input->getArgument('path'));
59+
$filePath = $input->getArgument('file');
60+
$force = $input->getOption('force');
61+
$noContainer = $input->getOption('no-container');
3662

37-
$parentNode = $session->getNode($path);
63+
$path = $this->session->getAbsPath($input->getArgument('path'));
64+
$mimeType = $input->getOption('mime-type');
65+
$filename = basename($filePath);
3866

39-
if (!file_exists($file)) {
67+
if (!file_exists($filePath)) {
4068
throw new \InvalidArgumentException(sprintf(
4169
'File "%s" does not exist.',
42-
$file
70+
$filePath
4371
));
4472
}
4573

46-
$finfo = finfo_open(FILEINFO_MIME_TYPE);
47-
$mimeType = finfo_file($finfo, $file);
74+
try {
75+
// first assume the user specified the path to the parent node
76+
$parentNode = $this->session->getNode($path);
77+
} catch (PathNotFoundException $e) {
78+
// if the given path does not exist, assume that the basename is the target
79+
// filename and the dirname the path to the parent node
80+
$parentPath = dirname($path);
81+
$parentNode = $this->session->getNode($parentPath);
82+
$filename = basename($path);
83+
}
84+
85+
$fhandle = fopen($filePath, 'r');
86+
87+
if ($noContainer) {
88+
$this->importToProperty($fhandle, $filePath, $filename, $parentNode, $force);
89+
} else {
90+
$this->importToContainer($fhandle, $mimeType, $filePath, $filename, $parentNode, $force);
91+
}
92+
}
93+
94+
private function importToProperty($fhandle, $filePath, $filename, $parentNode, $force)
95+
{
96+
$parentNode->setProperty($filename, $fhandle, PropertyType::BINARY);
97+
}
98+
99+
private function importToContainer($fhandle, $mimeType, $file, $filename, $parentNode, $force)
100+
{
101+
// if no mime-type specified, guess it.
102+
if (!$mimeType) {
103+
$finfo = finfo_open(FILEINFO_MIME_TYPE);
104+
$mimeType = finfo_file($finfo, $file);
105+
}
106+
107+
// handle existing node
108+
if ($parentNode->hasNode($filename)) {
109+
if (true === $force) {
110+
$fileNode = $parentNode->getNode($filename);
111+
$this->session->removeItem($fileNode->getPath());
112+
} else {
113+
throw new \InvalidArgumentException(sprintf(
114+
'Node "%s" already has child "%s". Use --force to overwrite.',
115+
$parentNode->getPath(),
116+
$filename
117+
));
118+
}
119+
}
48120

49-
$filename = basename($file);
50121
$fileNode = $parentNode->addNode($filename, 'nt:file');
51122
$contentNode = $fileNode->addNode('jcr:content', 'nt:unstructured');
52-
$content = file_get_contents($file);
53-
$contentNode->setProperty('jcr:data', $content, PropertyType::BINARY);
123+
$contentNode->setProperty('jcr:data', $fhandle, PropertyType::BINARY);
54124
$contentNode->setProperty('jcr:mimeType', $mimeType);
55125
}
56126
}

0 commit comments

Comments
 (0)