1<?php
2
3namespace Facebook\WebDriver\Remote;
4
5use Facebook\WebDriver\WebDriverBy;
6
7/**
8 * Compatibility layer between W3C's WebDriver and the legacy JsonWire protocol.
9 *
10 * @internal
11 */
12abstract class JsonWireCompat
13{
14    /**
15     * Element identifier defined in the W3C's WebDriver protocol.
16     *
17     * @see https://w3c.github.io/webdriver/webdriver-spec.html#elements
18     */
19    const WEB_DRIVER_ELEMENT_IDENTIFIER = 'element-6066-11e4-a52e-4f735466cecf';
20
21    public static function getElement(array $rawElement)
22    {
23        if (array_key_exists(self::WEB_DRIVER_ELEMENT_IDENTIFIER, $rawElement)) {
24            // W3C's WebDriver
25            return $rawElement[self::WEB_DRIVER_ELEMENT_IDENTIFIER];
26        }
27
28        // Legacy JsonWire
29        return $rawElement['ELEMENT'];
30    }
31
32    /**
33     * @param WebDriverBy $by
34     * @param bool $isW3cCompliant
35     *
36     * @return array
37     */
38    public static function getUsing(WebDriverBy $by, $isW3cCompliant)
39    {
40        $mechanism = $by->getMechanism();
41        $value = $by->getValue();
42
43        if ($isW3cCompliant) {
44            switch ($mechanism) {
45                // Convert to CSS selectors
46                case 'class name':
47                    $mechanism = 'css selector';
48                    $value = sprintf('.%s', self::escapeSelector($value));
49                    break;
50                case 'id':
51                    $mechanism = 'css selector';
52                    $value = sprintf('#%s', self::escapeSelector($value));
53                    break;
54                case 'name':
55                    $mechanism = 'css selector';
56                    $value = sprintf('[name=\'%s\']', self::escapeSelector($value));
57                    break;
58            }
59        }
60
61        return ['using' => $mechanism, 'value' => $value];
62    }
63
64    /**
65     * Escapes a CSS selector.
66     *
67     * Code adapted from the Zend Escaper project.
68     *
69     * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
70     * @see https://github.com/zendframework/zend-escaper/blob/master/src/Escaper.php
71     *
72     * @param string $selector
73     * @return string
74     */
75    private static function escapeSelector($selector)
76    {
77        return preg_replace_callback('/[^a-z0-9]/iSu', function ($matches) {
78            $chr = $matches[0];
79            if (mb_strlen($chr) === 1) {
80                $ord = ord($chr);
81            } else {
82                $chr = mb_convert_encoding($chr, 'UTF-32BE', 'UTF-8');
83                $ord = hexdec(bin2hex($chr));
84            }
85
86            return sprintf('\\%X ', $ord);
87        }, $selector);
88    }
89}
90