novius/laravel-backpack-crud-extended

This package extends Laravel Backpack\CRUD

0.4.0 2018-04-11 13:28 UTC

README

Travis Packagist Release Licence

This package extends Backpack/CRUD. See all features added bellow.

To do this without any modification on your controller or others package, this package:

  • is able to override all Backpack/CRUD views;
  • extends CrudPanel class.

Table of Contents

Installation

In your terminal:

composer require novius/laravel-backpack-crud-extended

Then, if you are on Laravel 5.4 (no need for Laravel 5.5 and higher), register the service provider to your config/app.php file:

'providers' => [
    ...
    Novius\Backpack\CRUD\CrudServiceProvider::class,
];

Publish views

If you have already published backpack-crud views, this package will not work. You have to remove views into resources/views/vendor/backpack/crud/, or to override them with:

php artisan vendor:publish --provider="Novius\Backpack\CRUD\CrudServiceProvider" --force

Configuration

Some options that you can override are available.

php artisan vendor:publish --provider="Novius\Backpack\CRUD\CrudServiceProvider" --tag="config"

Usage & Features

Permissions

Description

  • Permissions can be applied automatically to CRUD Controllers : deny access if user hasn't the permission linked to the route => apply_permissions option
  • Permissions can be automatically created for all Crud Controllers used in you application (4 permissions will be created : list, update, create, delete) => create_permissions_while_browsing option
  • Permissions can be automatically given to the logged user (useful in local environment) => give_permissions_to_current_user_while_browsing option

Requirements

php artisan permissions:generate // Insert permissions in database for each CRUD controllers.
  • Set to true each options that you want activate

Usage

Your CrudController must extend \Novius\Backpack\CRUD\Http\Controllers\CrudController

CRUD Boxes

You can now split your create/edit inputs into multiple boxes.

backpack-crud-boxes

In order to use this feature, you just need to specify the box name for each of your fields.

$this->crud->addField([
    'name' => 'title',
    'label' => "My Title",
    'type' => 'text',
    'box' => 'Box name here'
]);

You can also specify some options to each box:

$this->crud->setBoxOptions('Details', [
    'side' => true,         // Place this box on the right side?
    'class' => "box-info",  // CSS class to add to the div. Eg, <div class="box box-info">
    'collapsed' => true,    // Collapse this box by default?
]);

If you forget to specify a tab name for a field, Backpack will place it in the last box.

You can specify manually a default box in the crud file. If your field doesn't have the box attribute, this field will be displayed in this default box.

$this->crud->setDefaultBox('YourBoxName');

Fields Drivers

Fields type can now be a classname:

$this->crud->addField([
    'name' => 'username',
    'label' => "My username",
    'type' => \My\Other\Package\Field\Foo::class,
]);

This allows you to propose new field types in external packages. Your Field class must implement Field Contract.

Language / i18n

Set a custom dictionary for a specific crud:

$this->crud->setLangFile('backpack::crud/movie');

This dictionary will then be used in the CRUD views.

You can use it in your own views like this:

{{ trans($crud->getLangFile().'.add') }}

Upload Field : UploadableFile Trait

If you use Upload CRUD Field, you can implement this Trait on your Model to automatically upload / delete file(s) on server.

Example:

// Article Model

class Article extends \Backpack\NewsCRUD\app\Models\Article
{
    use Sluggable, SluggableScopeHelpers;
    use HasTranslations;
    use UploadableFile;

    protected $fillable = ['slug', 'title', 'content', 'image', 'status', 'category_id', 'featured', 'date', 'document', 'document_2'];
    protected $translatable = ['slug', 'title', 'content'];

    public function uploadableFiles(): array
    {
        return [
            ['name' => 'document'],
            ['name' => 'document_2', 'slug' => 'title']
        ];
    }
}
// ArticleCrudController

$this->crud->addField([ 
    'label' => 'Image',
    'name' => 'image',
    'type' => 'image',
    'upload' => true,
    'crop' => true, // set to true to allow cropping, false to disable
    'aspect_ratio' => 0, // ommit or set to 0 to allow any aspect ratio
    'prefix' => '/storage/',
]);

$this->crud->addField([
    'label' => 'Document',
    'name' => 'document',
    'type' => 'upload',
    'upload' => true,
    'prefix' => '/storage/',
]);

