Issues (18)

src/InputCharacter.php (6 issues)

1
<?php
2
3
namespace PhpSchool\Terminal;
4
5
use function in_array;
6
7
/**
8
 * @author Aydin Hassan <[email protected]>
9
 */
10
class InputCharacter
11
{
12
    /**
13
     * @var string
14
     */
15
    private $data;
16
17
    public const UP = 'UP';
18
    public const DOWN = 'DOWN';
19
    public const RIGHT = 'RIGHT';
20
    public const LEFT = 'LEFT';
21
    public const CTRLA = 'CTRLA';
22
    public const CTRLB = 'CTRLB';
23
    public const CTRLE = 'CTRLE';
24
    public const CTRLF = 'CTRLF';
25
    public const BACKSPACE = 'BACKSPACE';
26
    public const CTRLW = 'CTRLW';
27
    public const ENTER = 'ENTER';
28
    public const TAB = 'TAB';
29
    public const ESC = 'ESC';
30
31
    private static $controls = [
32
        "\033[A" => self::UP,
33
        "\033[B" => self::DOWN,
34
        "\033[C" => self::RIGHT,
35
        "\033[D" => self::LEFT,
36
        "\033OA" => self::UP,
37
        "\033OB" => self::DOWN,
38
        "\033OC" => self::RIGHT,
39
        "\033OD" => self::LEFT,
40
        "\001"   => self::CTRLA,
41
        "\002"   => self::CTRLB,
42
        "\005"   => self::CTRLE,
43
        "\006"   => self::CTRLF,
44
        "\010"   => self::BACKSPACE,
45
        "\177"   => self::BACKSPACE,
46
        "\027"   => self::CTRLW,
47
        "\n"     => self::ENTER,
48
        "\t"     => self::TAB,
49
        "\e"     => self::ESC,
50
    ];
51
52
    public function __construct(string $data)
53
    {
54
        $this->data = $data;
55
    }
56
57
    public function isHandledControl() : bool
58
    {
59
        return isset(static::$controls[$this->data]);
0 ignored issues
show
Since $controls is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $controls to at least protected.
Loading history...
60
    }
61
62
    /**
63
     * Is this character a control sequence?
64
     */
65
    public function isControl() : bool
66
    {
67
        return preg_match('/[\x00-\x1F\x7F]/', $this->data);
0 ignored issues
show
Bug Best Practice introduced by
The expression return preg_match('/[\x0...1F\x7F]/', $this->data) returns the type integer which is incompatible with the type-hinted return boolean.
Loading history...
68
    }
69
70
    /**
71
     * Is this character a normal character?
72
     */
73
    public function isNotControl() : bool
74
    {
75
        return ! $this->isControl();
76
    }
77
78
    /**
79
     * Get the raw character or control sequence
80
     */
81
    public function get() : string
82
    {
83
        return $this->data;
84
    }
85
86
    /**
87
     * Get the actual control name that this sequence represents.
88
     * One of the class constants. Eg. self::UP.
89
     *
90
     * Throws an exception if the character is not actually a control sequence
91
     */
92
    public function getControl() : string
93
    {
94
        if (!isset(static::$controls[$this->data])) {
0 ignored issues
show
Since $controls is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $controls to at least protected.
Loading history...
95
            throw new \RuntimeException(sprintf('Character "%s" is not a control', $this->data));
96
        }
97
98
        return static::$controls[$this->data];
99
    }
100
101
    /**
102
     * Get the raw character or control sequence
103
     */
104
    public function __toString() : string
105
    {
106
        return $this->get();
107
    }
108
109
    /**
110
     * Does the given control name exist? eg self::UP.
111
     */
112
    public static function controlExists(string $controlName) : bool
113
    {
114
        return in_array($controlName, static::$controls, true);
0 ignored issues
show
Since $controls is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $controls to at least protected.
Loading history...
115
    }
116
117
    /**
118
     * Get all of the available control names
119
     */
120
    public static function getControls() : array
121
    {
122
        return array_values(array_unique(static::$controls));
0 ignored issues
show
Since $controls is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $controls to at least protected.
Loading history...
123
    }
124
125
    /**
126
     * Create a instance from a given control name. Throws an exception if the
127
     * control name does not exist.
128
     */
129
    public static function fromControlName(string $controlName) : self
130
    {
131
        if (!static::controlExists($controlName)) {
132
            throw new \InvalidArgumentException(sprintf('Control "%s" does not exist', $controlName));
133
        }
134
135
        return new static(array_search($controlName, static::$controls, true));
0 ignored issues
show
Since $controls is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $controls to at least protected.
Loading history...
136
    }
137
}
138