cerbero90/Workflow

View on GitHub
src/Console/Drawing/Geometry.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php namespace Cerbero\Workflow\Console\Drawing;

/**
 * Geometry applied to the drawing.
 *
 * @author    Andrea Marco Sartori
 */
class Geometry {

    const BORDER_WIDTH = 1;

    const MIN_SPACE_FROM_BORDER_X = 1;

    const MIN_SPACE_FROM_BORDER_Y = 0;

    const ARROW_WIDTH = 1;

    const MIN_PIPE_LENGTH = 8;

    const SPACE_FROM_ARROW = 1;

    /**
     * @author    Andrea Marco Sartori
     * @var        string    $core    The name of the core.
     */
    protected $core;

    /**
     * @author    Andrea Marco Sartori
     * @var        array    $pipes    List of pipes.
     */
    protected $pipes;

    /**
     * @author    Andrea Marco Sartori
     * @var        integer    $nesting    Nesting level.
     */
    protected $nesting = 0;

    /**
     * Set the name of the core.
     *
     * @author    Andrea Marco Sartori
     * @param    string    $core
     * @return    void
     */
    public function setCore($core)
    {
        $this->core = $core;
    }

    /**
     * Set the pipes.
     *
     * @author    Andrea Marco Sartori
     * @param    array    $pipes
     * @return    void
     */
    public function setPipes(array $pipes)
    {
        $this->pipes = $pipes;
    }

    /**
     * Calculate the half width of the drawing.
     *
     * @author    Andrea Marco Sartori
     * @param    boolean    $up
     * @return    integer
     */
    public function getHalfWidth($up = false)
    {
        $number = $this->getTotalWidth();

        return $this->roundHalf($number, $up);
    }

    /**
     * Round the half of a number, either up or down.
     *
     * @author    Andrea Marco Sartori
     * @param    integer    $number
     * @param    boolean    $up
     * @return    integer
     */
    private function roundHalf($number, $up)
    {
        $round = $up ? 'ceil' : 'floor';

        return $round($number / 2);
    }

    /**
     * Calculate the total width of the drawing.
     *
     * @author    Andrea Marco Sartori
     * @return    integer
     */
    protected function getTotalWidth()
    {
        $borders = (static::BORDER_WIDTH + static::MIN_SPACE_FROM_BORDER_X) * 2;
        
        if(empty($this->pipes))
        {
            return $borders + $this->getCoreLength();
        }

        $borders *= count($this->pipes);

        $name = ($this->getLongestPipeLength() + static::SPACE_FROM_ARROW) * 2;

        return $borders + $name + static::ARROW_WIDTH;
    }

    /**
     * Calculate the length of the core name.
     *
     * @author    Andrea Marco Sartori
     * @return    integer
     */
    protected function getCoreLength()
    {
        return strlen($this->core);
    }

    /**
     * Calculate the length of the longest pipe name.
     *
     * @author    Andrea Marco Sartori
     * @return    integer
     */
    protected function getLongestPipeLength()
    {
        if(empty($this->pipes)) return 0;

        return array_reduce($this->pipes, function($carry, $pipe)
        {
            return strlen($pipe) > $carry ? strlen($pipe) : $carry;

        }, static::MIN_PIPE_LENGTH);
    }

    /**
     * Retrieve the spaced pipe and method pair.
     *
     * @author    Andrea Marco Sartori
     * @param    string    $pipe
     * @param    string    $arrow
     * @param    string    $method
     * @return    string
     */
    public function getSpacedPipe($pipe, $arrow, $method)
    {
        $left = $this->getSpacesByWord($pipe);

        $arrow = $this->addSpacesToArrow($arrow);

        $right = $this->getSpacesByWord($method);

        return $left.$pipe.$arrow.$method.$right;
    }

    /**
     * Retrieve the blank spaces close to a word.
     *
     * @author    Andrea Marco Sartori
     * @param    string    $word
     * @return    string
     */
    protected function getSpacesByWord($word)
    {
        $length = $this->getSideBordersLength() + static::SPACE_FROM_ARROW + static::ARROW_WIDTH;

        $extra = $this->getHalfWidth(true) - $length - strlen($word);

        return $extra > 0 ? str_repeat(' ', $extra) : '';
    }

    /**
     * Retrieve the length of the borders of a side.
     *
     * @author    Andrea Marco Sartori
     * @return    integer
     */
    protected function getSideBordersLength()
    {
        $border = (static::BORDER_WIDTH + static::MIN_SPACE_FROM_BORDER_X);

        return $border * $this->nesting;
    }

    /**
     * Add spaces around the given arrow.
     *
     * @author    Andrea Marco Sartori
     * @param    string    $arrow
     * @return    string
     */
    protected function addSpacesToArrow($arrow)
    {
        $spaces = str_repeat(' ', static::SPACE_FROM_ARROW);

        return "{$spaces}{$arrow}{$spaces}";
    }

    /**
     * Retrieve the left borders formatted with the given border.
     *
     * @author    Andrea Marco Sartori
     * @param    string    $border
     * @return    string
     */
    public function getLeftBordersWith($border)
    {
        $border = str_repeat($border, static::BORDER_WIDTH);

        $space = str_repeat(' ', static::MIN_SPACE_FROM_BORDER_X);

        return str_repeat("{$border}{$space}", $this->nesting);
    }

    /**
     * Retrieve the right borders formatted with the given border.
     *
     * @author    Andrea Marco Sartori
     * @param    string    $border
     * @return    string
     */
    public function getRightBordersWith($border)
    {
        $space = str_repeat(' ', static::MIN_SPACE_FROM_BORDER_X);

        $border = str_repeat($border, static::BORDER_WIDTH);

        return str_repeat("{$space}{$border}", $this->nesting);
    }

    /**
     * Increase the nesting level.
     *
     * @author    Andrea Marco Sartori
     * @return    void
     */
    public function increaseNesting()
    {
        $this->nesting++;
    }

    /**
     * Calculate the width of the drawing without the borders.
     *
     * @author    Andrea Marco Sartori
     * @return    integer
     */
    public function getWidthButBorders()
    {
        return $this->getTotalWidth() - $this->getBordersLength();
    }

    /**
     * Calculate the length of the borders.
     *
     * @author    Andrea Marco Sartori
     * @return    integer
     */
    protected function getBordersLength()
    {
        return $this->getSideBordersLength() * 2;
    }

    /**
     * Retrieve the spaced core name.
     *
     * @author    Andrea Marco Sartori
     * @return    string
     */
    public function getSpacedCore()
    {
        $left = $this->getSpacesByCore();

        $right = $this->getSpacesByCore(true);

        return $left.$this->core.$right;
    }

    /**
     * Retrieve the blank spaces close to the core.
     *
     * @author    Andrea Marco Sartori
     * @param    boolean    $up
     * @return    string
     */
    protected function getSpacesByCore($up = false)
    {
        $free = $this->getTotalWidth() - $this->getBordersLength() - $this->getCoreLength();

        return $free < 1 ? '' : str_repeat(' ', $this->roundHalf($free, $up));
    }

    /**
     * Decrease the nesting level.
     *
     * @author    Andrea Marco Sartori
     * @return    void
     */
    public function decreaseNesting()
    {
        $this->nesting--;
    }

}