Skip to content

Commit

Permalink
Merge pull request #45 from ctessier/1.1
Browse files Browse the repository at this point in the history
Release 1.1.0
  • Loading branch information
ctessier authored Jun 7, 2020
2 parents 7deddcf + af0904b commit f71abde
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 15 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Release Notes

## [v1.1.0](https://github.com/ctessier/nova-advanced-image-field/compare/v1.0.2...v1.1.0)

> Released 2020/06/07
### Added

- Possibility to choose between `gd` or `imagick` image processing library ([#43](https://github.com/ctessier/nova-advanced-image-field/pull/43)).
- License file ([#37](https://github.com/ctessier/nova-advanced-image-field/pull/37)). Thanks [james-staffs](https://github.com/james-staffs)!

### Internal

- Upgrade package dependencies ([#40](https://github.com/ctessier/nova-advanced-image-field/pull/40)).

## [v1.0.2](https://github.com/ctessier/nova-advanced-image-field/compare/v1.0.1...v1.0.2)

> Released 2020/03/15
Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@
[![StyleCI](https://github.styleci.io/repos/156091175/shield?branch=1.0)](https://github.styleci.io/repos/156091175)
[![Latest Version on Packagist](https://img.shields.io/packagist/v/ctessier/nova-advanced-image-field.svg?style=flat-square)](https://packagist.org/packages/ctessier/nova-advanced-image-field)
[![Total Downloads](https://img.shields.io/packagist/dt/ctessier/nova-advanced-image-field.svg?style=flat-square)](https://packagist.org/packages/ctessier/nova-advanced-image-field)
[![License](https://img.shields.io/github/license/ctessier/nova-advanced-image-field?color=%23B2878B&style=flat-square)](https://packagist.org/packages/ctessier/nova-advanced-image-field)

This package provides an advanced image field for Nova resources allowing you to upload, crop and resize any image.

It uses [Cropper.js](https://fengyuanchen.github.io/cropperjs) with [vue-cropperjs](https://github.com/Agontuk/vue-cropperjs) in the frontend and GD and [Intervention Image](http://image.intervention.io) in the backend.
It uses [Cropper.js](https://fengyuanchen.github.io/cropperjs) with [vue-cropperjs](https://github.com/Agontuk/vue-cropperjs) in the frontend and [Intervention Image](http://image.intervention.io) in the backend.

![screenshot of the advanced image field](https://github.com/ctessier/nova-advanced-image-field/blob/1.0/screenshot.png?raw=true)

## Requirements

To work correctly, this package requires the following components:
- Laravel & Nova
- Fileinfo Extension
- GD Library (>=2.0)

And **one of** the following libraries:
- GD Library >=2.0 (used by default)
- Imagick PHP extension >=6.5.7

See [Intervention requirements](http://image.intervention.io/getting_started/installation) for more details.

## Installation

Expand All @@ -24,6 +31,9 @@ Install the package into a Laravel application with Nova using Composer:
composer require ctessier/nova-advanced-image-field
```

If you want to use Imagick as the default image processing library, follow the [Intervention documentation for Laravel](http://image.intervention.io/getting_started/installation#laravel).
This will provide you with a new configuration file where you can specify the driver you want.

## Usage

`AdvancedImage` extends from `File` so you can use any methods that `File` implements. See the documentation [here](https://nova.laravel.com/docs/2.0/resources/fields.html#file-field).
Expand Down Expand Up @@ -63,6 +73,9 @@ class Post extends Resource
// Show a cropbox and resize the image
AdvancedImage::make('photo')->croppable()->resize(400, 300),

// Override the image processing driver for this field only
AdvancedImage::make('photo')->driver('imagick')->croppable(),

// Store to AWS S3
AdvancedImage::make('photo')->disk('s3'),

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"license": "MIT",
"require": {
"php": ">=7.1.0",
"intervention/image": "^2.4"
"intervention/image": "^2.5"
},
"autoload": {
"psr-4": {
Expand Down
3 changes: 2 additions & 1 deletion dist/js/field.js

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions dist/js/field.js.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*!
* Cropper.js v1.5.7
* https://fengyuanchen.github.io/cropperjs
*
* Copyright 2015-present Chen Fengyuan
* Released under the MIT license
*
* Date: 2020-05-23T05:23:00.081Z
*/

/*!
* Determine if an object is a Buffer
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/

/**
* @license
* Lodash <https://lodash.com/>
* Copyright JS Foundation and other contributors <https://js.foundation/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
2 changes: 1 addition & 1 deletion dist/mix-manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"/js/field.js": "/js/field.js",
"/css/field.css": "/css/field.css"
}
}
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"cross-env": "^5.0.0",
"laravel-mix": "^1.0",
"laravel-nova": "^1.0"
"cross-env": "^7.0.2",
"laravel-mix": "^5.0.4",
"laravel-nova": "^1.2.2",
"resolve-url-loader": "^3.1.1",
"sass": "^1.26.8",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.11"
},
"dependencies": {
"vue": "^2.5.0",
"vue-cropperjs": "^2.2.2"
"vue-cropperjs": "^4.1.0"
}
}
1 change: 1 addition & 0 deletions resources/js/components/FormField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
</template>

<script>
import 'cropperjs/dist/cropper.css'
import VueCropper from 'vue-cropperjs'
import { FormField, HandlesValidationErrors, Errors } from 'laravel-nova'
Expand Down
69 changes: 63 additions & 6 deletions src/AdvancedImage.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Ctessier\NovaAdvancedImageField;

use Illuminate\Support\Facades\Storage;
use Intervention\Image\ImageManagerStatic as Image;
use Intervention\Image\Facades\Image;
use Laravel\Nova\Fields\File;
use Laravel\Nova\Http\Requests\NovaRequest;

Expand All @@ -16,6 +16,16 @@ class AdvancedImage extends File
*/
public $component = 'advanced-image-field';

/**
* The driver library to use for image manipulation.
*
* This value will override the driver configured for Intervention
* in the `config/image.php` file of the Laravel project.
*
* @var string|null
*/
public $driver = null;

/**
* Indicates if the image is croppable.
*
Expand Down Expand Up @@ -65,15 +75,33 @@ public function __construct($name, $attribute = null, $disk = 'public', $storage
{
parent::__construct($name, $attribute, $disk, $storageCallback);

Image::configure(['driver' => 'gd']);

$this->thumbnail(function () {
return $this->value ? Storage::disk($this->disk)->url($this->value) : null;
})->preview(function () {
return $this->value ? Storage::disk($this->disk)->url($this->value) : null;
});
}

/**
* Override the default driver to be used by Intervention for the image manipulation.
*
* @param string $driver
*
* @throws \Exception
*
* @return $this
*/
public function driver(string $driver)
{
if (!in_array($driver, ['gd', 'imagick'])) {
throw new \Exception("The driver \"$driver\" is not a valid Intervention driver.");
}

$this->driver = $driver;

return $this;
}

/**
* Specify if the underlying image should be croppable.
* If a numeric value is given as a first parameter, it will be used to define a fixed aspect
Expand All @@ -95,6 +123,14 @@ public function croppable($param = true)
return $this;
}

/**
* Specify the size (width and height) the image should be resized to.
*
* @param int|null $width
* @param int|null $height
*
* @return $this
*/
public function resize($width = null, $height = null)
{
$this->width = $width;
Expand Down Expand Up @@ -124,9 +160,14 @@ protected function fillAttribute(NovaRequest $request, $requestAttribute, $model
if (!$this->croppable && !$this->width && !$this->height) {
parent::fillAttribute($request, $requestAttribute, $model, $attribute);
} else {
if ($this->driver) {
Image::configure([
'driver' => $this->driver,
]);
}
$image = Image::make($request->{$this->attribute});
if ($this->croppable) {
$this->handleCrop($image, $request);
$this->handleCrop($image, json_decode($request->{$this->attribute.'_data'}));
}
if ($this->width || $this->height) {
$this->handleResize($image, $this->width, $this->height);
Expand All @@ -147,12 +188,28 @@ protected function fillAttribute(NovaRequest $request, $requestAttribute, $model
Storage::disk($this->disk)->delete($previousFileName);
}

private function handleCrop($image, $request)
/**
* Crop the uploaded image.
*
* @param \Intervention\Image\Image $image
* @param object $cropperData
*
* @return void
*/
private function handleCrop($image, $cropperData)
{
$cropperData = json_decode($request->{$this->attribute.'_data'});
$image->crop($cropperData->width, $cropperData->height, $cropperData->x, $cropperData->y);
}

/**
* Resize the uploaded image.
*
* @param \Intervention\Image\Image $image
* @param int|null $width
* @param int|null $height
*
* @return void
*/
private function handleResize($image, $width, $height)
{
$image->resize($width, $height, function ($constraint) {
Expand Down

0 comments on commit f71abde

Please sign in to comment.