# LNCShared

This is a git submodule used containing all shared code between LNC applications. It is structured as a Laravel project would be.

## Installation
To add the submodule to a new project use the following command:
`git submodule add https://JhumanJ@bitbucket.org/lnconsulting/lncshared.git`

This will create a lnc-shared directory in your project. Then follow the steps of this readme to install and use each of the components it uses.

## Front-End

### SaSS
TODO: refactor component sass and include in this repository

### JS and Vue.js Components
TODO: refactor as much of the bootstrap js file to put it in here 

To add all of the components in the library simply require the `main.js` file. For instance, in a fresh Laravel application, add the following line to `app.js`:
```javascript

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

require('../../../lncshared/resources/assets/js/main'); // Add this line here


```

## Back-End

### Autoload

To be able to use the classes and the namespace used in the rest of this guide, you need to indicate into your `composer.json` autoloader where is the package. That's how to do so:

```json
{
// ...
  "autoload": {
        "psr-4": {
            "App\\": "app/",
            "LncShared\\App\\": "lncshared/app"   // Add this line here
        }
   }
}
```

After that run `composer dump-autoload` to re-generate the auto-loader. 

### Composer dependencies

List of the composer packages that must be installed (or added to `composer.json`) of the main file:
- `intervention/image`
- `laravel/passport`

You can install them simply by running: `composer require package-name`, where `package-name` is the name of the package as listed above.

### Service Provider

Only one service provider is used by this module, it's `LncSharedServiceProvider`. It used to register the various helpers. To use it, register in the providers array of `config/app.php`:

```php

/*
    |--------------------------------------------------------------------------
    | Autoloaded Service Providers
    |--------------------------------------------------------------------------
    |
    | The service providers listed here will be automatically loaded on the
    | request to your application. Feel free to add your own services to
    | this array to grant expanded functionality to your applications.
    |
    */

    'providers' => [
       // ...
       
       \LncShared\App\Providers\LncSharedServiceProvider::class
    ]

```

#### Aliases

Then, to be able to use the helpers, you can add the following to the alias array of `config/app.php`:
```php

    /*
    |--------------------------------------------------------------------------
    | Class Aliases
    |--------------------------------------------------------------------------
    |
    | This array of class aliases will be registered when this application
    | is started. However, feel free to register as many as you wish as
    | the aliases are "lazy" loaded so they don't hinder performance.
    |
    */

    'aliases' => [
        // ...
        'Error' => \LncShared\App\Helpers\Error::class,
        'NameHelper' => \LncShared\App\Helpers\NameHelper::class,
        'DynamicFieldBank' => \LncShared\App\Facades\DynamicFieldBank::class
        
    ]

```

### Helpers

Three helpers are included and already registered if you followed the previous step of this guide:
- `DynamicFieldBank` (used to ensure that dynamic field are only queried once per request)
- `Error` (used to manage error codes in the app)
- `NameHelper` (generate unique name from full name)

### Commands
Three commands come with this modules. Some of them (`CreateUser` and `Empower` may have to be changed to fit your data model). The commands:
- `CreateUser` (Creates a user)
- `Empower` (Make an existing user an admin)
- `JsonImport` (Import json by posting a specific endpoint as user chunk by chunk)

To be able to use the commands, you must register them in the commands array of `app/Console/Kernel.php` as below.

```php
/**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
    // ...
        CreateUser::class,
        Empower::class,
        JsonImport::class
    ];
```

### OAuth - Custom `protocol` grant type

The package provides a new grant type for Oauth. An api endpoint is created in the application (route name: `api.protocol-token.create`). It returns a protocol token that can then be used to get Oauth access token and refresh token. The protocol token is valid for 60 seconds, and can be used as follows:
- Use the `SHA256 algorithm` to hash the concatenation of the client secret and the protocol token ( `sha256( clientSecret + protocolToken )` ).
- Send an Oauth post request with the grant type `protocol` and the result hash in a `token` field. Of course, `client_id`, `client_secret` and `scope` are still required.  

### Models

It adds the following abstract Models that can be extended:
- `BaseModel` (that implements StrictMode traits and supports more dates format)
- `DynamicModel` (supports the use of the dynamic fields)

It adds the following Models used to power LncShared features:
- `DynamicField` (used by `DynamicModel`).
- `ProtocolToken` (used to create a custom Oauth grant type)

Migration files for these models are automatically loaded. Simply use : `php artisan migrate` to run the migrations.

#### Traits
Some models traits are also imported:
- `HasCompositePrimaryKey` (Overrides eloquent functions to support multi-keys models)
- `HasNews` (Delete attached news on object deletion)
- `HideNull` (Remove null values from the toArray method)
- `NameFullName` (Allow model to be find by id, name, full name or alias)
- `StrictMode` (Prevent undefined attributes to be filled)
- `Uuids` (Allow the primary key to be a Uuid)

For the `NameFullName` attribute, you can also use aliases. To activate them, add the following to your model:
```php
/**
 * Activate aliases use
 */
public function aliasActivated()
{
    return true;
}
```
Your model must have a jsonb field (by default nammed 'alias_names').

### Rules
The following custom rules are also included:
- `Country` (Must be a valid ISO country contained in a predefined json)
- `Currency` (Must be a valid ISO currency contained in a predefined json)
- `Foreign` (Field must be a reference to another precised model)
- `Multidate` (Date validator more flexible in terms of accepted format)

### Requests
The class `RefRequest` can be extended to create more powerful requests. It uses a custom validator (`RefValidator`), which adds more metadata to validation exceptions such as ref_id or validation exceptions.

### Resources
Three resources comes with this module (2 for collections, 1 for actual resource). Then can be extended to return nicely formatted json from your models.
- BaseCollection (Base collection wrapper)
- DynamicCollection (Collection used for dynamic models, it automatically formats dynamic fields)
- DynamicResource (Same but for one entity - not a collection)

### Middleware
This module includes the middleware `ValidJsonMiddleware` to ensure consistency of json posted to the api. To use it, add it to the middleware array of `app/Http/Kernel.php`. You should also add it the api middleware group, so that it automatically checks every request:
```php
/**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        // ...
        ValidJsonMiddleware::class
    ];
    
    /**
         * The application's route middleware groups.
         *
         * @var array
         */
        protected $middlewareGroups = [
            // ...
            
            'api' => [
                ValidJsonMiddleware::class,
                // ...
            ],
        ];
```
### Controllers
This module has `CrudController` that can be extended to build a CRUD for any of your models. 

#### Traits
The `Multiple` trait can be used by controllers (mainly a `CrudController`) to allow the bulk creation/update of many items at the same time.
