Skip to content

Commit d9f8fab

Browse files
#1 Add ZipTask and UnzipTask
1 parent f613d61 commit d9f8fab

File tree

7 files changed

+269
-2
lines changed

7 files changed

+269
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
v1.0.0
22
------
33

4-
* Initial release
4+
* Initial release with ZipTask and UnzipTask.

config/services/task.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,14 @@
11
services:
2+
cleverage_archive_process.task.unzip:
3+
class: CleverAge\ArchiveProcessBundle\Task\UnzipTask
4+
shared: false
5+
CleverAge\ArchiveProcessBundle\Task\UnzipTask:
6+
alias: cleverage_archive_process.task.unzip
7+
public: true
8+
9+
cleverage_archive_process.task.zip:
10+
class: CleverAge\ArchiveProcessBundle\Task\ZipTask
11+
shared: false
12+
CleverAge\ArchiveProcessBundle\Task\ZipTask:
13+
alias: cleverage_archive_process.task.zip
14+
public: true

docs/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ CleverAge\ArchiveProcessBundle\CleverAgeArchiveProcessBundle::class => ['all' =>
2222
## Reference
2323

2424
- Tasks
25-
- @TODO
25+
- [UnzipTask](reference/tasks/unzip_task.md)
26+
- [ZipTask](reference/tasks/zip_task.md)

docs/reference/tasks/unzip_task.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
UnzipTask
2+
===============
3+
4+
Unzip a file, requires the destination path in options.
5+
6+
Task reference
7+
--------------
8+
9+
* **Task Service**: `CleverAge\ArchiveProcessBundle\Task\UnzipTask`
10+
11+
Accepted inputs
12+
---------------
13+
14+
`array`: inputs are merged with task defined options.
15+
16+
Possible outputs
17+
----------------
18+
19+
`string`: the destination directory where zip file was extracted.
20+
21+
Options
22+
-------
23+
24+
| Code | Type | Required | Default | Description |
25+
|---------------|----------|:--------:|----------|-------------------------------------------------------|
26+
| `filename` | `string` | **X** | | Zip filename to extract |
27+
| `destination` | `string` | **X** | | Destination directory where zip content was extracted |
28+
29+
Examples
30+
--------
31+
32+
### Task
33+
34+
```yaml
35+
# Task configuration level
36+
code:
37+
service: '@CleverAge\ArchiveProcessBundle\Task\UnzipTask'
38+
options:
39+
filename: '%kernel.project_dir%/var/data/archive.zip'
40+
destination: '%kernel.project_dir%/var/data/unzip_archive'
41+
```

docs/reference/tasks/zip_task.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
ZipTask
2+
===============
3+
4+
Zip files into a given filename.
5+
6+
Task reference
7+
--------------
8+
9+
* **Task Service**: `CleverAge\ArchiveProcessBundle\Task\ZipTask`
10+
11+
Accepted inputs
12+
---------------
13+
14+
`array`: inputs are merged with task defined options.
15+
16+
Possible outputs
17+
----------------
18+
19+
`string`: the zip created filename.
20+
21+
Options
22+
-------
23+
24+
| Code | Type | Required | Default | Description |
25+
|-------------------|---------------------|:---------:|----------|---------------------------------------|
26+
| `filename` | `string` | **X** | | Zip to create filename |
27+
| `files` | `string` or `array` | **X** | | Files to add on archive |
28+
| `files_base_path` | `string` | | '' | Base directory where files to add are |
29+
30+
Examples
31+
--------
32+
33+
### Task
34+
35+
```yaml
36+
# Task configuration level
37+
code:
38+
service: '@CleverAge\ArchiveProcessBundle\Task\ZipTask'
39+
options:
40+
filename: '%kernel.project_dir%/var/data/zip_archive.zip'
41+
files:
42+
- '%kernel.project_dir%/var/data/sample.txt'
43+
files_base_path: '%kernel.project_dir%/var/data'
44+
```

src/Task/UnzipTask.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the CleverAge/ArchiveProcessBundle package.
7+
*
8+
* Copyright (c) Clever-Age
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace CleverAge\ArchiveProcessBundle\Task;
15+
16+
use CleverAge\ProcessBundle\Model\AbstractConfigurableTask;
17+
use CleverAge\ProcessBundle\Model\ProcessState;
18+
use Symfony\Component\OptionsResolver\OptionsResolver;
19+
20+
/**
21+
* Unzip a file, requires the destination path in options.
22+
*/
23+
class UnzipTask extends AbstractConfigurableTask
24+
{
25+
public function execute(ProcessState $state): void
26+
{
27+
if (null === $state->getInput()) {
28+
$state->setInput([]);
29+
}
30+
/**
31+
* @var array{filename: string, destination: string} $options
32+
*/
33+
$options = $this->getOptions($state);
34+
$filename = $options['filename'];
35+
36+
if (!file_exists($filename)) {
37+
throw new \UnexpectedValueException("File does not exists: '{$filename}'");
38+
}
39+
40+
if (!is_readable($filename)) {
41+
throw new \UnexpectedValueException("File is not readable: '{$filename}'");
42+
}
43+
44+
$dest = $options['destination'];
45+
46+
$zipArchive = new \ZipArchive();
47+
$res = $zipArchive->open($filename);
48+
if (true === $res) {
49+
$zipArchive->extractTo($dest);
50+
$zipArchive->close();
51+
} else {
52+
throw new \RuntimeException("Unable to open file {$filename}");
53+
}
54+
55+
$state->setOutput($dest);
56+
}
57+
58+
protected function configureOptions(OptionsResolver $resolver): void
59+
{
60+
$resolver->setRequired(['filename', 'destination']);
61+
$resolver->setAllowedTypes('filename', ['string']);
62+
$resolver->setAllowedTypes('destination', ['string']);
63+
}
64+
65+
/**
66+
* @return array{filename: string, destination: string}|null
67+
*/
68+
protected function getOptions(ProcessState $state): ?array
69+
{
70+
if (null === $this->options && \is_array($state->getInput())) {
71+
$resolver = new OptionsResolver();
72+
$this->configureOptions($resolver);
73+
$this->options = $resolver->resolve(array_merge($state->getContextualizedOptions() ?? [], $state->getInput()));
74+
}
75+
76+
// @phpstan-ignore return.type
77+
return $this->options;
78+
}
79+
}

src/Task/ZipTask.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the CleverAge/ArchiveProcessBundle package.
7+
*
8+
* Copyright (c) Clever-Age
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace CleverAge\ArchiveProcessBundle\Task;
15+
16+
use CleverAge\ProcessBundle\Model\AbstractConfigurableTask;
17+
use CleverAge\ProcessBundle\Model\ProcessState;
18+
use Symfony\Component\OptionsResolver\OptionsResolver;
19+
20+
/**
21+
* Zip files into a given filename.
22+
*/
23+
class ZipTask extends AbstractConfigurableTask
24+
{
25+
public function execute(ProcessState $state): void
26+
{
27+
if (null === $state->getInput()) {
28+
$state->setInput([]);
29+
}
30+
/**
31+
* @var array{filename: string, files: array<string>|string, files_base_path: string} $options
32+
*/
33+
$options = $this->getOptions($state);
34+
35+
$zip = new \ZipArchive();
36+
$ret = $zip->open($options['filename'], \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
37+
if (true !== $ret) {
38+
throw new \RuntimeException("Fail to open file {$options['filename']} with code {$ret}");
39+
}
40+
41+
$files = $options['files'];
42+
if (\is_string($files)) {
43+
$files = [$files];
44+
}
45+
foreach ($files as $file) {
46+
$currentFilename = ltrim(str_replace($options['files_base_path'], '', $file), \DIRECTORY_SEPARATOR);
47+
$currentFilepath = $options['files_base_path'].\DIRECTORY_SEPARATOR.$currentFilename;
48+
if (!file_exists($currentFilepath)) {
49+
throw new \UnexpectedValueException("File does not exists: '{$currentFilepath}'");
50+
}
51+
if (!is_readable($currentFilepath)) {
52+
throw new \UnexpectedValueException("File is not readable: '{$currentFilepath}'");
53+
}
54+
if (false === $zip->addFile($currentFilepath, $currentFilename)) {
55+
throw new \RuntimeException("Unable to add file {$currentFilepath} to zip");
56+
}
57+
}
58+
59+
$zip->close();
60+
61+
$state->setOutput($options['filename']);
62+
}
63+
64+
protected function configureOptions(OptionsResolver $resolver): void
65+
{
66+
$resolver->setRequired(['filename', 'files', 'files_base_path']);
67+
$resolver->setAllowedTypes('filename', ['string']);
68+
$resolver->setAllowedTypes('files', ['string', 'array']);
69+
$resolver->setAllowedTypes('files_base_path', ['string']);
70+
$resolver->setDefaults([
71+
'files_base_path' => '',
72+
]);
73+
}
74+
75+
/**
76+
* @return array{filename: string, files: array<string>|string, files_base_path: string}|null
77+
*/
78+
protected function getOptions(ProcessState $state): ?array
79+
{
80+
if (null === $this->options && \is_array($state->getInput())) {
81+
$resolver = new OptionsResolver();
82+
$this->configureOptions($resolver);
83+
$this->options = $resolver->resolve(array_merge($state->getContextualizedOptions() ?? [], $state->getInput()));
84+
}
85+
86+
// @phpstan-ignore return.type
87+
return $this->options;
88+
}
89+
}

0 commit comments

Comments
 (0)