## Developer notes

### Symfony & Twig

Symfony & Twig is used for the backend (because PS 8.x does not fully implement
Symfony on the frontend). The **config** files are still read on frontend though
so we can leverage DI same way as in the backend.

### vendor folder

PS is built through Composer, but we cannot leverage this for our own package
because modules in PS are not installed through Composer. Because of this, we
need to include our dependencies in a **vendor** folder within our module, and
we need to manually autoload our files since Composer cannot do this for us.

### Bootstrapping Ecom

Because the backend use Symfony (and PS 9.x will also use this for its frontend)
we should leverage the event system in Symfony to load our classes and bootstrap
Ecom.

However, since in PS 8.x, the frontend is not Symfony, we need to bootstrap Ecom
and load our classes using the legacy hook system instead.

This means the file structure will be a little confusing:

- `src/Service/Autoloader` Loads our classes.
- `src/Service/Ecom` Configures the Ecom instance.
- `src/EventListener/Autoloader` Listens for the `kernel.request` event and
  autoloads our classes through the `Autoloader` service.
- `src/EventListener/Ecom` Listens for the `kernel.request` event and
  configures the Ecom instance through the `Ecom` service.
- `src/Service/TwigTranslations` Listens for the `kernel.request` event and
  adds a filter to Twig for translating strings through Ecom.

You will note that there are three separate classes we execute for the same
event. The reason for this is that the autoloader must execute before the
others. The other two leverage DI to inject classes which we need to load
before its possible.

You will also note that the `Autoloader` listener class will execute the
`Autoloader` service from its constructor. This is because Symfony will find all
classes that listens for the `kernel.request` event and create instances of them
then it will execute whatever method we've configured in turn on each of the
created objects. The autoloader _must_ load classes before the other listeners
can leverage DI, otherwise we will get an error. This is why the autoloader
executes from its constructor.

While we technically could combine the two other event listeners for
`kernel.request` this would make for a more confusing integration pattern, which
it why we've separated them.

We abstract the actual code to load classes and configure ecom to classes in
`src/Service` because we need to execute them differently on frontend where
Symfony events are not available to us (PS 8.x).

### Configuration files

In the `config` folder we have `admin/services.yml` and `fron/services.yml`
which are used to configure Symfony services (objects with DI, event listeners
etc.) for **backend** and **frontend** respectively.

In the root of the config directory there is a `common.yml` file which is used
to configure services that are used in both the backend and frontend. We import
this file in both `admin/services.yml` and `front/services.yml`.
