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

Commit

Permalink
Merge branch '1.1.0' of git://github.com/burzum/cakephp-file-storage …
Browse files Browse the repository at this point in the history
…into 1.1.0
  • Loading branch information
Florian Krämer committed Nov 18, 2015
2 parents bab7597 + b242e51 commit 63a43a5
Show file tree
Hide file tree
Showing 16 changed files with 294 additions and 60 deletions.
81 changes: 45 additions & 36 deletions docs/Documentation/How-To-Use.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Preparing the File Upload

This section is going to show how to store a file using the Storage Manager directly.

For example you have a Report model and want to save a pdf to it, you would then create an association like:
For example you have a Report table and want to save a pdf to it, you would then create an association like:

```php
public function initialize(array $config)
Expand All @@ -29,48 +29,21 @@ public function initialize(array $config)
}
```

In your `add.ctp` or `edit.ctp` views you would add something like:
In your `add.ctp` or `edit.ctp` views you would add something like this.

```php
echo $this->Form->create($report, ['type' => 'file']);
echo $this->Form->input('title');
echo $this->Form->input('pdf_files.file');
echo $this->Form->file('pdf_files.file'); // Pay attention here!
echo $this->Form->input('description');
echo $this->Form->submit(__('Submit'));
echo $this->Form->end();
```

