puphpet/puphpet

View on GitHub
src/PuphpetBundle/Extension/Manager.php

Summary

Maintainability
A
35 mins
Test Coverage
<?php

namespace PuphpetBundle\Extension;

use PuphpetBundle\Extension;

use Symfony\Component\Yaml\Yaml;

class Manager
{
    /** @var Extension\Archive */
    protected $archive;

    /** @var string Base path to config files */
    protected $confDir;

    /** @var array */
    protected $extensions = [];

    /** @var Yaml */
    private $yaml;

    public function __construct($confDir = __DIR__ . '/../Resources/config')
    {
        $this->confDir = $confDir;
    }

    /**
     * @param string $name
     * @return $this
     */
    public function addExtension($name)
    {
        $confDir = sprintf('%s/%s', $this->confDir, $name);
        $name    = str_replace('-', '_', $name);

        $data      = $this->yamlParse($confDir . '/data.yml');
        $defaults  = $this->yamlParse($confDir . '/defaults.yml');
        $available = $this->yamlParse($confDir . '/available.yml');

        $data      = is_array($data) ? $data : [];
        $defaults  = is_array($defaults) ? $defaults : [];
        $available = is_array($available) ? $available : [];

        $mergedData = array_replace_recursive($data, $defaults);

        $this->extensions[$name] = [
            'available' => $available,
            'data'      => $data,
            'defaults'  => $defaults,
            'merged'    => $mergedData,
        ];

        return $this;
    }

    /**
     * @param string $name
     * @return array
     */
    public function getExtension($name)
    {
        $name = str_replace('-', '_', $name);

        return $this->extensions[$name];
    }

    /**
     * @return array
     */
    public function getExtensions()
    {
        return $this->extensions;
    }

    /**
     * @param string $name
     * @return array
     */
    public function getExtensionData($name)
    {
        $name = str_replace('-', '_', $name);

        return $this->extensions[$name]['data'];
    }

    /**
     * @param string $name
     * @return array
     */
    public function getExtensionAvailableData($name)
    {
        $name = str_replace('-', '_', $name);

        return $this->extensions[$name]['available'];
    }

    /**
     * @param array $data
     * @return string
     */
    public function createConfig(array $data)
    {
        foreach ($data as $key => $values) {
            $name = $this->parseDataKeyName($values, $key);

            if (!empty($this->extensions[$name])) {
                $data[$key] = array_replace_recursive($this->extensions[$name]['data'], $data[$key]);
            }
        }

        return $data;
    }

    /**
     * @param array $data
     * @return string
     */
    public function createArchive(array $data)
    {
        $data = $this->createConfig($data);

        $this->archive = new Extension\Archive;
        $this->archive->queueToFile(
            'puphpet/config.yaml',
            $this->yamlDump($data)
        );

        $this->archive->write();

        return $this->archive->zip();
    }

    /**
     * @return string
     */
    public function getPuppetModules()
    {
        $this->archive = new Extension\Archive('puphpet/puppet/modules');

        $this->archive->write();

        return $this->archive->zip();
    }

    /**
     * Accepts custom data for all possible extensions
     *
     * @param array $data
     * @return bool
     */
    public function setCustomDataAll($data)
    {
        foreach ($this->extensions as $name => $extension) {
            if (!$formattedName = $this->vagrantfileHandling($data, $name)) {
                continue;
            }

            if (empty($data[$formattedName])) {
                continue;
            }

            $mergedData = array_replace_recursive(
                $this->extensions[$name]['data'],
                $data[$formattedName]
            );

            $this->extensions[$name]['merged'] = $mergedData;
        }

        return true;
    }

    /**
     * Figures out which Vagrantfile extension was selected in config file.
     *
     * The vagrantfile config key does not tell us which extension was selected,
     * eg "vagrantfile-rackspace" or "vagrantfile-digitalocean". The best way to
     * figure out which target was originally selected is by reading the
     * "vagrantfile.target" value.
     *
     * While looping, if current $name value is not the vagrantfile extension name
     * chosen, set the "vagrantfile-$name.target" value to "false" so we can
     * properly reflect choice in the GUI.
     *
     * If current $name value is chosen vagrantfile extension, set
     * "vagrantfile-$name.target" value to $name to properly reflect choice in
     * the GUI.
     *
     * @param array  $data Custom data
     * @param string $name Name of current extension in loop
     * @return bool|string
     */
    protected function vagrantfileHandling($data, $name)
    {
        /**
         * If "vagrantfile.target" value was not originally set in config,
         * default to "local". This handles config files created before
         * v5 redesign.
         */
        $vagrantfileTarget = empty($data['vagrantfile']['target'])
            ? 'local'
            : $data['vagrantfile']['target'];

        // Current loop is on a vagrantfile-* key
        if (stristr($name, 'vagrantfile') !== false) {
            // Current loop is NOT what was chosen in custom target
            if (stristr($name, $vagrantfileTarget) === false) {
                $this->extensions[$name]['merged']['target'] = false;

                return false;
            }

            $this->extensions[$name]['merged']['target'] = $vagrantfileTarget;

            return 'vagrantfile';
        }

        return $name;
    }

    protected function parseDataKeyName($data, $name)
    {
        if (stristr($name, 'vagrantfile') !== false) {
            return sprintf('vagrantfile_%s', $data['target']);
        }

        return $name;
    }

    protected function yamlParse($file)
    {
        if (!$this->yaml) {
            $this->yaml = new Yaml();
        }

        return $this->yaml->parse(file_get_contents($file), true);
    }

    protected function yamlDump($data)
    {
        if (!$this->yaml) {
            $this->yaml = new Yaml();
        }

        return $this->yaml->dump($data, 50, 4);
    }
}