Skip to content
This repository was archived by the owner on Mar 5, 2022. It is now read-only.

Commit 9bece86

Browse files
author
Florian Krämer
committed
Improving the storage event listeners.
There is now an exception throw if a listener can't work with a specific adapter. Also I've introduced a new BaseListener that doesn't have any restrictions on which adapter it will take. In theory you can use it with any storage backend as long as the path it builds for the files is compatible with your chosen storage backend. A new shell command has been introduced to store a file via command line. The Quick Start tutorial has been updated as well.
1 parent 5be989e commit 9bece86

File tree

5 files changed

+322
-208
lines changed

5 files changed

+322
-208
lines changed

docs/Tutorials/Quick-Start.md

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,26 @@ app/Config/file_storage.php
1818

1919
There is a good amount of code to be added to prepare everything. In theory you can put all of this in bootstrap as well but to keep things clean it is recommended to put all of this in a separate file.
2020

21+
This might look like a lot things to do but when this is done storing the files will work immediately and you have a *very* flexible and powerful storage system configured.
22+
2123
```php
22-
use Aws\S3;
23-
use Burzum\FileStorage\Event\ImageProcessingListener;
24-
use Burzum\FileStorage\Event\S3StorageListener;
25-
use Burzum\FileStorage\Lib\FileStorageUtils;
26-
use Burzum\FileStorage\Lib\StorageManager;
24+
use Aws\S3\S3Client;
25+
use Burzum\FileStorage\Storage\Listener\BaseListener;
26+
use Burzum\FileStorage\Storage\StorageUtils;
27+
use Burzum\FileStorage\Storage\StorageManager;
2728
use Cake\Core\Configure;
2829
use Cake\Event\EventManager;
2930

30-
// Attach the S3 Listener to the global EventManager
31-
$listener = new S3StorageListener();
32-
EventManager::instance()->on($listener);
33-
34-
// Attach the Image Processing Listener to the global EventManager
35-
$listener = new ImageProcessingListener();
31+
// Instantiate a storage event listener
32+
$listener = new BaseListener(
33+
'imageProcessing' => true, // Required if you want image processing!
34+
'pathBuilderOptions' => [
35+
// Preserves the original filename in the storage backend.
36+
// Otherwise it would use a UUID as filename by default.
37+
'preserveFilename' => true
38+
]
39+
);
40+
// Attach the BaseListener to the global EventManager
3641
EventManager::instance()->on($listener);
3742

3843
Configure::write('FileStorage', [
@@ -65,27 +70,48 @@ Configure::write('FileStorage', [
6570
]);
6671

6772
// This is very important! The hashes are needed to calculate the image versions!
68-
FileStorageUtils::generateHashes();
69-
70-
// Optional, lets use the AwsS3 adapter here instead of local
71-
$S3Client = \Aws\S3\S3Client::factory([
72-
'key' => 'YOUR-KEY',
73-
'secret' => 'YOUR-SECRET'
74-
]);
73+
StorageUtils::generateHashes();
74+
75+
// Lets use the Amazon S3 adapter here instead of the default `Local` config.
76+
// We need to pass a S3Client instance to this adapter to make it work
77+
$S3Client = new S3Client([
78+
'version' => 'latest',
79+
'region' => 'eu-central-1',
80+
'credentials' => [
81+
'key' => 'YOUR-AWS-S3-KEY-HERE',
82+
'secret' => 'YOUR-SECRET-HERE'
83+
]
84+
]);
7585

76-
// Configure the Gaufrette adapter through the StorageManager
77-
StorageManager::config('S3Image', [
78-
'adapterOptions' => [
86+
// Configure the S3 adapter instance through the StorageManager
87+
StorageManager::config('S3', [
88+
'adapterOptions' => array(
7989
$S3Client,
80-
'YOUR-BUCKET-NAME',
90+
'YOUR-BUCKET-NAME-HERE', // Bucket
8191
[],
8292
true
83-
],
93+
),
8494
'adapterClass' => '\Gaufrette\Adapter\AwsS3',
8595
'class' => '\Gaufrette\Filesystem'
8696
]);
8797
```
8898

