<?php
							 | 
						|
								
							 | 
						|
								namespace App\Menus\Nginx;
							 | 
						|
								
							 | 
						|
								use PhpSchool\CliMenu\Builder\CliMenuBuilder;
							 | 
						|
								use PhpSchool\CliMenu\CliMenu;
							 | 
						|
								use PhpSchool\CliMenu\MenuItem\CheckboxItem;
							 | 
						|
								use PhpSchool\CliMenu\Style\SelectableStyle;
							 | 
						|
								use PhpSchool\CliMenu\MenuItem\MenuMenuItem;
							 | 
						|
								use PhpSchool\CliMenu\MenuItem\StaticItem;
							 | 
						|
								
							 | 
						|
								use Respect\Validation\Validator as v;
							 | 
						|
								use Respect\Validation\Exceptions\NestedValidationException;
							 | 
						|
								
							 | 
						|
								use App\Menus\ItemValidator;
							 | 
						|
								
							 | 
						|
								use App\BladeFile;
							 | 
						|
								use App\Helpers\NginxTemplateHelper;
							 | 
						|
								
							 | 
						|
								use App\Facades\TerminalHelper;
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 *
							 | 
						|
								 *
							 | 
						|
								 *  @author Björn Hase, Tentakelfabrik
							 | 
						|
								 *  @license http://opensource.org/licenses/MIT The MIT License
							 | 
						|
								 *  @link https://gitea.tentakelfabrik.de/Tentakelfabrik/mcp
							 | 
						|
								 *
							 | 
						|
								 */
							 | 
						|
								class TemplateMenuFactory
							 | 
						|
								{
							 | 
						|
								    // path templates
							 | 
						|
								    const TEMPLATES_DIR = '/resources/nginx/templates';
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     *  add item to select template
							 | 
						|
								     *
							 | 
						|
								     *
							 | 
						|
								     *  @return PhpSchool\CliMenu\Builder\CliMenu
							 | 
						|
								     *
							 | 
						|
								     */
							 | 
						|
								    public function addSelectTemplateItem()
							 | 
						|
								    {
							 | 
						|
								        $menu = function(CliMenuBuilder $builder)
							 | 
						|
								        {
							 | 
						|
								            // create blade
							 | 
						|
								            $bladeFile = new BladeFile(self::TEMPLATES_DIR);
							 | 
						|
								
							 | 
						|
								            $builder
							 | 
						|
								                ->setTitle('Nginx > Add')
							 | 
						|
								                ->setGoBackButtonText('Back');
							 | 
						|
								
							 | 
						|
								            $nginxTemplateHelper = new NginxTemplateHelper();
							 | 
						|
								
							 | 
						|
								            // get templates
							 | 
						|
								            foreach($nginxTemplateHelper->find() as $template) {
							 | 
						|
								                $submenuCallable = $this->addCreateItem($template, $bladeFile);
							 | 
						|
								                $builder
							 | 
						|
								                    ->addSubMenu($template['name'], $submenuCallable);
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            $builder->addLineBreak('-');
							 | 
						|
								        };
							 | 
						|
								
							 | 
						|
								        return $menu;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     *  default configuration
							 | 
						|
								     *
							 | 
						|
								     *  @TODO will be removed after
							 | 
						|
								     *
							 | 
						|
								     *  @return array
							 | 
						|
								     */
							 | 
						|
								    private function getConfiguration()
							 | 
						|
								    {
							 | 
						|
								        return [
							 | 
						|
								            'domain' => '',
							 | 
						|
								            'root' => '',
							 | 
						|
								            'index' => 'index.php',
							 | 
						|
								            'ssl' => true,
							 | 
						|
								            'redirect_www' => true
							 | 
						|
								        ];
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     *  add input item
							 | 
						|
								     *
							 | 
						|
								     *  @param string $key
							 | 
						|
								     *  @param string $label
							 | 
						|
								     *  @param array $configuration
							 | 
						|
								     */
							 | 
						|
								    private function addInputItem($key, $label, &$configuration, $itemValidator = NULL)
							 | 
						|
								    {
							 | 
						|
								        $callable = function(CliMenu $menu) use ($key, $label, &$configuration, $itemValidator)
							 | 
						|
								        {
							 | 
						|
								            $input = $menu->askText();
							 | 
						|
								
							 | 
						|
								            if ($configuration[$key]) {
							 | 
						|
								                $input->setPlaceholderText($configuration[$key]);
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            $result = $input->ask();
							 | 
						|
								            $configuration[$key] = $result->fetch();
							 | 
						|
								
							 | 
						|
								            $menu->getSelectedItem()->setText($label.': '.$result->fetch());
							 | 
						|
								
							 | 
						|
								            if ($itemValidator) {
							 | 
						|
								                $itemValidator->validate($menu, $menu->getSelectedItem(), [ $key => $result->fetch() ]);
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            $menu->redraw();
							 | 
						|
								        };
							 | 
						|
								
							 | 
						|
								        return $callable;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     *  add item to publish configuration
							 | 
						|
								     *
							 | 
						|
								     *  @param string $template
							 | 
						|
								     *  @param object $bladeFile
							 | 
						|
								     *  @param array $configuration
							 | 
						|
								     */
							 | 
						|
								    private function addPublishItem($template, $bladeFile, &$configuration)
							 | 
						|
								    {
							 | 
						|
								        $callable = function(CliMenu $menu) use ($template, $bladeFile, &$configuration)
							 | 
						|
								        {
							 | 
						|
								            // getting configuration
							 | 
						|
								            $data = $configuration;
							 | 
						|
								
							 | 
						|
								            $validator = v::key('domain', v::domain(false))
							 | 
						|
								                ->key('root', v::notEmpty())
							 | 
						|
								                ->key('index', v::notEmpty())
							 | 
						|
								                ->key('phpFpm', v::notEmpty());
							 | 
						|
								
							 | 
						|
								            try {
							 | 
						|
								                $validator->assert($data);
							 | 
						|
								            } catch(NestedValidationException $exception) {
							 | 
						|
								                $errors = $exception->getMessages();
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if (isset($errors)) {
							 | 
						|
								                TerminalHelper::confirmArray($menu, $errors);
							 | 
						|
								            } else {
							 | 
						|
								
							 | 
						|
								                // create filename
							 | 
						|
								                $filename = $configuration['domain'].'.conf';
							 | 
						|
								
							 | 
						|
								                // write configuration to file
							 | 
						|
								                $bladeFile->put($template['name'], '/etc/nginx/sites-available/'.$filename, $configuration);
							 | 
						|
								                $menu->confirm('Success!')->display('Ok!');
							 | 
						|
								
							 | 
						|
								                // invoke action
							 | 
						|
								                $action = new NginxVhostGoBackAction();
							 | 
						|
								                is_callable($action($menu));
							 | 
						|
								            }
							 | 
						|
								        };
							 | 
						|
								
							 | 
						|
								        return $callable;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     *  adding radio buttons to select php-fpm version
							 | 
						|
								     *
							 | 
						|
								     *
							 | 
						|
								     *  @param CliMenuBuilder $builder
							 | 
						|
								     *  @param array $configuration
							 | 
						|
								     */
							 | 
						|
								    private function addPhpFpmItems($builder, &$configuration)
							 | 
						|
								    {
							 | 
						|
								        // get php-fpm services
							 | 
						|
								        exec('find /lib/systemd/system/ -name "php[0-9\.]*-fpm.service"', $files);
							 | 
						|
								
							 | 
						|
								        foreach($files as $index => $file) {
							 | 
						|
								
							 | 
						|
								            // remove path
							 | 
						|
								            $file = str_replace('/lib/systemd/system/', '', $file);
							 | 
						|
								
							 | 
						|
								            // remove extension
							 | 
						|
								            $file = str_replace('.service', '', $file);
							 | 
						|
								
							 | 
						|
								            $builder->addRadioItem($file, function(CliMenu $menu) use (&$configuration) {
							 | 
						|
								                $configuration['phpFpm'] = $menu->getSelectedItem()->getText();
							 | 
						|
								            });
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        return $builder;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     *  add create item
							 | 
						|
								     *
							 | 
						|
								     *
							 | 
						|
								     *  @param  array $template
							 | 
						|
								     *  @param  Blade $blade
							 | 
						|
								     *  @return CliMenuBuilder
							 | 
						|
								     */
							 | 
						|
								    private function addCreateItem($template, $bladeFile)
							 | 
						|
								    {
							 | 
						|
								        $menu = function(CliMenuBuilder $builder) use ($template, $bladeFile)
							 | 
						|
								        {
							 | 
						|
								            $configuration = $this->getConfiguration();
							 | 
						|
								
							 | 
						|
								            // create checkbox for ssl
							 | 
						|
								            $checkboxSSL = new CheckboxItem('ssl', function(CliMenu $menu) use (&$configuration) {
							 | 
						|
								                $configuration['ssl'] = $menu->getSelectedItem()->getChecked();
							 | 
						|
								            });
							 | 
						|
								
							 | 
						|
								            $checkboxSSL->setChecked($configuration['ssl']);
							 | 
						|
								
							 | 
						|
								            // create checkbox for redirect from www
							 | 
						|
								            $checkboxRedirect = new CheckboxItem('redirect www', function(CliMenu $menu) use (&$configuration) {
							 | 
						|
								                $configuration['redirect_www'] = $menu->getSelectedItem()->getChecked();
							 | 
						|
								            });
							 | 
						|
								
							 | 
						|
								            $checkboxRedirect->setChecked($configuration['redirect_www']);
							 | 
						|
								
							 | 
						|
								            $validator = v::key('root', v::directory());
							 | 
						|
								            $itemValidator = new ItemValidator($validator);
							 | 
						|
								
							 | 
						|
								            $builder
							 | 
						|
								                ->setTitle('Nginx > Add > '.$template['name'])
							 | 
						|
								                ->setGoBackButtonText('Cancel')
							 | 
						|
								
							 | 
						|
								                // input domain
							 | 
						|
								                ->addItem('domain: -', $this->addInputItem('domain', 'domain', $configuration))
							 | 
						|
								
							 | 
						|
								                // input root
							 | 
						|
								                ->addItem('root: -', $this->addInputItem('root', 'root', $configuration, $itemValidator))
							 | 
						|
								
							 | 
						|
								                // input index
							 | 
						|
								                ->addItem('index: '.$configuration['index'], $this->addInputItem('index', 'index', $configuration))
							 | 
						|
								                ->addLineBreak('-');
							 | 
						|
								
							 | 
						|
								            // add php-fpm items
							 | 
						|
								            $builder = $this->addPhpFpmItems($builder, $configuration);
							 | 
						|
								
							 | 
						|
								            $builder
							 | 
						|
								                ->addLineBreak('-')
							 | 
						|
								
							 | 
						|
								                // options
							 | 
						|
								                ->addMenuItem($checkboxSSL)
							 | 
						|
								                ->addMenuItem($checkboxRedirect)
							 | 
						|
								                ->addLineBreak('-')
							 | 
						|
								
							 | 
						|
								                // create
							 | 
						|
								                ->addItem('publish', $this->addPublishItem($template, $bladeFile, $configuration))
							 | 
						|
								                ->addLineBreak('-');
							 | 
						|
								        };
							 | 
						|
								
							 | 
						|
								        return $menu;
							 | 
						|
								    }
							 | 
						|
								}
							 |