Coder Social home page Coder Social logo

burzum / cakephp-file-storage Goto Github PK

View Code? Open in Web Editor NEW
197.0 29.0 84.0 1.84 MB

Abstract file storage and upload plugin for CakePHP. Write to local disk, FTP, S3, Dropbox and more through a single interface. It's not just yet another uploader but a complete storage solution.

License: MIT License

PHP 99.84% Ruby 0.16%
storage php cakephp storage-adapter s3 ftp dropbox storage-backend upload uploader

cakephp-file-storage's People

Contributors

adnan0703 avatar ajibarra avatar andrej-griniuk avatar bfncs avatar bionicpimp avatar burzum avatar choma avatar clawsonm avatar curtisgibby avatar d4rkmindz avatar dereuromark avatar guidohendriks avatar j15e avatar mcallisto avatar mhimmer avatar osazos avatar ravage84 avatar renan avatar rifer avatar robertpustulka avatar scrutinizer-auto-fixer avatar skie avatar steinkel avatar stonelasley avatar stripthis avatar thinkingmedia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cakephp-file-storage's Issues

Quick Start Guide instructions issue

https://github.com/burzum/cakephp-file-storage/blob/3.0/docs/Tutorials/Quick-Start.md

I get this error in my upload.ctp

Notice (8): Undefined variable: productImage [APP/Template/Products/upload.ctp, line 12]

in your controller you never set $productImages

class ProductsController extends AppController {
    // Upload an image
    public function upload($productId = null) {
        if (!$this->request->is('get')) {
            if ($this->Products->ProductImages->upload($productId, $this->request->data)) {
                $this->Flash->set(__('Upload successful!');
            }
        }
    }
}

What is the correct way? Can you guys share a project with this working so i can dissect it. Thank you

Including the helper 'FileStorage.Image' does not work

Error: FileStorage.ImageHelper could not be found.

Make sure your plugin FileStorage is in the C:\xampp\htdocs\myapp\plugins\ directory and was loaded.

Error: Create the class ImageHelper below in file: C:\xampp\htdocs\myapp\plugins\FileStorage\src\View\Helper\ImageHelper.php

Automatic adding of image versions

When using the image model with versioning, currently all versions are created after uploading. Since it is some standard problem that you get aware of other image sizes you want later, it would be very nice if the Image Model hat a function that checks all images on whether all configured image sizes are there and if not creates the missing ones.

I understand the considerations about why it is a bad idea to create the images in the desired size on the first request, even with caching turned on. I also like the way this is executed here with hashing and everything. But it would be nice to have an automatic way to add new image sizes without having to write your own script for this.

Creating versions of images not working

Cake PHP 3
PHP Version 5.5.12

When I try to create versions of my image i have an error (without versions it works !). Here is my stackrace :

Invalid log level "file_storage"
InvalidArgumentException

⟩ Cake\Log\Log::write
CORE\src\Log\LogTrait.php, line 36
⟩ Burzum\FileStorage\Event\AbstractStorageEventListener->log
ROOT\vendor\burzum\file-storage\src\Event\ImageProcessingListener.php, line 287
⟩ Burzum\FileStorage\Event\ImageProcessingListener->afterSave
CORE\src\Event\EventManager.php, line 389
⟩ Cake\Event\EventManager->_callListener
CORE\src\Event\EventManager.php, line 355
⟩ Cake\Event\EventManager->dispatch
ROOT\vendor\burzum\file-storage\src\Model\Table\ImageStorageTable.php, line 81
⟩ Burzum\FileStorage\Model\Table\ImageStorageTable->afterSave
CORE\src\Event\EventManager.php, line 389
⟩ Cake\Event\EventManager->_callListener
CORE\src\Event\EventManager.php, line 355
⟩ Cake\Event\EventManager->dispatch
CORE\src\Event\EventDispatcherTrait.php, line 78
⟩ Cake\ORM\Table->dispatchEvent
CORE\src\ORM\Table.php, line 1459
⟩ Cake\ORM\Table->_processSave
CORE\src\ORM\Table.php, line 1377
⟩ Cake\ORM\Table->Cake\ORM\{closure}
CORE\src\Database\Connection.php, line 557
⟩ Cake\Database\Connection->transactional
CORE\src\ORM\Table.php, line 1378
⟩ Cake\ORM\Table->save
APP/Model\Table\CompanyImagesTable.php, line 32
⟩ App\Model\Table\CompanyImagesTable->uploadImage
[internal function]
⟩ call_user_func_array
CORE\src\ORM\Association.php, line 896
⟩ Cake\ORM\Association->__call
APP/Controller\CompaniesEditionController.php, line 131
⟩ Cake\ORM\Association\HasMany->uploadImage
APP/Controller\CompaniesEditionController.php, line 131
⟩ App\Controller\CompaniesEditionController->upload
[internal function]
⟩ call_user_func_array
CORE\src\Controller\Controller.php, line 429
⟩ Cake\Controller\Controller->invokeAction
CORE\src\Routing\Dispatcher.php, line 114
⟩ Cake\Routing\Dispatcher->_invoke
CORE\src\Routing\Dispatcher.php, line 87
⟩ Cake\Routing\Dispatcher->dispatch
ROOT\webroot\index.php, line 37

My file_storage.php in APP/config/

<?php

use Burzum\FileStorage\Event\ImageProcessingListener;
use Burzum\FileStorage\Lib\FileStorageUtils;
use Cake\Core\Configure;
use Cake\Event\EventManager;

$listener = new ImageProcessingListener();
EventManager::instance()->on($listener);

Configure::write('FileStorage', [
    'imageSizes' => [
        'CompanyImage' => [
            'small' => [
                'crop' => [
                    'width' => 50, 'height' => 50
                ],
            ]
        ]
    ]
]);

FileStorageUtils::generateHashes();

My CompanyImagesTable.php

<?php
namespace App\Model\Table;

use Burzum\FileStorage\Model\Table\ImageStorageTable;

class CompanyImagesTable extends ImageStorageTable
{
    public function initialize(array $config)
    {
        $this->belongsTo('Companies');
    }

