bupy7 / yii2-widget-cropbox

This widget allows crop image before upload to server and send informations about crop in JSON format.
BSD 3-Clause "New" or "Revised" License
91 stars 33 forks source link

Undefined index: dHeight #44

Closed douglas-srs closed 7 years ago

douglas-srs commented 7 years ago

Hello,

When trying to save an image I'm getting this error. Note: I'm using yii2-user and adding the image to the profile form.

My model:

namespace app\models;

use dektrium\user\models\Profile as BaseProfile;
use yii\helpers\FileHelper;
use yii\imagine\Image;
use yii\helpers\Json;
use Imagine\Image\Box;
use Imagine\Image\Point;

class Profile extends BaseProfile {

    public $picture;
    public $crop_info;

    public function rules() {
        $rules = parent::rules();
        $rules[] = [
                    'picture', 
                    'image', 
                    'extensions' => ['jpg', 'jpeg', 'png', 'gif'],
                    'mimeTypes' => ['image/jpeg', 'image/pjpeg', 'image/png', 'image/gif'],
                ];
        $rules[] = ['crop_info', 'safe'];
        return $rules;
    }

    public function afterSave($insert, $changedAttributes)
    {
        $picture = Image::getImagine()->open($this->picture->tempName);

        $cropInfo = Json::decode($this->crop_info)[0];

        $cropInfo['dWidth'] = (int)$cropInfo['dWidth']; //new width image
        $cropInfo['dHeight'] = (int)$cropInfo['dHeight']; //new height image
        $cropInfo['x'] = $cropInfo['x']; //begin position of frame crop by X
        $cropInfo['y'] = $cropInfo['y']; //begin position of frame crop by Y

        //delete old images
        $oldImages = FileHelper::findFiles(Yii::getAlias('@web/users'), [
            'only' => [
                $this->id . '.*',
                'thumb_' . $this->id . '.*',
            ], 
        ]);
        for ($i = 0; $i != count($oldImages); $i++) {
            @unlink($oldImages[$i]);
        }

        //saving thumbnail
        $newSizeThumb = new Box($cropInfo['dWidth'], $cropInfo['dHeight']);
        $cropSizeThumb = new Box(200, 200); //frame size of crop
        $cropPointThumb = new Point($cropInfo['x'], $cropInfo['y']);
        $pathThumbImage = Yii::getAlias('@web/users') 
            . '/thumb_' 
            . $this->id 
            . '.' 
            . $this->picture->getExtension();  

        $picture->resize($newSizeThumb)
            ->crop($cropPointThumb, $cropSizeThumb)
            ->save($pathThumbImage, ['quality' => 100]);

        //saving original
        $this->picture->saveAs(
            Yii::getAlias('@web/users') 
            . '/' 
            . $this->id 
            . '.' 
            . $this->picture->getExtension()
        );
        parent::afterSave($insert, $changedAttributes);
    }

}

My View:

<?php
                    echo $form->field($model, 'picture')->widget(CropboxWidget::className(), [
                        'croppedDataAttribute' => 'crop_info',
                        'pluginOptions' => [
                            'variants' => [
                                ['width' => 160,
                                'height' => 160,
                                'minWidth' => 160,
                                'minHeight' => 160,
                                'maxWidth' => 500,
                                'maxHeight' => 500,],
                            ],
                            'messages' => [
                                ['Ajuste a imagem.'],
                            ]
                        ],
                    ]);
                ?>

My Controller:


<?php

namespace app\controllers;

use dektrium\user\controllers\SettingsController as BaseSettingsController;

