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

Commit

Permalink
Improving the storage event listeners.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Florian Krämer committed Jan 20, 2016
1 parent 5be989e commit 9bece86
Show file tree
Hide file tree
Showing 5 changed files with 322 additions and 208 deletions.
72 changes: 49 additions & 23 deletions docs/Tutorials/Quick-Start.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,26 @@ app/Config/file_storage.php

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.

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.

```php
use Aws\S3;
use Burzum\FileStorage\Event\ImageProcessingListener;
use Burzum\FileStorage\Event\S3StorageListener;
use Burzum\FileStorage\Lib\FileStorageUtils;
use Burzum\FileStorage\Lib\StorageManager;
use Aws\S3\S3Client;
use Burzum\FileStorage\Storage\Listener\BaseListener;
use Burzum\FileStorage\Storage\StorageUtils;
use Burzum\FileStorage\Storage\StorageManager;
use Cake\Core\Configure;
use Cake\Event\EventManager;

// Attach the S3 Listener to the global EventManager
$listener = new S3StorageListener();
EventManager::instance()->on($listener);

// Attach the Image Processing Listener to the global EventManager
$listener = new ImageProcessingListener();
// Instantiate a storage event listener
$listener = new BaseListener(
'imageProcessing' => true, // Required if you want image processing!
'pathBuilderOptions' => [
// Preserves the original filename in the storage backend.
// Otherwise it would use a UUID as filename by default.
'preserveFilename' => true
]
);
// Attach the BaseListener to the global EventManager
EventManager::instance()->on($listener);

Configure::write('FileStorage', [
Expand Down Expand Up @@ -65,27 +70,48 @@ Configure::write('FileStorage', [
]);

// This is very important! The hashes are needed to calculate the image versions!
FileStorageUtils::generateHashes();

// Optional, lets use the AwsS3 adapter here instead of local
$S3Client = \Aws\S3\S3Client::factory([
'key' => 'YOUR-KEY',
'secret' => 'YOUR-SECRET'
]);
StorageUtils::generateHashes();

// Lets use the Amazon S3 adapter here instead of the default `Local` config.
// We need to pass a S3Client instance to this adapter to make it work
$S3Client = new S3Client([
'version' => 'latest',
'region' => 'eu-central-1',
'credentials' => [
'key' => 'YOUR-AWS-S3-KEY-HERE',
'secret' => 'YOUR-SECRET-HERE'
]
]);

// Configure the Gaufrette adapter through the StorageManager
StorageManager::config('S3Image', [
'adapterOptions' => [
// Configure the S3 adapter instance through the StorageManager
StorageManager::config('S3', [
'adapterOptions' => array(
$S3Client,
'YOUR-BUCKET-NAME',
'YOUR-BUCKET-NAME-HERE', // Bucket
[],
true
],
),
'adapterClass' => '\Gaufrette\Adapter\AwsS3',
'class' => '\Gaufrette\Filesystem'
]);
```

If you did everything right you can now run this command from your app:

```sh
bin/cake storage store <some-file-to-store-here> --adapter S3
```

If you did everything right your should see some output like this:

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!

```
File successfully saved!
UUID: ebb21e79-029d-441d-8f2e-d8c20ca8f5a9
Path: file_storage/18/ef/b4/ebb21e79029d441d8f2ed8c20ca8f5a9/<some-file-to-store-here>
```

**It is highly recommended to read the following sections to understand how this works.**

* [Included Event Listeners](../Documentation/Included-Event-Listeners.md)
Expand Down
51 changes: 51 additions & 0 deletions src/Shell/StorageShell.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
namespace Burzum\FileStorage\Shell;

use Cake\Console\Shell;
use Burzum\FileStorage\Storage\StorageUtils;
use Burzum\FileStorage\Storage\StorageManager;

class StorageShell extends Shell {

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

public function getOptionParser() {
$parser = parent::getOptionParser();
$parser->addOption('adapter', [
'short' => 'a',
'help' => __('The adapter config name to use.'),
'default' => 'Local'
]);
$parser->addOption('model', [
'short' => 'm',
'help' => __('The model / table to use.'),
'default' => 'Burzum/FileStorage.FileStorage'
]);
$parser->addSubcommand('image', [
'help' => __('Image Processing Task.'),
'parser' => $this->Image->getOptionParser()
]);
$parser->addSubcommand('store', [
'help' => __('Stores a file in the DB.'),
]);
return $parser;
}

/**
* Store a local file via command line in any storage backend.
*
* @return void
*/
public function store() {
$model = $this->loadModel($this->params['model']);
if (empty($this->args[0])) {
$this->error('No file provided!');
}

if (!file_exists($this->args[0])) {
$this->error('The file does not exist!');
}

$adapterConfig = StorageManager::config($this->params['adapter']);
if (empty($adapterConfig)) {
$this->error(sprintf('Invalid adapter config `%s` provided!', $this->params['adapter']));
}

$fileData = StorageUtils::fileToUploadArray($this->args[0]);
$entity = $model->newEntity([
'adapter' => $this->params['adapter'],
'file' => $fileData,
'filename' => $fileData['name']
]);

if ($model->save($entity)) {
$this->out('File successfully saved!');
$this->out('UUID: ' . $entity->id);
$this->out('Path: ' . $entity->path());
} else {
$this->error('Failed to save the file.');
}
}
}
11 changes: 8 additions & 3 deletions src/Storage/Listener/AbstractListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,20 @@ public function implementedEvents() {
* Check if the event is of a type or subject object of type model we want to
* process with this listener.
*
* @throws \InvalidArgumentException
* @param Event $event
* @return boolean
* @return bool
* @throws \Burzum\FileStorage\Storage\StorageException
*/
protected function _checkEvent(Event $event) {
$className = $this->_getAdapterClassFromConfig($event->data['record']['adapter']);
$classes = $this->_adapterClasses;
if (!empty($classes) && !in_array($className, $this->_adapterClasses)) {
$message = 'The listener `%s` doesn\'t allow the `%s` adapter class! Probably because it can\'t work with it.';
throw new StorageException(sprintf($message, get_class($this), $className));
}
return (
isset($event->data['table'])
&& $event->data['table'] instanceof Table
&& $this->getAdapterClassName($event->data['record']['adapter'])
&& $this->_modelFilter($event)
);
}
Expand Down
Loading

0 comments on commit 9bece86

Please sign in to comment.