    public function uploadImage($companyID, $entity)
    {
        $entity = $this->patchEntity($entity, [
            'adapter' => 'Local',
            'model' => 'CompanyImage',
            'company_id' => $companyID
        ]);

        return $this->save($entity);
    }

}

CompaniesTable.php


<?php

namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

class CompaniesTable extends Table
{

    public function initialize(array $config)
    {
        $this->hasMany('CompanyImages');
        ... 
    }

}

My Controller action

public function upload()
    {
        if ($this->request->is(['post', 'put']))
        {
            $entity = $this->t_companies->CompanyImages->newEntity($this->request->data());

            if ($this->t_companies->CompanyImages->uploadImage($this->company->id, $entity))
            {
                echo 'ok';
            }
            else echo 'error';
        }
    }

Quick Start Tutorial not working

Hi. Following the quick start tutorial, I'm unable to setup the project despite having done all the installations. Please provide a simpler, working tutorial (perhaps based on the default blog post tutorial by CakePHP) as this plugin looks very promissing. Thanks and Regards, Zipate.

3.0-dev: Model field

I'm not sure if I understand this correctly, but image processing config is based on model field. Docs suggest that the model should be propagated with a table alias. But ImageStorageTable sets table() value in beforeSave by default. Shouldn't it set alias() value?

BTW I don't quite understand why beforeSave (and actaully all listeners) operates on $event->data['entity'] instead of $entity object...

Filesize validation does not work

Hello!

I just wanted to use the file size validation but it does not work. I used it that way:

$this->addBehavior('Burzum/FileStorage.UploadValidator', [
    'allowedExtensions' => [ 'pdf' ],
    'validateFilesize' => 31457280,
]);

The following error occurs:

Notice (8): Undefined property: Burzum\FileStorage\Validation\UploadValidator::$_filesize [ROOT/vendor/burzum/file-storage/src/Validation/UploadValidator.php, line 257]

If i correct the type (_filesize -> _fileSize) but then the next error occurs:

Fatal error: Call to undefined method Burzum\FileStorage\Validation\UploadValidator::_validateSize() in /path/to/file/vendor/burzum/file-storage/src/Validation/UploadValidator.php on line 93

Do I do something wrong or is this an error I should try to correct :-)

Thanks,
Bernhard

S3 directory specified double slash issue

I'm uploading files to S3 and specifying a sub directory. When the path gets built there is a slash prepended. When the path gets passed to Gaufrette and there is a directory set it will add another slash so my file gets uploaded to directory//files/etc/etc.jpg.

I don't think S3 requires the leading slash here so we can maybe remove it from the S3 listener?

StorageManager::config('S3Image', [
    'adapterOptions' => [
        $S3Client,
        'bucket',
        [
            'directory' => 'tools',
        ],
        true,
    ],
    'adapterClass' => '\Gaufrette\Adapter\AwsS3',
    'class' => '\Gaufrette\Filesystem',
]);

Questions about the docs

I've been reading the docs and found some things that are confusing to me.

First, in the quick start, there is a theoretical model setup. I don't get what uploadImage() and uploadDocument() functions are for. Wouldn't be easier, at least for teaching purposes, to set model field in an event (maybe in file_storage.php), something like:

\Cake\Event\EventManager::instance()->on('Model.beforeSave', function (\Cake\Event\Event $event, \Cake\ORM\Entity $entity, ArrayObject $options) {
    $event->subject()->patchEntity($entity, ['model' => $entity->source()]);
});

This way, you just need to save the entity to get the files uploaded. Or maybe I'm loosing something and the functions are there for another reason?

Second, I followed the configuration suggested for local filesystem, (I created the symlink in the exact same way). The uploads works ok, but the entity is saved with wrong path, since it doesn't include the uploads directory. Then the ImageHelper display() function won't work.

Windows Azure Connection

I have managed to set everything up and files can be upped locally along with entering records in the DB. But I just cannot seem to get Windows Azure storage to save the uploaded items? It's saving to the DB fine. (Removed credentials from connection string). Help would be much appreciated :)