class SettingsController extends BaseSettingsController
{
    public function actionProfile()
    {
        $model = $this->finder->findProfileById(\Yii::$app->user->identity->getId());
        if ($model == null) {
            $model = \Yii::createObject(Profile::className());
            $model->link('user', \Yii::$app->user->identity);
        }
        $event = $this->getProfileEvent($model);
        $this->performAjaxValidation($model);
        $this->trigger(self::EVENT_BEFORE_PROFILE_UPDATE, $event);
        if ($model->load(\Yii::$app->request->post())) {
            //die(print_r(\Yii::$app->request, true));

            $model->picture = \yii\web\UploadedFile::getInstance($model, 'picture');

            if ($model->save()){
                \Yii::$app->getSession()->setFlash('success', \Yii::t('user', 'Your profile has been updated'));
                $this->trigger(self::EVENT_AFTER_PROFILE_UPDATE, $event);
                return $this->refresh();
            }

        }
        return $this->render('profile', [
            'model' => $model,
        ]);
    }
}```
bupy7 commented 7 years ago

Hey! Which do you use version of extension?

douglas-srs commented 7 years ago

Latest one, I guess it's 5.1.1, installed today using composer.

bupy7 commented 7 years ago

Hm... Could you give me dump from $crop_info model property? And reload page and look at console errors. Property message from pluginOptions must have only array string values, no array array string values as you have.

douglas-srs commented 7 years ago

var_dump of $crop_info string(0) ""

Now that you talked about console errors I found out something, after I press the "Crop" button this error shows:

cropbox.js:78 Uncaught TypeError: Cannot read property 'data' of undefined
    at HTMLDivElement.<anonymous> (cropbox.js:78)
    at HTMLDivElement.dispatch (jquery-1.11.2.min.js:3)
    at HTMLDivElement.r.handle (jquery-1.11.2.min.js:3)
    at Cropbox._customTrigger (cropbox.js:453)
    at Cropbox.crop (cropbox.js:93)
    at e.fn.init.$.fn.cropbox (cropbox.js:18)
    at HTMLButtonElement.<anonymous> (cropbox.js:73)
    at HTMLButtonElement.dispatch (jquery-1.11.2.min.js:3)
    at HTMLButtonElement.r.handle (jquery-1.11.2.min.js:3)
bupy7 commented 7 years ago

You ought to fix messages list:

'messages' => [
    'Ajuste a imagem.',
]

After try again.

douglas-srs commented 7 years ago

Fixed the messages list and the problem persists. I set console.log(event) in cb:cropped event and it displays the event with an undefined data attribute. I have no idea what's wrong.

douglas-srs commented 7 years ago

I did some tests with cropbox.js and changed the cb:cropped event to this:

$th.on('cb:cropped', function(event) {
    var data = $th.cropbox('getData')[0];
    var $img = $('<img />', {
        src: data.image,
        class: 'img-thumbnail'
    });
    $(s.croppedContainer).append($img);
    $(s.croppedDataInput).val(JSON.stringify($th.cropbox('getData')));
});

This makes it works again but I'm sure this is not the proper way and it will probably break If I add more variants or update the plugin.

douglas-srs commented 7 years ago

For some reason this._customTrigger(EVENT_CB_CROPPED, {data: data}); is not passing the data to the event.

douglas-srs commented 7 years ago

I found out something weird:

$th.on('cb:cropped', function(event) {
    console.log(event.detail.data.image);// this prints undefined
    console.log(event.originalEvent.detail.data.image);// this prints the image data
    var $img = $('<img />', {
        src: event.originalEvent.detail.data.image,
        class: 'img-thumbnail'
    });
    $(s.croppedContainer).append($img);
    $(s.croppedDataInput).val(JSON.stringify($th.cropbox('getData')));
});

This way it works, looks like some kind of jQuery issue, I found this: https://github.com/jquery/jquery/issues/1867

Maybe you could check if event.detail is undefined and set use event.originalEvent instead.

bupy7 commented 7 years ago

I made tests with your cropbox configuration. I have all work. I don't know why you have a trouble. Update your jQuery library to 2.2.4 minimum. You have very oldest version of jQuery.

douglas-srs commented 7 years ago

Man... that was it, I'm so sorry for all the trouble, turned out another plugin I installed was using an old version of jQuery, I replaced it with newer jQuery and now it works perfectly, thank you for support and awesome plugin!

bupy7 commented 7 years ago

Don't worry. Be happy. =)