99+
If you did everything right you can now run this command from your app:
100+
101+
```sh
102+
bin/cake storage store <some-file-to-store-here> --adapter S3
103+
```
104+
105+
If you did everything right your should see some output like this:
106+
107+
If you're not familiar with the CakePHP shell and running into problems with the shell, not the plugin itself, please [read this](http://book.cakephp.org/3.0/en/console-and-shells.html) first!
108+
109+
```
110+
File successfully saved!
111+
UUID: ebb21e79-029d-441d-8f2e-d8c20ca8f5a9
112+
Path: file_storage/18/ef/b4/ebb21e79029d441d8f2ed8c20ca8f5a9/<some-file-to-store-here>
113+
```
114+
89115
**It is highly recommended to read the following sections to understand how this works.**
90116

91117
* [Included Event Listeners](../Documentation/Included-Event-Listeners.md)

src/Shell/StorageShell.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
namespace Burzum\FileStorage\Shell;
88

99
use Cake\Console\Shell;
10+
use Burzum\FileStorage\Storage\StorageUtils;
11+
use Burzum\FileStorage\Storage\StorageManager;
1012

1113
class StorageShell extends Shell {
1214

@@ -23,10 +25,59 @@ public function main() {}
2325

2426
public function getOptionParser() {
2527
$parser = parent::getOptionParser();
28+
$parser->addOption('adapter', [
29+
'short' => 'a',
30+
'help' => __('The adapter config name to use.'),
31+
'default' => 'Local'
32+
]);
33+
$parser->addOption('model', [
34+
'short' => 'm',
35+
'help' => __('The model / table to use.'),
36+
'default' => 'Burzum/FileStorage.FileStorage'
37+
]);
2638
$parser->addSubcommand('image', [
2739
'help' => __('Image Processing Task.'),
2840
'parser' => $this->Image->getOptionParser()
2941
]);
42+
$parser->addSubcommand('store', [
43+
'help' => __('Stores a file in the DB.'),
44+
]);
3045
return $parser;
3146
}
47+
48+
/**
49+
* Store a local file via command line in any storage backend.
50+
*
51+
* @return void
52+
*/
53+
public function store() {
54+
$model = $this->loadModel($this->params['model']);
55+
if (empty($this->args[0])) {
56+
$this->error('No file provided!');
57+
}
58+
59+
if (!file_exists($this->args[0])) {
60+
$this->error('The file does not exist!');
61+
}
62+
63+
$adapterConfig = StorageManager::config($this->params['adapter']);
64+
if (empty($adapterConfig)) {
65+
$this->error(sprintf('Invalid adapter config `%s` provided!', $this->params['adapter']));
66+
}
67+
68+
$fileData = StorageUtils::fileToUploadArray($this->args[0]);
69+
$entity = $model->newEntity([
70+
'adapter' => $this->params['adapter'],
71+
'file' => $fileData,
72+
'filename' => $fileData['name']
73+
]);
74+
75+
if ($model->save($entity)) {
76+
$this->out('File successfully saved!');
77+
$this->out('UUID: ' . $entity->id);
78+
$this->out('Path: ' . $entity->path());
79+
} else {
80+
$this->error('Failed to save the file.');
81+
}
82+
}
3283
}

src/Storage/Listener/AbstractListener.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,20 @@ public function implementedEvents() {
132132
* Check if the event is of a type or subject object of type model we want to
133133
* process with this listener.
134134
*
135-
* @throws \InvalidArgumentException
136135
* @param Event $event
137-
* @return boolean
136+
* @return bool
137+
* @throws \Burzum\FileStorage\Storage\StorageException
138138
*/
139139
protected function _checkEvent(Event $event) {
140+
$className = $this->_getAdapterClassFromConfig($event->data['record']['adapter']);
141+
$classes = $this->_adapterClasses;
142+
if (!empty($classes) && !in_array($className, $this->_adapterClasses)) {
143+
$message = 'The listener `%s` doesn\'t allow the `%s` adapter class! Probably because it can\'t work with it.';
144+
throw new StorageException(sprintf($message, get_class($this), $className));
145+
}
140146
return (
141147
isset($event->data['table'])
142148
&& $event->data['table'] instanceof Table
143-
&& $this->getAdapterClassName($event->data['record']['adapter'])
144149
&& $this->_modelFilter($event)
145150
);
146151
}

0 commit comments

Comments
 (0)