$this->crud->addField([
    'label' => 'Document 2',
    'name' => 'document_2',
    'type' => 'upload',
    'upload' => true,
    'prefix' => '/storage/',
]);

Upload Field : file_upload_crud validation rule

A validation rule exists to easily validate CRUD request with "upload" field.

Example of usage in your requests files:

public function rules()
{
    return [
        'name' => 'required|min:2|max:191',           
        'document' => 'file_upload_crud:pdf,docx', // the parameters must be valid mime types
    ];
}

public function messages()
{
    return [
        'file_upload_crud' => 'The :attribute must be a valid file.',
    ];
}

Image Field : UploadableImage Trait

If you use the Image CRUD Field, you can implement this trait on your model to automatically manage saving and deleting the image on the server.

Example:

namespace App\Models;

use Backpack\CRUD\CrudTrait;
use Illuminate\Database\Eloquent\Model;
use Novius\Backpack\CRUD\ModelTraits\UploadableImage;

class Example extends Model
{
    use CrudTrait;
    use UploadableImage;

    protected $fillable = ['title', 'image', 'thumbnail'];

    public function uploadableImages()
    {
        return [
            [
                'name' => 'image', // The attribute name where to store the image path
                'slug' => 'title', // The attribute name from which to generate the image file name (optionnal)
            ],
            [
                'name' => 'thumbnail',
            ],
        ];
    }
}

If you want to perform some custom actions on your image after saving or deleting it :

namespace App\Models;

use Backpack\CRUD\CrudTrait;
use Illuminate\Database\Eloquent\Model;
use Novius\Backpack\CRUD\ModelTraits\UploadableImage;

class Example extends Model
{
    use CrudTrait;
    use UploadableImage {
        imagePathSaved as imagePathSavedNative;
        imagePathDeleted as imagePathDeletedNative;
    }

    protected $fillable = ['title', 'image', 'thumbnail'];

    public function uploadableImages()
    {
        return [
            [
                'name' => 'image', // The attribute name where to store the image path
                'slug' => 'title', // The attribute name from which to generate the image file name (optionnal)
            ],
            [
                'name' => 'thumbnail',
            ],
        ];
    }

    /**
     * Callback triggered after image saved on disk
     */
    public function imagePathSaved(string $imagePath, string $imageAttributeName = null, string $diskName = null)
    {
        if (!$this->imagePathSavedNative()) {
            return false;
        }

        // Do what you want here

        return true;
    }

    /**
     * Callback triggered after image deleted on disk
     */
    public function imagePathDeleted(string $imagePath, string $imageAttributeName = null, string $diskName = null)
    {
        if (!$this->imagePathDeletedNative()) {
            return false;
        }
        
        // Do what you want here

        return true;
    }
}

MediaLibrary

If you want to store the images in the MediaLibrary provided by Spatie, use the trait SpatieMediaLibrary\UploadableImage instead of UploadableImage.

For example with the MediaLibrary you can easily manage conversions (crop, resize, ...).

Translations

Both traits UploadableImage and SpatieMediaLibrary\UploadableImage are compatible with the translation package provided by Spatie.

In the case of translatable images with SpatieMediaLibrary\UploadableImage, the name of the collection where the image is stored is composed of the name of the attribute and the locale, separated by a dash (eg. image-en, image-fr, ...).

CRUD : custom routes

You can set a custom value to some routes.

  • Index route : used with "back to all" button or breadcrumb's link. Available with $crud->indexRoute().
  • Reorder route : used with "Reorder button". Available with $crud->reorderRoute().

Example of usage in your CrudController :

// Set a custom index route
$this->crud->setIndexRoute('crud.slide.index', ['slideshow' => (int) request('slideshow')]);

// Set a custom reorder route
$this->crud->setReorderRoute('crud.slide.reorder', ['slideshow' => (int) request('slideshow')]);

Testing

Run the tests with:

./test.sh

Lint

Run php-cs with:

./cs.sh

Contributing

Contributions are welcome! Leave an issue on Github, or create a Pull Request.

Licence

This package is under GNU Affero General Public License v3 or (at your option) any later version.

However, this package requires Backpack\CRUD, which is under YUMMY license: if you use it in a commercial project, you have to buy a backpack license.