Handling the File Upload
------------------------
[Make sure your form is using the right HTTP method](http://book.cakephp.org/3.0/en/views/helpers/form.html#changing-the-http-method-for-a-form)!

**Now comes the crucial point of the whole implementation**

Because of to many different requirements and personal preferences out there the plugin is *not* automatically storing the file. You'll have to customize it a little but its just a matter for a few lines.

Lets go by this scenario inside the report model, assuming there is an add() method:

```php
$entity = $this->newEntity($postData);
$saved = $this->save($entity);
if ($saved) {
$key = 'your-file-name';
if (StorageManager::adapter('Local')->write($key, file_get_contents($this->data['pdf_files']['file']['tmp_name']))) {
$postData['pdf_files']['foreign_key'] = $saved->id;
$postData['pdf_files']['model'] = 'Reports';
$postData['pdf_files']['path'] = $key;
$postData['pdf_files']['adapter'] = 'Local';
$this->PdfDocuments->save($this->PdfDocuments->newEntity($postData));
}
}
```

Later, when you want to delete the file, for example in the beforeDelete() or afterDelete() callback of your Report model, you'll know the adapter you have used to store the attached PdfFile and can get an instance of this adapter configuration using the StorageManager. By having the path or key available you can then simply call:

```php
StorageManager::adapter($data['PdfFile']['adapter'])->delete($data['PdfFile']['path']);
```

Insted of doing all of this in the model that has the files associated to it you can also simply extend the FileStorage model from the plugin and add your storage logic there and use that model for your association.

How to store an uploaded file II - using Events
-----------------------------------------------
Store an uploaded file using Events
-----------------------------------

The **FileStorage** plugin comes with a class that acts just as a listener to some of the events in this plugin. Take a look at [ImageProcessingListener.php](../../src/Event/ImageProcessingListener.php).

Expand Down Expand Up @@ -105,6 +78,42 @@ Event Listeners

See [this page](Included-Event-Listeners.md) for the event listeners that are included in the plugin.


Handling the File Upload Manually
---------------------------------

You'll have to customize it a little but its just a matter for a few lines.

Note the Listener expects a request data key `file` present in the form, so use `echo $this->Form->input('file');` to allow the Marshaller pick the right data from the uploaded file.

Lets go by this scenario inside the report table, assuming there is an add() method:

```php
public function add() {
$entity = $this->newEntity($postData);
$saved = $this->save($entity);
if ($saved) {
$key = 'your-file-name';
if (StorageManager::adapter('Local')->write($key, file_get_contents($this->data['pdf_files']['file']['tmp_name']))) {
$postData['pdf_files']['foreign_key'] = $saved->id;
$postData['pdf_files']['model'] = 'Reports';
$postData['pdf_files']['path'] = $key;
$postData['pdf_files']['adapter'] = 'Local';
$this->PdfDocuments->save($this->PdfDocuments->newEntity($postData));
}
}
return $entity;
}
```

Later, when you want to delete the file, for example in the beforeDelete() or afterDelete() callback of your Report model, you'll know the adapter you have used to store the attached PdfFile and can get an instance of this adapter configuration using the StorageManager. By having the path or key available you can then simply call:

```php
StorageManager::adapter($data['PdfFile']['adapter'])->delete($data['PdfFile']['path']);
```

Insted of doing all of this in the table object that has the files associated to it you can also simply extend the FileStorage table from the plugin and add your storage logic there and use that table for your association.

Why is it done like this?
-------------------------

Expand Down
59 changes: 59 additions & 0 deletions docs/Documentation/The-Image-Version-Shell.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,62 @@
The Image Version Shell
=======================

The shell comes with three pretty much self explaining commands: `generate`, `remove` and `regenerate`.

Generate
--------

**Arguments**

* **model (required)**: Value of the model property of the images to generate.
* **version (required)**: Image version to generate.

**Options**

* **storageTable**: The storage table for image processing you want to use.
* **limit**: Limits the amount of records to be processed in one batch.
* **keep-old-versions**: Use this switch if you do not want to overwrite existing versions.

Example:

```sh
bin\cake imageVersion generate Avatar t150
```

Remove
------

**Arguments**

* **model (required)**: Value of the model property of the images to generate.
* **version (required)**: Image version to generate.

**Options**

* **storageTable**: The storage table for image processing you want to use.
* **limit**: Limits the amount of records to be processed in one batch.

Example:

```sh
bin\cake imageVersion remove Avatar t150
```

Regenerate
----------

**Arguments**

* **model (required)**: Value of the model property of the images to generate.

**Options**

* **storageTable**: The storage table for image processing you want to use.
* **limit**: Limits the amount of records to be processed in one batch.
* **keep-old-versions**: Use this switch if you do not want to overwrite existing versions.

Example:

```sh
bin\cake imageVersion regenerate Avatar
```
2 changes: 1 addition & 1 deletion docs/Tutorials/Quick-Start.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class Products extends Table {
'className' => 'ProductImages',
'foreignKey' => 'foreign_key',
'conditions' => [
'Images.model' => 'ProductImage'
'ProductImages.model' => 'ProductImage'
]
]);
$this->hasMany('Documents', [
Expand Down
5 changes: 5 additions & 0 deletions src/Event/THIS-FOLDER-IS-DEPRECATED.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The event listeners have been *completly* overhauled and rewritten.

The content of this folder is deprecatd and is going to be removed within the new few month with the release of the 2.0 version of the plugin.

While the new listeners will feature a backward compatible listener it is strongly recommended to already switch and use the new listeners.
3 changes: 3 additions & 0 deletions src/Lib/THIS-FOLDER-IS-DEPRECATED.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The classes inside this folder have been moved to src/Storage/.

The classes here inside this folder are just proxy classes that encapsulate the new classes and will be removed within the next few month when the 2.0 version of the plugin is released.
19 changes: 19 additions & 0 deletions src/Model/Entity/ImageStorage.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php
namespace Burzum\FileStorage\Model\Entity;

use Cake\Core\Configure;

/**
* FileStorage Entity.
*
Expand All @@ -10,4 +12,21 @@
*/
class ImageStorage extends FileStorage {

/**
* Gets the version of an image.
*
* @param string
* @param array $options
* @return string
*/
public function imageVersion($version, $options = []) {
$options['version'] = $version;
$options['image'] = $this;
$options['hash'] = Configure::read('FileStorage.imageHashes.' . $this->_properties['model'] . '.' . $version);
if (empty($options['hash'])) {
throw new \InvalidArgumentException(sprintf('No valid version key (Identifier: `%s` Key: `%s`) passed!', $this->get('model'), $version));
}
$event = $this->dispatchEvent('ImageVersion.getVersions', $options);
return $event->result;
}
}
4 changes: 3 additions & 1 deletion src/Storage/Listener/AbstractListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,9 @@ public function createTmpFile($folder = null, $checkAndCreatePath = true) {
}

/**
* @param \Cake\Datasource\EntityInterface
* Get the path for a storage entity.
*
* @param \Cake\Event\Event $event
* @return string
*/
public function getPath(Event $event) {
Expand Down
4 changes: 4 additions & 0 deletions src/Storage/Listener/LocalListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ public function imagePath(Event $event) {
'pathType' => 'fullPath'
];

if ($event->subject() instanceof EntityInterface) {
$data['image'] = $event->subject();
}

$entity = $data['image'];
$version = $data['version'];
$options = $data['options'];
Expand Down
2 changes: 1 addition & 1 deletion src/Storage/PathBuilder/BasePathBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ public function fullPath(EntityInterface $entity, array $options = []) {
* @return string
*/
public function url(EntityInterface $entity, array $options = []) {
$url = $this->path($entity) . $this->filename($entity);
$url = $this->path($entity) . $this->filename($entity, $options);
return str_replace('\\', '/', $url);
}

Expand Down
15 changes: 7 additions & 8 deletions src/Storage/StorageManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
namespace Burzum\FileStorage\Storage;

/**
* StorageManager - manages and instantiates gaufrette storage engine instances
* StorageManager - manages and instantiates Gaufrette storage engine instances
*
* @author Florian Krämer
* @copyright 2012 - 2015 Florian Krämer
Expand All @@ -11,7 +11,7 @@
class StorageManager {

/**
* Adapter configs
* Adapter configurations
*
* @var array
*/
Expand All @@ -26,7 +26,7 @@ class StorageManager {
/**
* Return a singleton instance of the StorageManager.
*
* @return ClassRegistry instance
* @return \Burzum\FileStorage\Storage\StorageManager
*/
public static function &getInstance() {
static $instance = array();
Expand Down Expand Up @@ -61,8 +61,7 @@ public static function config($adapter, $options = array()) {
* Flush all or a single adapter from the config.
*
* @param string $name Config name, if none all adapters are flushed.
* @throws RuntimeException
* @return boolean True on success
* @return bool True on success.
*/
public static function flush($name = null) {
$_this = StorageManager::getInstance();
Expand All @@ -76,12 +75,12 @@ public static function flush($name = null) {
}

/**
* StorageAdapter
* Gets a configured instance of a storage adapter.
*
* @param mixed $adapterName string of adapter configuration or array of settings
* @param boolean $renewObject Creates a new instance of the given adapter in the configuration
* @throws RuntimeException
* @return Gaufrette object as configured by first argument
* @throws \RuntimeException
* @return \Gaufrette\Filesystem
*/
public static function adapter($adapterName, $renewObject = false) {
$_this = StorageManager::getInstance();
Expand Down
3 changes: 3 additions & 0 deletions src/Validation/UploadValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public function isUploadedFile($value) {
/**
* Validates that a set field / property is a valid upload array.
*
* @deprecated Use \Cake\Utility\Validation::uploadedFile() instead.
* @param mixed $value
* @return boolean
*/
Expand All @@ -84,6 +85,7 @@ public function isUploadArray($value) {
/**
* Validates the filesize.
*
* @deprecated Use \Cake\Utility\Validation::fileSize() instead.
* @param array $value.
* @param int $size.
* @param array $context.
Expand Down Expand Up @@ -119,6 +121,7 @@ public function extension($value, $extensions) {
/**
* Validates mime types.
*
* @deprecated Use \Cake\Utility\Validation::mimeType() instead.
* @param array $value.
* @param array $mimeTypes.
* @return boolean
Expand Down
22 changes: 12 additions & 10 deletions src/View/Helper/ImageHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ public function display($image, $version = null, $options = array()) {
return $this->fallbackImage($options, $image, $version);
}

protected function _getHash($version, $image) {
if (!empty($version)) {
$hash = Configure::read('FileStorage.imageHashes.' . $image['model'] . '.' . $version);
if (empty($hash)) {
throw new \InvalidArgumentException(sprintf('No valid version key (Identifier: `%s` Key: `%s`) passed!', @$image['model'], $version));
}
return $hash;
}
return null;
}

/**
* URL
*
Expand All @@ -54,17 +65,8 @@ public function imageUrl($image, $version = null, $options = []) {
return false;
}

if (!empty($version)) {
$hash = Configure::read('FileStorage.imageHashes.' . $image['model'] . '.' . $version);
if (empty($hash)) {
throw new \InvalidArgumentException(sprintf('No valid version key (Identifier: `%s` Key: `%s`) passed!', @$image['model'], $version));
}
} else {
$hash = null;
}

$eventOptions = [
'hash' => $hash,
'hash' => $this->_getHash($version, $image),
'image' => $image,
'version' => $version,
'options' => $options,
Expand Down
8 changes: 6 additions & 2 deletions tests/Fixture/ItemFixture.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
* @copyright 2012 - 2015 Florian Krämer
* @license MIT
*/
class ItemFixture extends CakeTestFixture {
namespace Burzum\FileStorage\Test\Fixture;

use Cake\TestSuite\Fixture\TestFixture;

class ItemFixture extends TestFixture {

/**
* Name
Expand All @@ -28,7 +32,7 @@ class ItemFixture extends CakeTestFixture {
* @var array
*/
public $fields = array(
'id' => array('type' => 'char', 'null' => false, 'length' => 36),
'id' => array('type' => 'uuid', 'null' => true, 'default' => NULL, 'length' => 36),
'name' => array('type' => 'string', 'null' => true, 'default' => NULL),
'_constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
Expand Down

0 comments on commit 63a43a5

Please sign in to comment.