# mtcmedia/platform

This repository is the starting base of the mtc code platform. It is a Laravel
based system with some endpoint-based features that have been used in the system historically.
System functions as a Laravel application and most if not all patterns of Laravel are usable and 
encouraged (key exception currently is mail/notification system). 

**Key system tools**

This system is running on **Laravel 6.x**. Documentation about Laravel can be
found [here](https://laravel.com/docs/6.x).

System uses **Twig** 1.x to render templates. Documentation on Twig can be found 
[here](https://twig.symfony.com/doc/1.x/)

For reactive UI system uses Vue.js 2.6+ and jQuery 1.x. Documentation 
on Vue.js can be found [here](https://vuejs.org/v2/guide/), however jQuery can be found [here](https://api.jquery.com/)

System provides two key user journeys - customer/public side and admin user area. 
Admin user area uses **Bootstrap** v4.x for CSS styles. Documentation on Bootstrap 
can be found [here](https://getbootstrap.com/docs/4.0/getting-started/introduction/)


## Installation and setup process

This section describes installation process of the system

### Installation on server
mtc servers or docker setup should manage successful site installation by default. The key requirements are listed below, however there will be some php extensions required.

  PHP >= 7.2.0
  Node >= 8.X
  composer
  MySQL database

While not explicitly required by the framework we normally use MySQL as database engine

**Database**
During installation process you will also need to provide database name and username/password to access it,
so it is best to create these values ahead of time. Database and its user can be set up via cPanel on the account if working with mtc cPanel server.

We follow these guidelines for naming database and user:
```
SITEUSERNAME_db
SITEUSERNAME_admin
```
User needs all access privileges to the database

You can start a new project with the following commands from SSH/bash or any other shell.

**0.** SSH into account, empty public_html and execute the following scripts from the root (above public_html). If you are doing this from your local machine, choose location based on personal preference.

**1.** Clone this repository to your destination (public_html represents the server path, if you are using local setup adjust this to project name)
```
# For starting work on a project:
composer create-project mtcmedia/platform public_html --repository-url=https://composer.mtcassets.com

# For Development:
composer create-project mtcmedia/platform public_html dev-master --repository-url=https://composer.mtcassets.com --keep-vcs
```

Development version keeps main git repository in place allowing you to use this git repository for doing modifications and submitting pull requests.
Our project workflow however does start their own git repository so for that process we do not require keeping git folder.
You can also create a development branch of the project by specifying a branch after the destination path.


**2.** Go into project directory (cd public_html) and set up the environment values. This step will require some questions from you including DB credentials
```bash
php artisan install:create-env
```

> Sandbox vs project - sandbox is for system development purposes (strips .git folders from submodules), project is for starting a client project

> Bitbucket username is your tag/name (e.g. martinsfridenbergsmtc), not email.
> Bitbucket password is [App Password](https://bitbucket.org/account/settings/app-passwords/) in Bitbucket.

> Theme - project specific theme. For ecommerce/shop use Themey. Theme will install plugins that are required by that specific theme

After entering all the required information, check that the mysql password in .env is accurate given what you entered.

**3.** Run the setup process

```bash
composer setup
```

**4.** To fully install the **shop** packages you will need the following steps:
```bash
composer require mtcmedia/shop
php artisan install:components
```

### Local installation

Before we create a new application on your Windows machine, make sure to install [Docker Desktop](https://www.docker.com/products/docker-desktop). 
Next, you should ensure that Windows Subsystem for Linux 2 (WSL2) is installed and enabled. 
WSL allows you to run Linux binary executables natively on Windows 10. Information on how to install and enable WSL2 
can be found within Microsoft's [developer environment documentation](https://docs.microsoft.com/en-us/windows/wsl/install-win10).

> After installing and enabling WSL2, you should ensure that Docker Desktop is [configured to use the WSL2 backend](https://docs.docker.com/docker-for-windows/wsl/).

If you're developing on a Mac/Linux and Docker Desktop is already installed, you do not require any additional preparation.


To create a new application in a directory named "example-app", you may run the following command in your terminal:

```shell
curl -s "https://projects.mtcmedia.co.uk/start-project/example-app" | bash

# or for dev version (keeping git on the main platform repository) 

curl -s "https://projects.mtcmedia.co.uk/start-project/example-app/dev" | bash
```

After the installation process finishes it will provide the commands for the next steps in the format similar to following.
Run the command to proceed with next installation steps. Before running this commannd make sure you do not have other 
docker containers running on ports 80,443,3306,6379

```shell
# Get started with: 
cd my-project && ./vendor/bin/sail up -d && ./vendor/bin/sail artisan install:create-env && ./vendor/bin/sail composer setup
```

This step will require some questions from you including DB credentials. Guidelines for answers are as follows

> Sandbox vs project - sandbox is for system development purposes (strips .git folders from submodules), project is for starting a client project
> 
> MySQL database credentials should remain unchanged so just proceed by not entering anything in these questions
> 
> Bitbucket username is your tag/name (e.g. martinsfridenbergsmtc), not email.
> 
> Bitbucket password is [App Password](https://bitbucket.org/account/settings/app-passwords/) in Bitbucket.
> 
> Theme - project specific theme. For ecommerce/shop use Themey. Theme will install plugins that are required by that specific theme

If shop was selected to be installed during the installation process, you will need to run the following step to finalize installation
```shell
vendor/bin/sail composer require mtcmedia/shop && vendor/bin/sail artisan install:components
```

> To avoid necessity of having to write `vendor/bin/sail` all the time you can create an alias.
> 
> Alias is added inside your preferred shell config file (`~/.bashrc` for bash, `~/.zshrc` for zsh)
> 
> ```alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'```
> 
> After adding alias you need to either reload the shell or run `source ~/.zshrc` to apply changes to the shell

*(!)When using Sail all commands (php artisan, composer etc.) should use `vendor/bin/sail` or `sail` for invoking instead of php.*


### Local installation for existing application

When working with a team, you may not be the one that initially creates the application.
Therefore, none of the application's Composer dependencies, including Sail, will be installed after you clone 
the application's repository to your local computer.

You may install the application's dependencies by navigating to the application's directory and executing the following command.
This command uses a small Docker container containing PHP and Composer to install the application's dependencies:

```shell
docker run --rm \
-u "$(id -u):$(id -g)" \
-v $(pwd):/var/www/html \
-w /var/www/html \
chialab/php:8.0 \
composer install --ignore-platform-reqs
```

When using the chialab/php:X.X image, you should use the same version of PHP that you plan to use for your application (7.4, 8.0, or 8.1).

### Post-install
If you are working on your sandbox environment (shop) you can run product population script to seed some dummy products
```bash
php artisan populate:products
```

Once finished site should be successfully installed. In case of issues see the errors outlined by the installer.

> (!) If you want to make changes to mtcmedia/platform you will need to make sure ssh key is linked up with bitbucket alongside with --keep-vcs option.

**5.** You can now sign in automagically into admin area - `/admin` using your credentials from the [MTC Projects System](https://projects.mtcmedia.co.uk).

### Known Issues
Some popular issues with the installation process are described on [Wiki](https://wiki.mtcmedia.co.uk/index.php?title=Core_-_5_Minute_Install#Known_Issues)

## Parts of system

This platform does consist of a number of sub-modules that are set-up during installation process:

* **platform** - _this_ repository. Laravel boilerplate + boostrapping for non-package submodules
* [**cms**](https://bitbucket.org/mtcmedia/core-cms/src/master/) - mtc cms system. Documentation is [here](https://wiki.mtcmedia.co.uk/index.php?title=Cms2)
* [**shop**](https://bitbucket.org/mtcmedia/core-shop/src/master/) - mtc ecommerce tooling. This repository used to hold all ecommerce functionality from products to basket/checkout process but it is in transition to be split into Laravel packages so only elements of it remain (product filter/product management) 
* [**plugins/modules**](https://bitbucket.org/mtcmedia/workspace/projects/EXT) - a set of pluggable features for mtc system. List is located [here](https://bitbucket.org/mtcmedia/workspace/projects/EXT). These are not actively maintained so might have some conflicts during installation if they use outdated features. They provide a large set of custom features for system.
* [**mtcmedia packages**](https://composer.mtcassets.com/) - a transition to using packages from pluggables has been in place as packages offer updatability. List of mtc packages with their versions are located [here](https://composer.mtcassets.com/)

mtc package dependencies:

* [mtcmedia/admin-google2fa](https://bitbucket.org/mtcmedia/packages-admin-google2fa/src/master/) - Two Factor authentication implementation for admin user accounts
* [mtcmedia/core](https://bitbucket.org/mtcmedia/core/) - key php modules for system - admin scaffolding, currencies, seo, media/images, countries/regions
* [mtcmedia/insights](https://bitbucket.org/mtcmedia/packages-insights/) - internal stats gatherer for tracking where certain features are installed
* [mtcmedia/installer](https://bitbucket.org/mtcmedia/installer/) - system that handles new site installation and component installation on systems
* mtcmedia/mailer - package that handles email sendout for `email()` function
* [mtcmedia/moxie-manager](https://bitbucket.org/mtcmedia/moxie-manager/) - moxie manager file manager in an updatable package
* [mtcmedia/mtc-login](https://bitbucket.org/mtcmedia/mtc-login/) - API that verifies logins with mtc emails against our centralised project system 
* [mtcmedia/stemmer](https://packagist.org/packages/mtcmedia/stemmer) - stemmer that supports multi-word processing and allows word cleanup

## Architecture concepts
This segment describes key architecture concepts that might differ from native flows of Laravel or other base systems.

System does rely on users knowing [PSR-4](https://www.php-fig.org/psr/psr-4/) concept, Laravel patterns (controllers, routing, artisan tasks, eloquent, service providers etc.)
as these are key elements of the system. If developer working with the system is not aware of these it is recommended to familiarize with them first.

### Plugins / modules
System does have auto-loading process for pluggable features. Pluggables are blocks of functionality that are stored 
either in `plugins` or `modules` folders. At current state there is no difference between a plugin or module and they
behave exactly the same way. Historically they did differ as modules were not included in automatic asset compilation process,
but currently assets are merged for both. Semantically modules are more aimed toward standalone features whilst plugins
are more as extensions of a different module.

Pluggables have a pre-defined PSR-4 namespace:
```json

    "psr-4": {
        "Mtc\\Plugins\\": "plugins/",
        "Mtc\\Modules\\": "modules/"
    }
```

Pluggable feature auto-loading is performed in 3 stages:

* Laravel Service provider auto-loading is attempted - `Mtc\Plugins\PluginName\Classes\Providers\PluginNameServiceProvider` loading is attempted if file exists
* `plugins/PluginName/hooks.php` is loaded (if exists) to register hooks/events early in system lifecycle (legacy feature)
* `plugins/PluginName/loader.php` is loaded (if exists) to register hooks/events after main modules are loaded (legacy feature)

### Task Scheduling & CI/CD deployment
Since system consists both of Laravel and legacy features a combined task scheduler exists in `crons` file.
This file defines tasks application should run on system production environment. Artisan tasks should be defined in 
Console Kernel as it is normally done in Laravel. 

Crons file is automatically deployed to production server crontab via the `deploy.sh` script. mtc's deployment process 
triggers this shell script when deploying to production server. Crons file will be deployed each time so manually
editing crontab on production server will reset cron after deployment 

Deployment script will be run only on production server, deployment between development forks and main staging server is not performed.

Deployment process performs key actions to ensure Continuous integration of the site:

* migrates database changes (laravel migrations)
* compiles assets
* updates dependencies
* resets caches
* ensures scheduled tasks are set

### Queues
[Laravel Queue system](https://laravel.com/docs/6.x/queues) is usable. 
Queues use database engine (jobs are stored in database) and workers are driven by artisan scheduler on production environment.
Artisan will schedule task to run the queue as part of the scheduling process.
On development/staging environments queues _will not_ run automatically and they will have to be triggered manually:

```shell
php artisan queue:listen
```

If a queue task fails, it will record failure in `failed_jobs` table.


### Templates and rendering
System uses Twig as templating engine. Templates can be rendered using `template()` [helper method](https://bitbucket.org/mtcmedia/platform/src/981dbf2740cbc6bfe02bff062dee7d93593ecb44/classes/helpers.php#lines-566)
```php
function template(string $template = null, array $data = [])
```

In some instances there is a use of adding global twig variables and adding twig functions in system, but this behaviour is discouraged.

Templates are loaded from various locations in system (load order from top to bottom):

* cms/templates
* shop/templates
* plugin/myPlugin/templates
* modules/myModule/templates
* packages that register templates via `app('twig_loader')->addPath(dirname(__DIR__, 2) . '/resources/templates');`
* sites/{site-id}/templates
* resources/templates

Twig templates do not have namespacing. Vendor templates can be modified by copying it to a location like resources/templates or sites/{site-id}/templates
with its template path matched to overwrite it (e.g. package/resources/templates/admin/auth/login.twig => /resources/templates/admin/auth/login.twig)

### Asset compilation
Assets are compiled using Laravel Mix (`npm run dev` / `npm run prod`) process. Watcher process for continuous file watching and re-compilation
is available (`npm run watch`). 

System does compile 5 assets during compilation process by default:

* app.js - all front-end javascript functionality
* admin.js - all admin javascript functionality
* app.css - all front-end css 
* admin.css - all admin css
* admin_login.css - css for /admin login page (and password reset page)

### Mail system
Currently system uses `email()` [helper function](https://bitbucket.org/mtcmedia/platform/src/981dbf2740cbc6bfe02bff062dee7d93593ecb44/classes/helpers.php#lines-476) to handle dispatching mail notifications. Function takes pre-rendered content and does not have template rendering features.
```php 
function email(string $recipient_email, string $subject, string $message, bool $dev_copy = false)
```

Mail sending using Laravel Mail facade is possible, but to do this you must ensure the from email details are correct.

### MtcPdo
Additionally to Eloquent system also has `\MtcPdo` class that allows running queries with traditional PDO query engine.
This is still used in a large portion of the system and functions as a raw MySql query engine.

### Hooks
System has `\HooksAdapter` and `\HooksAdapter` classes that implement WordPress hook system. This is very similar concept to 
Laravel events and was used before Events were added to system. It is not recommended to use them for adding new functionality,
but they are still used in a number of sections of the system.

### Image uploading
All application files are uploaded to `uploads/` folder in project path. Image uploading is done using `Mtc\Core\ImagesImageUploader` class.
This class will require specifying image folders - a list of supported image dimensions and folders where each size is stored.
By default, system registers media folders in theme, core and shop. Additional structures can be added via `Mtc\Core\Facades\Media` facade.

### Session 
System uses raw sessions ($_SESSION super-global) via `stechstudio/laravel-raw-sessions` package to ensure session can be shared amongst Laravel and legacy elements.
Whilst in Laravel workflow $_SESSION should **not** be used as Laravel will write its Session store to this variable at the end of request.


### Debugging 
Following debug tools are available to system:

- laravel/tinker
- laravel/telescope
- filp/whoops (error display)

If `php artisan tinker` throws an error make sure `~/.config/psysh/config.php` file exists and has this content:
```php
<?php
return [
    'runtimeDir' => './.psysh',
];
```
