<commit_before><?php
/**
 * Copyright (c) 2015 <NAME>
 *    <<EMAIL>>
 *
 * GNU General Public License v3.0
 *    <http://www.gnu.org/licenses/gpl-3.0.txt>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
declare(strict_types=1);

namespace Oppa\Link;

use Oppa\{Util, Config};
use Oppa\Exception\InvalidConfigException;

/**
 * @package    Oppa
 * @subpackage Oppa\Link
 * @object     Oppa\Link\Linker
 * @author     <NAME> <<EMAIL>>
 */
final class Linker
{
    /**
     * Config.
     * @var Oppa\Config
     */
    protected $config;

    /**
     * Stack.
     * @var array
     */
    protected $links = [];

    /**
     * Constructor.
     * @note  For all methods in this object, "$host" parameter is important, cos
     * it is used as a key to prevent to create new links in excessive way.
     * Thus, host will be always set, even user does not pass/provide it.
     * @param Oppa\Config $config
     */
    final public function __construct(Config $config)
    {
        $this->config = $config;
    }

    /**
     * Connect.
     * @param  string|null $host
     * @return self
     * @throws Oppa\InvalidConfigException
     */
    final public function connect(string $host = null): self
    {
        // link is already active?
        if ($host && isset($this->links[$host])) {
            return $this;
        }

        // set type as single as default
        $type = Link::TYPE_SINGLE;

        // get config as array
        $config = $this->config->toArray();

        // get database directives from given config
        $database = ($config['database'] ?? []);

        // is master/slave active?
        if (true === $this->config->get('sharding')) {
            $master = ($database['master'] ?? []);
            $slaves = ($database['slaves'] ?? []);
            switch ($host) {
                // act: master as default
                case null:
                case Link::TYPE_MASTER:
                    $type = Link::TYPE_MASTER;
                    $database = $database + $master;
                    break;
                //  act: slave
                case Link::TYPE_SLAVE:
                    $type = Link::TYPE_SLAVE;
                    if (!empty($slaves)) {
                        $slave = Util::arrayRand($slaves);
                        $database = $database + $slave;
                    }
                    break;
                default:
                    // given host is master's host?
                    if ($host == ($master['host'] ?? '')) {
                        $type = Link::TYPE_MASTER;
                        $database = $database + $master;
                    } else {
                        // or given host is slaves's host?
                        $type = Link::TYPE_SLAVE;
                        foreach ($slaves as $slave) {
                            if (isset($slave['host'], $slave['name']) && $slave['host'] == $host) {
                                $database = $database + $slave;
                                break;
                            }
                        }
                    }
            }
        }

        // remove unused parts
        unset($config['database'], $database['master'], $database['slaves']);

        // merge configs
        $config = $config + (array) $database;
        if (!isset($config['host'], $config['name'], $config['username'], $config['password'])) {
            throw new InvalidConfigException(
                'Please specify all needed credentials (host'.
                ', name, username, password) for a link!'
            );
        }

        // use host as a key for link stack
        $host = $config['host'];

        // create a new link if not exists
        if (!isset($this->links[$host])) {
            $link = new Link($type, $host, new Config($config));
            $link->open();
            $this->setLink($host, $link);
        }

        return $this;
    }

    /**
     * Disconnect.
     * @param  string|null $host<commit_msg>Fix merge actions.<commit_after><?php
/**
 * Copyright (c) 2015 <NAME>
 *    <<EMAIL>>
 *
 * GNU General Public License v3.0
 *    <http://www.gnu.org/licenses/gpl-3.0.txt>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
declare(strict_types=1);

namespace Oppa\Link;

use Oppa\{Util, Config};
use Oppa\Exception\InvalidConfigException;

/**
 * @package    Oppa
 * @subpackage Oppa\Link
 * @object     Oppa\Link\Linker
 * @author     <NAME> <<EMAIL>>
 */
final class Linker
{
    /**
     * Config.
     * @var Oppa\Config
     */
    protected $config;

    /**
     * Stack.
     * @var array
     */
    protected $links = [];

    /**
     * Constructor.
     * @note  For all methods in this object, "$host" parameter is important, cos
     * it is used as a key to prevent to create new links in excessive way.
     * Thus, host will be always set, even user does not pass/provide it.
     * @param Oppa\Config $config
     */
    final public function __construct(Config $config)
    {
        $this->config = $config;
    }

    /**
     * Connect.
     * @param  string|null $host
     * @return self
     * @throws Oppa\InvalidConfigException
     */
    final public function connect(string $host = null): self
    {
        // link is already active?
        if ($host && isset($this->links[$host])) {
            return $this;
        }

        // set type as single as default
        $type = Link::TYPE_SINGLE;

        // get config as array
        $config = $this->config->toArray();

        // get database directives from given config
        $database = ($config['database'] ?? []);

        // is master/slave active?
        if (true === $this->config->get('sharding')) {
            $master = ($database['master'] ?? []);
            $slaves = ($database['slaves'] ?? []);
            switch ($host) {
                // act: master as default
                case null:
                case Link::TYPE_MASTER:
                    $type = Link::TYPE_MASTER;
                    $database = array_merge($database, $master);
                    break;
                //  act: slave
                case Link::TYPE_SLAVE:
                    $type = Link::TYPE_SLAVE;
                    if (!empty($slaves)) {
                        $database = array_merge($database, Util::arrayRand($slaves));
                    }
                    break;
                default:
                    // given host is master's host?
                    if ($host == ($master['host'] ?? '')) {
                        $type = Link::TYPE_MASTER;
                        $database = array_merge($database, $master);
                    } else {
                        // or given host is slaves's host?
                        $type = Link::TYPE_SLAVE;
                        foreach ($slaves as $slave) {
                            if (isset($slave['host']) && $slave['host'] == $host) {
                                $database = array_merge($database, $slave);
                                break;
                            }
                        }
                    }
            }
        }

        // remove unused parts
        unset($config['database'], $database['master'], $database['slaves']);

        // merge configs
        $config = array_merge($config, $database);
        if (!isset($config['host'], $config['name'], $config['username'], $config['password'])) {
            throw new InvalidConfigException(
                'Please specify all needed credentials (host, name, username, password) for a link!');
        }

        // use host as a key for link stack
        $host = $config['host'];

        // create a new link if not exists
        if (!isset($this->links[$host])) {
            $link = new Link($type, $host, new Config($config));
            $link->open();
            // add link to links stack
            $this->setLink($host, $link);
        }

        return $this;
    }

    /**
     * Disconnect.
     * @param  string|null $host
{'fraction_non_alphanumeric': 0.12562486415996524, 'fraction_numerical': 0.0021734405564007822, 'mean_word_length': 1.6078209124397846, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2928858', 'n_tokens_mistral': 2457, 'n_tokens_neox': 2358, 'n_words': 760}