Configuration
=============

.. php:namespace:: Baleen\Cli\Provider

Service Name: :php:const:`Services::CONFIG`

The Baleen CLI framework allows you to easily define your configuration's schema using :php:ns:`Symfony\\Config` 
definitions. A default schema is provided that covers the basic structure.

The default configuration schema is as follows:

.. code-block:: php

    <?php
    [
        // list of Providers to load
        'providers' => [
            'key' => 'My\Provider', // FQCN
            // ...
        ],
        // config for the Repository service
        'migrations' => [
            'directory' => '/path/to/migrations',
            'namespace' => 'Migrations\Namespace', // for autoloading
        ],
        // config for the Storage service
        'storage' => [
            'file' => '/path/to/storage.txt', // path to storage file
        ],
    ];

Throughout this tutorial we refer to specific configuration options using a dot (.) to indicate nesting levels. E.g.
the configuration file location can be specified with the "storage.file" option.

.. note::

  The "migrations" section in the configuration corresponds to the Repository. But we decided to name it "migrations"
  simply because that would be a more recognizable name for end-users who are not familiar with the nomenclature we use
  at Baleen.

Customizing the Configuration
-----------------------------

If you're building your own migrations library based on Baleen CLI you can easily customize the configuration definition
and main configuration class to your needs. If you read any of the other guides most of the process should be familiar
by now, but there are a couple of unique considerations - the main configuration file must:

* Provide default configuration values that comply with the :php:class:`Definition`.
* Accept a configuration that's compliant to the Definition.

Therefore if you change the configuration class, its likely you'll have to change the Definition, and vice-versa.

Configuration Class
+++++++++++++++++++

.. php:namespace:: Baleen\Cli\Config

To customize the configuration class simply create a new class that implements :php:interface:`ConfigInterface` and adds
any additional functionality you may need. Then provide the class in the container under the key mentioned at the top of
this page.

A set of methods that's important to mention is :php:meth:`ConfigInterface::getDefaults` and the
``Config::get{SECTION}Defaults`` family of methods (e.g. :php:meth:`Config::getProviderDefaults`). The main
``getDefaults()`` method should return a complete array of defaults, which is what will be used to create the end-user's
configuration file when the user runs the ``config:init`` command. The other methods in the family are in charge of
returning defaults for the specified section. This is not enforced by the interface, but its useful if you only want to
customize the "storage" defaults but not the rest. See the next section for further explanation.

Another method that's important to note is :php:meth:`ConfigInterface::getDefinition`. It must return an instance of
``Symfony\Component\Config\Definition\ConfigurationInterface``.

.. note::

  For more information about the methods declared in :php:class:`ConfigInterface` refer to the referenced docs.

If the changes to your configuration class don't affect the default definition then just return the default definition.
Otherwise read the next section.

Definition Class
++++++++++++++++

The definition class is simply a class that implements ``Symfony\Component\Config\Definition\ConfigurationInterface``.
So if you want to start your configuration from scratch just implement that interface on a clean class.

Baleen's configuration definition is broken down into multiple methods to make it easy to customize only certain
sections of the configuration. For example, if all you need is to customize the "storage" section of the definition:

1. Create a new Definition class that extends :php:class:`Definition`.
2. Override the :php:meth:``Definition::addStorageNode`` method and supply your own rules for that node.
3. The method must return an instance of ``Symfony\Component\Config\Definition\Builder\NodeDefinition``.

The Definition class is not offered as a service. Its only accessible through the main configuration class'
:php:class:`ConfigInterface::getDefinition` function. So if you have to change the definition you will always have to
override the main Config class as well.
