1<?php
2
3namespace Facebook\WebDriver;
4
5/**
6 * Representations of pressable keys that aren't text.
7 * These are stored in the Unicode PUA (Private Use Area) code points.
8 * @see https://w3c.github.io/webdriver/#keyboard-actions
9 */
10class WebDriverKeys
11{
12    const NULL = "\xEE\x80\x80";
13    const CANCEL = "\xEE\x80\x81";
14    const HELP = "\xEE\x80\x82";
15    const BACKSPACE = "\xEE\x80\x83";
16    const TAB = "\xEE\x80\x84";
17    const CLEAR = "\xEE\x80\x85";
18    const RETURN_KEY = "\xEE\x80\x86";
19    const ENTER = "\xEE\x80\x87";
20    const SHIFT = "\xEE\x80\x88";
21    const CONTROL = "\xEE\x80\x89";
22    const ALT = "\xEE\x80\x8A";
23    const PAUSE = "\xEE\x80\x8B";
24    const ESCAPE = "\xEE\x80\x8C";
25    const SPACE = "\xEE\x80\x8D";
26    const PAGE_UP = "\xEE\x80\x8E";
27    const PAGE_DOWN = "\xEE\x80\x8F";
28    const END = "\xEE\x80\x90";
29    const HOME = "\xEE\x80\x91";
30    const ARROW_LEFT = "\xEE\x80\x92";
31    const ARROW_UP = "\xEE\x80\x93";
32    const ARROW_RIGHT = "\xEE\x80\x94";
33    const ARROW_DOWN = "\xEE\x80\x95";
34    const INSERT = "\xEE\x80\x96";
35    const DELETE = "\xEE\x80\x97";
36    const SEMICOLON = "\xEE\x80\x98";
37    const EQUALS = "\xEE\x80\x99";
38    const NUMPAD0 = "\xEE\x80\x9A";
39    const NUMPAD1 = "\xEE\x80\x9B";
40    const NUMPAD2 = "\xEE\x80\x9C";
41    const NUMPAD3 = "\xEE\x80\x9D";
42    const NUMPAD4 = "\xEE\x80\x9E";
43    const NUMPAD5 = "\xEE\x80\x9F";
44    const NUMPAD6 = "\xEE\x80\xA0";
45    const NUMPAD7 = "\xEE\x80\xA1";
46    const NUMPAD8 = "\xEE\x80\xA2";
47    const NUMPAD9 = "\xEE\x80\xA3";
48    const MULTIPLY = "\xEE\x80\xA4";
49    const ADD = "\xEE\x80\xA5";
50    const SEPARATOR = "\xEE\x80\xA6";
51    const SUBTRACT = "\xEE\x80\xA7";
52    const DECIMAL = "\xEE\x80\xA8";
53    const DIVIDE = "\xEE\x80\xA9";
54    const F1 = "\xEE\x80\xB1";
55    const F2 = "\xEE\x80\xB2";
56    const F3 = "\xEE\x80\xB3";
57    const F4 = "\xEE\x80\xB4";
58    const F5 = "\xEE\x80\xB5";
59    const F6 = "\xEE\x80\xB6";
60    const F7 = "\xEE\x80\xB7";
61    const F8 = "\xEE\x80\xB8";
62    const F9 = "\xEE\x80\xB9";
63    const F10 = "\xEE\x80\xBA";
64    const F11 = "\xEE\x80\xBB";
65    const F12 = "\xEE\x80\xBC";
66    const META = "\xEE\x80\xBD";
67    const ZENKAKU_HANKAKU = "\xEE\x80\xC0";
68    const RIGHT_SHIFT = "\xEE\x81\x90";
69    const RIGHT_CONTROL = "\xEE\x81\x91";
70    const RIGHT_ALT = "\xEE\x81\x92";
71    const RIGHT_META = "\xEE\x81\x93";
72    const NUMPAD_PAGE_UP = "\xEE\x81\x94";
73    const NUMPAD_PAGE_DOWN = "\xEE\x81\x95";
74    const NUMPAD_END = "\xEE\x81\x96";
75    const NUMPAD_HOME = "\xEE\x81\x97";
76    const NUMPAD_ARROW_LEFT = "\xEE\x81\x98";
77    const NUMPAD_ARROW_UP = "\xEE\x81\x99";
78    const NUMPAD_ARROW_RIGHT = "\xEE\x81\x9A";
79    const NUMPAD_ARROW_DOWN = "\xEE\x81\x9B";
80    const NUMPAD_ARROW_INSERT = "\xEE\x81\x9C";
81    const NUMPAD_ARROW_DELETE = "\xEE\x81\x9D";
82    // Aliases
83    const LEFT_SHIFT = self::SHIFT;
84    const LEFT_CONTROL = self::CONTROL;
85    const LEFT_ALT = self::ALT;
86    const LEFT = self::ARROW_LEFT;
87    const UP = self::ARROW_UP;
88    const RIGHT = self::ARROW_RIGHT;
89    const DOWN = self::ARROW_DOWN;
90    const COMMAND = self::META;
91
92    /**
93     * Encode input of `sendKeys()` to appropriate format according to protocol.
94     *
95     * @param string|array|int|float $keys
96     * @param bool $isW3cCompliant
97     * @return array|string
98     */
99    public static function encode($keys, $isW3cCompliant = false)
100    {
101        if (is_numeric($keys)) {
102            $keys = (string) $keys;
103        }
104
105        if (is_string($keys)) {
106            $keys = [$keys];
107        }
108
109        if (!is_array($keys)) {
110            if (!$isW3cCompliant) {
111                return [];
112            }
113
114            return '';
115        }
116
117        $encoded = [];
118        foreach ($keys as $key) {
119            if (is_array($key)) {
120                // handle key modifiers
121                $key = implode('', $key) . self::NULL; // the NULL clears the input state (eg. previous modifiers)
122            }
123            $encoded[] = (string) $key;
124        }
125
126        if (!$isW3cCompliant) {
127            return $encoded;
128        }
129
130        return implode('', $encoded);
131    }
132}
133