# Module Customization

Advanced configuration options for customizing how Gacela discovers and resolves module classes.

## Suffix Types

```php
addSuffixTypeFacade(string $suffix);
addSuffixTypeFactory(string $suffix);
addSuffixTypeConfig(string $suffix);
addSuffixTypeProvider(string $suffix);
```

Apart from the known Gacela suffix classes: `Factory`, `Config`, and `Provider`, you can define other suffixes to be
resolved for your different modules. You can do this by adding custom gacela resolvable types.

```php
<?php # gacela.php

return function (GacelaConfig $config) {
  $config->addSuffixTypeFacade('EntryPoint');
  $config->addSuffixTypeFactory('Creator');
  $config->addSuffixTypeConfig('Conf');
  $config->addSuffixTypeProvider('Binder');
};
```

In the example above, you'll be able to create a gacela module with these file names:

```bash
ExampleModule
├── Domain
│   └── YourLogicClass.php
├── EntryPoint.php  # this is the `Facade`
├── Creator.php     # this is the `Factory`
├── Conf.php        # this is the `Config`
└── Binder.php      # this is the `Provider` 
```

## Project Namespaces

```php
setProjectNamespaces(array $list);
```

You can add your project namespaces to be able to resolve gacela classes with priorities.

Gacela will start looking on your project namespaces when trying to resolve any gacela resolvable classes, eg:
`Facade`, `Factory`, `Config`, or `Provider`.

Let's visualize it with an example. Consider this structure:
```
├── gacela.php
├── index.php # entry point
├── src
│   └── Main
│       └── ModuleA
│           └── Factory.php
└── vendor
    └── third-party
        └── ModuleA
            ├── Facade.php
            └── Factory.php
```

```php
<?php # gacela.php

return function (GacelaConfig $config) {
  $config->setProjectNamespaces(['Main']);
};
```

Because you have defined `Main` as your project namespace, when you use the `ModuleA\Facade` from vendor, that Facade
will load the Factory from `src/Main/ModuleA/Factory` and not `vendor/third-party/ModuleA/Factory` because `Main` has
priority (over `third-party`, in this case).

**TL;DR**: You can override gacela resolvable classes by copying the directory structure from vendor modules in your
project namespaces.

## Listening to internal events

```php
registerGenericListener(callable $listener);
registerSpecificListener(string $event, callable $listener);
```

Gacela has an internal event-listener system that dispatches a variety of events.
These are read-only events interesting for tracing, debugging or act on them as you want.

### Register a generic listener

```php
<?php # gacela.php

return function (GacelaConfig $config) {
  $config->registerGenericListener(
    function (GacelaEventInterface $event) {
      echo $event->toString();
    }
  );
};
```

### Register a specific listener

```php
<?php # gacela.php

return function (GacelaConfig $config) {
  $config->registerSpecificListener(
    ResolvedClassCreatedEvent::class, 
    function (GacelaEventInterface $event): void {
      echo $event->toString();
    }
  );
};
```

### The full event catalog

The high-level lifecycle events (bootstrap, config, container, provider and cache)
and every low-level class-resolution event live in one place, each with its typed
accessors and copy-paste recipes: see **[Events](https://gacela-project.com/docs/1.x/events.md)**.

## Reset InMemoryCache

```php
resetInMemoryCache();
```

If you are working with integration tests, this option can be helpful to avoid false-positives, as `Gacela` works as a global singleton pattern to store the resolved dependencies.

```php
<?php # gacela.php

return function (GacelaConfig $config) {
  $config->resetInMemoryCache();
};
```