$connectionString = "DefaultEndpointsProtocol=https;AccountName=;AccountKey=";
$blobRestProxy = new Gaufrette\Adapter\AzureBlobStorage\BlobProxyFactory($connectionString);
$blobRestProxy->create();

// Configure the Gaufrette adapter through the StorageManager
StorageManager::config('AzureBlobStorage', [
    'adapterOptions' => [
        $blobRestProxy,
        'gatewayfiles'
    ],
    'adapterClass' => '\Gaufrette\Adapter\AzureBlobStorage',
    'class' => '\Gaufrette\Filesystem'
]);

EDIT: Also, if I allow the container to be created that works fine. So it is connecting to the storage okay.

Amazon S3 metadata support?

Is it possible to set metadata (for example Content-Type and Cache-Control) when writing to Amazon S3?

It would be ok as a general config; even better, of course, if it could be set each time a file is written.

"First arg must be a non empty string!" exception when deleting on cascade

I'm having a "First arg must be a non empty string!" exception when trying to delete a post and its associated image on cascade.

I'm using cakephp v3.2.1, with cakephp-file-storage v1.1.4 and cakephp-imagine-plugin v2.1.1

As I understand the problem is here. It is trying to read $event->result['adapter'], but $event->result is equal to true (I'm not sure, but I think that value comes from here)

Here is my current configuration:

// config/file_storage.php
$listener = new BaseListener([
    'imageProcessing' => true, // Required if you want image processing!
    'pathBuilderOptions' => [
        'pathPrefix' => '/files',
        'preserveFilename' => true
    ]
]);
// Attach the BaseListener to the global EventManager
EventManager::instance()->on($listener);
Configure::write('FileStorage', [
    // Configure image versions on a per model base
        // Same as docs example
]);
// This is very important! The hashes are needed to calculate the image versions!
StorageUtils::generateHashes();
// Configure Local adapter instance through the StorageManager
StorageManager::config('Local', [
    'adapterOptions' => [ROOT . DS . 'file_storage', true],
    'adapterClass' => '\Gaufrette\Adapter\Local',
    'class' => '\Gaufrette\Filesystem'
]);
// Set model field
\Cake\Event\EventManager::instance()->on('Model.beforeSave', function (\Cake\Event\Event $event, \Cake\ORM\Entity $entity, ArrayObject $options) {
    $event->subject()->patchEntity($entity, ['model' => $entity->source()]);
});

Table classes:

class PostsTable extends Table
{
    public function initialize(array $config)
    {
        parent::initialize($config);
        $this->hasOne('MainImages', [
            'foreignKey' => 'foreign_key',
            'className' => 'PostImages',
            'conditions' => ['model' => 'MainImages'],
            'dependent' => true,
            'cascadeCallbacks' => true
        ]);
    }
}

and

use Burzum\FileStorage\Model\Table\ImageStorageTable;
class PostImagesTable extends ImageStorageTable
{
    // empty
}

The controllers and templates are baked, and I'm using the posts/delete action to delete posts (and images on cascade).

Here is the full error log message:

2016-02-21 03:16:43 Error: [Burzum\FileStorage\Storage\StorageException] First arg must be a non empty string!
Request URL: /posts/delete/32
Referer URL: http://testupload.v1/posts
Stack Trace:
#0 /home/choma/www/testupload_v1/vendor/burzum/file-storage/src/Storage/Listener/BaseListener.php(81): Burzum\FileStorage\Storage\Listener\AbstractListener->_deleteFile(Object(Cake\Event\Event))
#1 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventManager.php(391): Burzum\FileStorage\Storage\Listener\BaseListener->afterDelete(Object(Cake\Event\Event), Object(Cake\ORM\Entity), Object(Gaufrette\Filesystem), Object(App\Model\Table\PostImagesTable))
#2 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventManager.php(355): Cake\Event\EventManager->_callListener(Array, Object(Cake\Event\Event))
#3 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventDispatcherTrait.php(78): Cake\Event\EventManager->dispatch(Object(Cake\Event\Event))
#4 /home/choma/www/testupload_v1/vendor/burzum/file-storage/src/Model/Table/FileStorageTable.php(243): Cake\ORM\Table->dispatchEvent('ImageStorage.af...', Array, NULL)
#5 /home/choma/www/testupload_v1/vendor/burzum/file-storage/src/Model/Table/ImageStorageTable.php(129): Burzum\FileStorage\Model\Table\FileStorageTable->dispatchEvent('ImageStorage.af...', Array)
#6 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventManager.php(391): Burzum\FileStorage\Model\Table\ImageStorageTable->afterDelete(Object(Cake\Event\Event), Object(Cake\ORM\Entity), Object(ArrayObject), Object(App\Model\Table\PostImagesTable))
#7 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventManager.php(355): Cake\Event\EventManager->_callListener(Array, Object(Cake\Event\Event))
#8 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventDispatcherTrait.php(78): Cake\Event\EventManager->dispatch(Object(Cake\Event\Event))
#9 /home/choma/www/testupload_v1/vendor/burzum/file-storage/src/Model/Table/FileStorageTable.php(243): Cake\ORM\Table->dispatchEvent('Model.afterDele...', Array, NULL)
#10 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1725): Burzum\FileStorage\Model\Table\FileStorageTable->dispatchEvent('Model.afterDele...', Array)
#11 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1647): Cake\ORM\Table->_processDelete(Object(Cake\ORM\Entity), Object(ArrayObject))
#12 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Database/Connection.php(557): Cake\ORM\Table->Cake\ORM\{closure}(Object(Cake\Database\Connection))
#13 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1652): Cake\Database\Connection->transactional(Object(Closure))
#14 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Association/DependentDeleteTrait.php(48): Cake\ORM\Table->delete(Object(Cake\ORM\Entity), Array)
#15 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/AssociationCollection.php(270): Cake\ORM\Association\HasOne->cascadeDelete(Object(App\Model\Entity\Post), Array)
#16 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1709): Cake\ORM\AssociationCollection->cascadeDelete(Object(App\Model\Entity\Post), Array)
#17 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1647): Cake\ORM\Table->_processDelete(Object(App\Model\Entity\Post), Object(ArrayObject))
#18 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Database/Connection.php(557): Cake\ORM\Table->Cake\ORM\{closure}(Object(Cake\Database\Connection))
#19 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1652): Cake\Database\Connection->transactional(Object(Closure))
#20 /home/choma/www/testupload_v1/src/Controller/PostsController.php(102): Cake\ORM\Table->delete(Object(App\Model\Entity\Post))
#21 [internal function]: App\Controller\PostsController->delete('32')
#22 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Controller/Controller.php(430): call_user_func_array(Array, Array)
#23 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Routing/Dispatcher.php(114): Cake\Controller\Controller->invokeAction()
#24 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Routing/Dispatcher.php(87): Cake\Routing\Dispatcher->_invoke(Object(App\Controller\PostsController))
#25 /home/choma/www/testupload_v1/webroot/index.php(37): Cake\Routing\Dispatcher->dispatch(Object(Cake\Network\Request), Object(Cake\Network\Response))
#26 {main}

Question / Possible Issue with SSLv3

I got this email (truncated) from Amazon about our S3 connection using this FileStorage plugin.

The following bucket(s) are currently accepting requests from clients that specify SSLv3 to connect to Amazon S3 HTTPS endpoints. For your applications to continue running on Amazon S3, your end users need to access S3 from clients configured to use TLS. As of 12:00 AM PDT May 20, 2015, AWS will discontinue support of SSLv3 for securing connections to S3 buckets.

I believe (though I could be wrong) that this issue has to do with the end point specified around line 121 in Event/S3StorageListener.php, and how the url is https, instead of a TLS endpoint. Do you have any insight as to whether this is the issue, and/or how it might be fixed?

$url = 'https://' . $adapterConfig['adapterOptions'][1] . '.s3.amazonaws.com' . $combined;

Request

I didn't find any documentation or Quickstart that talks about FTP/SFTP.

Adding composer.json

It would be great if this plugin (and its dependencies) could be installed via composer.

Mime-Type Content Length?

I've been debugging an issue, and I don't think it'll cause issues for me, but I noticed that the mime-type column in the DB is set to 32 chars long. Some mime-types, most noticeably MS Office files, are longer than that. Are there plans to store the whole mime-type string, or have you found it doesn't matter?

Inconsistencies in Quick Start

In Quick Start, after setting up the Products table to contain both Images and Documents, you go on to implement a ProductImages table. It includes a method to upload documents, something that is not expected to be done by this table.

In the controller example below, $this->Products->ProductImages->uploadImage() is called, but uploadDocument() is not further used or mentioned.

Call to undefined method Burzum\\FileStorage\\Event\\ImageProcessingListener::log()

Hi!

When I invoke the saveEntitiy method in the following class:

class ProductsImagesTable extends ImageStorageTable
{

  public function uploadImage($productId, $entity)
{
    $entity = $this->patchEntity($entity, [
        'adapter' => 'Local',
        'model' => 'ProductImage',
        'foreign_key' => $productId
    ]);
    return $this->save($entity); <---- the error happens here
}

}

I receive the error in the subject of this message. I'm a newbie to cake php because of that I don't know if maybe my cakephp framework is erroneously configured.

I noticed that your plugin invokes the log function with $this->log, and that does not work for me (I use always Log::write('debug', 'something');

May you help me?

Thanks in advance

UploadValidatorBehavior error messages

File deletion throws error (3.0)

I managed to get file uploading working in 3.0. Really nice plugin, but it seriously needs some better documentation.

Anyway, it seems much of the code has not been updated for Cake 3's object oriented entity model. Uploading works fine, deletion, on the other hand, not so much. For one, FileStorageTable's beforeDelete method tries calling the parent's (Cake\ORM\Table) beforeDelete method, which does not exist.

I extended the original object, and fixed this in my own app. However, later on, the ImageProcessingListener refers to the file entity's properties as an array, instead of an object, causing it to return null, so the adapter throws an error, and this goes on for a lot of the code.
The code looks like an unholy mixture of Cake 2 and 3 ORM handling. Is this not ready for use, or am I doing something wrong?

I really need something like this for Cake 3, keep up the good work.

ImageHelper::display

How do you show the original image? Image->display($image, null);throws exception Image processing configuration in "FileStorage.imageSizes" is missing!

Error in log Method for ImageProcessingListener line 287

Fatal error: Call to undefined method Burzum\FileStorage\Event\ImageProcessingListener::log() in /Applications/MAMP/htdocs/store/vendor/burzum/file-storage/src/Event/ImageProcessingListener.php on line 287

Uploading files work fine for me until I tried to change the StorageManager location

//I added this to the bottom of my file_storage.php which is included in my bootstrape.php
StorageManager::config('Local', [
'adapterOptions' => [ROOT . DS . 'file_storage' . DS], // Your base path here
'adapterClass' => '\Gaufrette\Adapter\Local',
'class' => '\Gaufrette\Filesystem'
]);

Also in your documentation for the view helper
echo $this->Image->display($product['Image'], 'small');

What is $product['image'] is it the filename? I looked in the code and it says URL. So I am passing the entire filepath that so shouldn't it be $file_storage->path . $file_storage->filename or $file_storage->id?

And here is my composer.json required and require-dev

"require": {
"php": ">=5.4.16",
"cakephp/cakephp": "~3.0",
"mobiledetect/mobiledetectlib": "2.",
"cakephp/migrations": "~1.0",
"cakephp/plugin-installer": "
",
"friendsofcake/cakephp-csvview": "~2.0",
"burzum/file-storage": "3.0.@dev",
"burzum/cakephp-imagine-plugin": "3.0.
@dev",
"cakephp/migrations": "~1.0"
},
"require-dev": {
"psy/psysh": "@stable",
"cakephp/debug_kit": "~3.0",
"cakephp/bake": "~1.0"
},

did i miss anything?

File not saving to local file system

I am trying to implement the plugin for the first time. I'm also pretty new to CakePHP in general. I was able to get a file saved to the local file system by basing my model on the the ImageStorageTable. But that was cheating: I really need plain txt files, and had to literally override the plugin's UploadValidatorBehavior in order to allow a .txt extension -- not good.

I changed to using the FileStorageTable and the configureUploadValidation to get my .txt extension. That's better, and the record still writes to my file_storage table of the database. But....I can't find anything getting written to the file system itself. The path in the file-storage table is null, instead of the built path that was used when an image.

I haven't intentionally changed anything other than from Image... to File... and the Behavior configuration. Any suggestions as to what step I've missed? Code snips are below. Thanks!


My model:

configureUploadValidation (array( 'localFile' => false, 'validate' => true, 'allowedExtensions' => array( 'jpg', 'jpeg', 'png', 'gif', 'txt' ) )); } public function uploadDocument($headerId, $entity) { $entity = $this->patchEntity($entity, [ 'adapter' => 'Local', 'model' => 'ProjectDocuments', 'foreign_key' => $headerId ]); return $this->save($entity); } ``` } --- My controller: ``` // Upload an attachment public function upload($headerId = null) { $entity = $this->ProjectHeaders->ProjectDocuments->newEntity(); if ($this->request->is(['post', 'put'])) { $entity = $this->ProjectHeaders->ProjectDocuments->patchEntity( $entity, $this->request->data ); if ($this->ProjectHeaders->ProjectDocuments->uploadDocument($headerId, $entity)) { $this->Flash->set(__('Upload successful!')); } } $this->set('projectDocument', $entity); } ``` --- My config for file_storage StorageManager (worked as Image, but even deleting this to go back to the default TMP doesn't help for File): StorageManager::config('Local', [ 'adapterOptions' => [ROOT . DS . 'Data', true], 'adapterClass' => '\Gaufrette\Adapter\Local', 'class' => '\Gaufrette\Filesystem' ]);

Refactor the way to get the path and version paths from an entity

The way I implemented it now doesn't require a helper, instead you can now get (any) path directly from the entity. I'm just still not happy with the image versions but I think this should be handled in a similar way. Maybe I'm going to add FileStorageEntity::versionPath('type', $options); or something similar, I guess I'll have to try a few things to figure out a nice way to use that functionality.

I think the version path and filename should be handled by the path builders as well but then they need to become aware of the image processing.

Evaluate if it is possible to come up with an interface for uploaders

I just had the idea if it won't be somehow possible to provide a unique interface for different uploader tools like plupload or uploadify and jquery upload.

Need to evaluate if this can be done as a component (?) loading different upload processors as adapters to return a unified array of data that can be passed to the file storage model.

No way to change jpg/png quality

I'm afraid there's no way to configure custom quality for image versions. At least not in 3.0-event-overhaul branch. Currently the only save option passed to imagine save() method is image format (in pretty simple way though because it's resolved based on file extension and not mime type).

I was thinking that there could be another config key - for example FileStorage.saveOptions, where default compression for jpg, png and other imagine options could be configured.

I could add a commit to #74 with proposed changes.

Support Gaufrette AND Flysystem

Right now FileStorage is only supporting Gaufrette because it was there before Flysystem.

It seems that Flysystem was created because some people were unhappy with the Gaufrette team and it's slow response times to issues.

So if you want Gaufrette and Flysystem support please vote this up by answering with +1 or 👍 here.

fullFilePath() & fileUrl() is implemented wrong in the event-overhaul branch

@robertpustulka this won't work.

    public function fullFilePath(EntityInterface $entity, array $options = []) {
        $pathBuilder = $this->createPathBuilder($entity['adapter']);
        return $pathBuilder->fullPath($entity, $options);
    }

    public function fileUrl(EntityInterface $entity, array $options = []) {
        $pathBuilder = $this->createPathBuilder($entity['adapter']);
        return $pathBuilder->url($entity, $options);
    }

The path builder won't match the adapter name! For example you have configured Local1 and Local2 or S3BucketFiles and `S3BucketImages - I guess you get the idea - there are no such path builders (S3BucketFilesPathBuilder...) available.

I would really prefer to trigger an event here so that all logic that is involved for an adapter is handled inside the related listener.

Here is my proposed change:

    public function fullFilePath(EntityInterface $entity, array $options = []) {
        $event = $this->dispatchEvent('FileStorage.fullFilePath', [
            'record' => $entity
        ]);
        return $event->result;
    }

    public function fileUrl(EntityInterface $entity, array $options = []) {
        $event = $this->dispatchEvent('FileStorage.fileUrl', [
            'record' => $entity
        ]);
        return $event->result;
    }

Error: Class '\Gaufrette\FileSystem' not found

on windows i have not issue but when i deploy to linux machine ubuntu 14.04 i get that error

Error: Class '\Gaufrette\FileSystem' not found
File /home/ubuntu/imageapp/vendor/burzum/file-storage/src/Lib/StorageManager.php
Line: 113

Setting `FileStorage.schema.useIntegers` does not seem to affect schema creation

After setting the above configuration, running:

`Console/cake schema create -p FileStorage`

still generates table still with id and foreign_key fields with char(36) type.

I had a quick look, and it seems this might not be easily fixable here as the SchemaShell uses CakeSchema [1] to read the schema file.

And it seems that we have no way of modifying the returned $Schema object from the schema file.

If this is not possible anymore due to changes upstream, maybe we'll just remove FileStorage.schema.useIntegers and document it to avoid confusion.

[1] https://github.com/cakephp/cakephp/blob/master/lib/Cake/Console/Command/SchemaShell.php#L252

Move storage table methods to a dedicated behaviors

I was thinking that maybe file/image callbacks and methods would be better placed in behaviors. It would provide more flexibility if apps could just add behaviors to custom tables. It's not the best option to extend plugin tables...

I could try to do this if the idea makes sense for you.

Basic usage question

I'm not very familiar with the CakePHP event system, so I'm trying to start with the first usage pattern, accessing the StorageManager directly...

Think about my app as if it is Craigslist. There is a Listing model, which hasMany Photo(s). In my Listing model I've added the relationship:

public $hasMany = array(
    'Photo' => array(
        'className' => 'FileStorage.FileStorage',
        'foreignKey' => 'foreign_key'
    )
);

In my view, I write the form manually because I'm using dropzone.js to post the files with AJAX. When I $this->log($this->data) it looks like this, which I think is correct:

    [Photo] => Array
        (
            [listing_id] => 8
            [file] => Array
                (
                    [0] => Array
                        (
                            [name] => test-photo.jpg
                            [type] => image/jpeg
                            [tmp_name] => /Applications/MAMP/tmp/php/phpHBX6zx
                            [error] => 0
                            [size] => 257838
                        )

                )

        )

In my ListingsController I have an action called upload_photo which looks like this (validation, etc omitted for brevity):

    ...
    StorageManager::config('Local', array(
        'adapterOptions' => array(TMP, true),
        'adapterClass' => '\Gaufrette\Adapter\Local',
        'class' => '\Gaufrette\Filesystem')
    );

    foreach ($this->data['Photo']['file'] as $index=>$uploadedFile) {
        $key = 'files'.DS.'test-name-'.$index.'-'.time();
        if (StorageManager::adapter('Local')->write($key, file_get_contents($uploadedFile['tmp_name']))) {
            $uploadedFile['foreign_key'] = $listing_id;
            $uploadedFile['model'] = 'Listing';
            $uploadedFile['path'] = $key;
            $uploadedFile['adapter'] = 'Local';
        }

    }

I copied that code carefully from the "How to use" documentation, but it isn't working as expected. When I test it, the files are saved to the proper location, but new records are not added to the database. What am I missing? Is the StorageManager supposed to handle that automatically? It looks like I need to do something manually like: $this->Listing->Photo->save( $uploadedFile ); but I'm not sure.

Which branch?

Which branch I should use for cake3 1.0, 1.1, or 3.0?

Error on save in commit 31a2344dcb01a905a553e8701534a14421cffacd

Hey!

Just testing the new commit 31a2344. Seems to me there is a bug in the Event dispatching process (or my code?) I simply cannot find it.

My custom Table

class DocumentsTable extends FileStorageTable
{
    public function initialize(array $config) {
        parent::initialize($config);
        $this->addBehavior('Tree');
        $this->addBehavior('Burzum/FileStorage.UploadValidator', [
            'allowedExtensions' => [ 'pdf' ],
            'validateUploadArray' => true,
            'localFile' => true,
            'validateUploadErrors' => true
        ]);
    }
}

The listener in bootstrap.php:

$listener = new LocalListener();
EventManager::instance()->on($listener);

My save call:

(...)
$this->News->Documents->save( $document );

This error happens:

Warning (4096): Argument 2 passed to Burzum\FileStorage\Storage\Listener\LocalListener::afterSave() must implement interface Cake\Datasource\EntityInterface, boolean given [ROOT/vendor/burzum/file-storage/src/Storage/Listener/LocalListener.php, line 108]

Fatal error: Call to a member function isNew() on boolean in /Users/bernhard/Sites/oegmm-neu/vendor/burzum/file-storage/src/Storage/Listener/LocalListener.php on line 109

Somewhere on the way the $entity gets to true. Checked in LocalListener.php via:

(...)
    public function afterSave(Event $event, EntityInterface $entity) {
        debug($entity);
        if ($this->_checkEvent($event) && $entity->isNew()) {
(...)

See also comment here
Bernhard

How to delete created images?

In the instructions you write that one should use

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

to delete the file created before.

I am creating multiple sizes of my images. So I have one folder with a couple files. When I try to delete this folder as shown above ('path' points to the folder) I get a "Directory not empty" warning and nothing is deleted. Stepping through the code this is not surprising as the images itself are never removed.

How do I remove all images including the folder using your code? I could not find a suitable method or the parameters to clean up properly.

Thank you for any hints!

Typo error in getting started?

Hi,

I'm trying to include your plugin in my project, because of that I added all the composer dependencies and followed your getting started tutorial. I'm using the version 3.0 of the plugin, for cakephp 3.

The problem is that after following your getting start tutorial, I receive the following error when trying to create the new entity. I Invoke

$entity = $this->Products->ProductImages->newEntity();

the error message is:

Table \u0022App\\Model\\Table\\ProductsTable\u0022 is not associated with \u0022ProductsImages\u0022"

I'm not sure, but you declare the has many relationship for the products table, is there an typo error in the has many?

class Products extends Table {
public function initialize() {
    parent::initialize();
    $this->hasMany('Images', [
        'className' => 'ProductImages',
        'foreignKey' => 'foreign_key',
        'conditions' => [
            'Images.model' => 'ProductImage'
        ]
    ]);

Because if If use:

 class Products extends Table {
public function initialize() {
    parent::initialize();
    $this->hasMany('ProductImages', [   <----- Modified line
        'className' => 'ProductImages',
        'foreignKey' => 'foreign_key',
        'conditions' => [
            'Images.model' => 'ProductImage'
        ]
    ]);

It works,

thank you in advance!

Installation error

When I copy/paste the following (found here: https://github.com/burzum/cakephp-file-storage/blob/master/Docs/Documentation/Installation.md#cakephp-bootstrap) into my bootstrap.php file, I get the following error:

bootstrap.php

App::uses('CakeEventManager', 'Event');
App::uses('FileStorageUtils', 'FileStorage.Lib/Utility');
App::uses('StorageManager', 'FileStorage.Lib');
App::uses('LocalImageProcessingListener', 'FileStorage.Event');
App::uses('LocalFileStorageListener', 'FileStorage.Event');
App::uses('FileStorageListener', 'FileStorage.Event');

// Only required if you're *NOT* using composer or another autoloader!
spl_autoload_register(__NAMESPACE__ .'\FileStorageUtils::gaufretteLoader');

$listener = new LocalFileStorageListener();
CakeEventManager::instance()->attach($listener);

// For automated image processing you'll have to attach this listener as well
$listener = new ImageProcessingListener();
CakeEventManager::instance()->attach($listener);

ERROR:

2014-12-09 13:01:26 Error: [LogicException] Function '\FileStorageUtils::gaufretteLoader' not found (class '\FileStorageUtils' not found)
Stack Trace:
#0 /Applications/MAMP/htdocs/letreehouse/app/Config/bootstrap.php(0): spl_autoload_register()
#1 /Applications/MAMP/htdocs/letreehouse/lib/Cake/Core/Configure.php(92): include('/Applications/M...')
#2 /Applications/MAMP/htdocs/letreehouse/lib/Cake/bootstrap.php(175): Configure::bootstrap(true)
#3 /Applications/MAMP/htdocs/letreehouse/app/webroot/index.php(90): include('/Applications/M...')
#4 {main}

What am I doing wrong?

I tried adding: CakePlugin::load('FileStorage') but it only produced different errors.

File deletion error

Hey!

I think I found a bug when deleting files. I created my own DocumentsTable object and extended FileStorage. When I delete an Entry from my NewsTable, an error is thrown, that the directory to be deleted is not empty.

NewsTable:

$this->hasOne('Documents', [
    'foreignKey' => 'foreign_key',
    'dependent' => true,
    'cascadeCallbacks' => true,
]);
Warning (2): rmdir(/path/to/project/file_storage/files/86/39/60/4927dbd92ef7435588da876d44430b5f) [function.rmdir]: Directory not empty [ROOT/vendor/knplabs/gaufrette/src/Gaufrette/Adapter/Local.php, line 132]
CakePHP Exception: Could not remove the "files/86/39/60/4927dbd92ef7435588da876d44430b5f/" key.

There is still the file i uploaded in this folder. Seems like the Gauffrette library doesn't remove recursively:
https://github.com/KnpLabs/Gaufrette/blob/master/src/Gaufrette/Adapter/Local.php#L129

Great plugin btw!

Thanks,
Bernhard

How to distinguish between the different versions of the image?

Hi,

In my config I defined three versions for my images (high, medium, small). A client App invokes the api and should receive an array with entities, each entity containing all the associates images for this entity.

It is easy to load the associated images:

     $data = $this->Reviews->find()
        ->contain(['ReviewImages'])
        ->select()
        ->where(['user_id = ' => $user_id])
        ->where(['created >= ' => $date])->all();

And yes, there are all the images for each review attached in an array. The question is, how to distinguish between the small, medium and high versions. Ok I suppose I can group the images by filename and sort them by filesize but that is not very practical.

I'm sure I'm missing a more easy way to return in my controller, the url's for the three diferent versions for each entity. Actually I don't need the whole Image entity, only three the three urls...

Is it possible to the the Image Helper in a controller, and if yes, how can I retrive the Url of a image version for a given entity Id?

Thanks in advance.

Problem when updating related data

I'm not sure if it is a bug, or I'm using the plugin in the wrong way.
I have a PostsTable with:

$this->hasMany('PostImages', [   // PostImages extends ImageStorageTable
    'foreignKey' => 'foreign_key',
    'conditions' => ['model' => 'PostImages'],
    'dependent' => true,
    'cascadeCallbacks' => true
]);

$this->hasOne('PostDocuments', [  // PostDocuments extends FileStorageTable
    'foreignKey' => 'foreign_key',
    'conditions' => ['model' => 'PostDocuments'],
    'dependent' => true,
    'cascadeCallbacks' => true
]);

a baked PostsController, so the edit action is as follows:

public function edit($id = null)
    {
        $post = $this->Posts->get($id, [
            'contain' => [
                'PostImages',
                'PostDocuments'
            ]
        ]);
        if ($this->request->is(['patch', 'post', 'put'])) {
            $post = $this->Posts->patchEntity($post, $this->request->data);
            if ($this->Posts->save($post)) {
                $this->Flash->success(__('The post has been saved.'));
                return $this->redirect(['action' => 'index']);
            } else {
                $this->Flash->error(__('The post could not be saved. Please, try again.'));
            }
        }
        $this->set(compact('post'));
        $this->set('_serialize', ['post']);
    }

and the form is:

        echo $this->Form->input('post_images.0.file', ['type' => 'file']);
        echo $this->Form->input('post_images.0.old_file_id', ['type' => 'hidden', 'value' => $post->post_images[0]->id]);
        echo $this->Form->input('post_images.1.file', ['type' => 'file']);
        echo $this->Form->input('post_images.1.old_file_id', ['type' => 'hidden', 'value' => $post->post_images[1]->id]);

        echo $this->Form->input('post_document.file', ['type' => 'file']);
        echo $this->Form->input('post_document.old_file_id', ['type' => 'hidden', 'value' => $post->post_document->id]);

The problem is that patchEntity() is "mixing" the old and new post_document data (hasOne association), so it results in the plugin trying to delete the new file (which isn't uploaded yet).
The post_images (hasMany association) on the other hand will work, since patchEntity() will create new entities with the data. But it will fail if I add id fields like: $this->Form->input('post_images.0.id');. This is because now patchEntity() correctly identifies the entities and mixes the data.

So, the question is: is there a way to use old_file_id in the same entity which is being updated? I mean delete the old file first, and then upload and save new one.

Rotate on ImageProcessor is called with wrong parameters

In the ImageProcessingListener the method rotate is called on the ImageProcessor from the burzum/cake-imagine-plugin. In this call the image is passed while it shouldn't.

Method call: https://github.com/burzum/cakephp-file-storage/blob/1.1/src/Event/ImageProcessingListener.php#L100

Method definition: https://github.com/burzum/cakephp-imagine-plugin/blob/c88eaa490dcc60df0914536dbb5da32f78c45b1f/src/Lib/ImageProcessor.php#L364

From what I can tell, we'd just have to delete the $image parameter. Will create a PR for it.

Deleting images on Local

When deleting an existing image using the old_file_id property, delete() is called on the storage adapter with the path as key. Because the path is the directory the files are stored in, rmdir() is called in the adapter. This won't work since rmdir() can only delete empty directories.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.