DatePicker   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 132
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 13
c 0
b 0
f 0
lcom 1
cbo 3
dl 0
loc 132
ccs 0
cts 36
cp 0
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 2
A setDate() 0 7 1
A isDateSelected() 0 20 3
A isDateAvailable() 0 12 3
A execute() 0 4 1
A datePicker() 0 9 2
A jsDate() 0 4 1
1
<?php
2
/**
3
 * @author Sergii Bondarenko, <[email protected]>
4
 */
5
namespace Drupal\TqExtension\Utils;
6
7
// Contexts.
8
use Drupal\TqExtension\Context\RawTqContext;
9
// Helpers.
10
use Behat\DebugExtension\Debugger;
11
use Behat\Mink\Element\NodeElement;
12
13
class DatePicker
14
{
15
    use Debugger;
16
17
    /**
18
     * @var NodeElement
19
     */
20
    private $element;
21
    /**
22
     * @var string
23
     */
24
    private $date = '';
25
    /**
26
     * @var RawTqContext
27
     */
28
    private $context;
29
30
    /**
31
     * @param RawTqContext $context
32
     *   Behat context.
33
     * @param string $selector
34
     *   Element selector.
35
     * @param string $date
36
     *   Human-readable date.
37
     */
38
    public function __construct(RawTqContext $context, $selector, $date)
39
    {
40
        $this->context = $context;
41
42
        if (null === $this->execute('$.fn.datepicker')) {
43
            throw new \RuntimeException('jQuery DatePicker is not available on the page.');
44
        }
45
46
        $this->element = $this->context->element('*', $selector);
47
        $this->date = self::jsDate($date);
48
    }
49
50
    /**
51
     * @return self
52
     */
53
    public function setDate()
54
    {
55
        // @todo setDate will not work if browser window is not active.
56
        $this->datePicker([__FUNCTION__, '<date>']);
57
58
        return $this;
59
    }
60
61
    /**
62
     * @throws \Exception
63
     *
64
     * @return self
65
     */
66
    public function isDateSelected()
67
    {
68
        $value = $this->datePicker(['getDate']);
69
        $initial = $this->execute($this->date);
70
71
        // By some reasons DatePicker could not return a date using "getDate" method
72
        // and we'll try to use it from input value directly. An issue could occur
73
        // after saving the form and/or reloading the page.
74
        if (empty($value)) {
75
            $value = $this->execute(self::jsDate($this->element->getValue()));
76
        }
77
78
        self::debug(['Comparing "%s" with "%s".'], [$value, $initial]);
79
80
        if ($value !== $initial) {
81
            throw new \Exception(sprintf('DatePicker contains the "%s" but should "%s".', $value, $initial));
82
        }
83
84
        return $this;
85
    }
86
87
    /**
88
     * @throws \Exception
89
     *
90
     * @return self
91
     */
92
    public function isDateAvailable()
93
    {
94
        // @todo For now, any out of scope variable inside of "beforeShowDay" method will be undefined.
95
        // @link https://github.com/refactoror/SelBlocks/issues/5#issuecomment-68511965
96
        $beforeShowDay = $this->datePicker(['option', 'beforeShowDay']);
97
98
        if (!empty($beforeShowDay) && !empty($this->execute("$beforeShowDay($this->date)")[0])) {
99
            throw new \Exception(sprintf('The "%s" is not available for choosing.', $this->date));
100
        }
101
102
        return $this;
103
    }
104
105
    /**
106
     * @param string $javascript
107
     *   JS code for execution.
108
     *
109
     * @return mixed
110
     *   Result of JS execution.
111
     */
112
    private function execute($javascript)
113
    {
114
        return $this->context->executeJs("return $javascript;");
115
    }
116
117
    /**
118
     * @param array $arguments
119
     *   jQuery.fn.datepicker arguments.
120
     *
121
     * @return mixed
122
     *   Result of JS execution.
123
     */
124
    private function datePicker(array $arguments)
125
    {
126
        return $this->context->executeJsOnElement($this->element, sprintf(
127
            "return jQuery({{ELEMENT}}).datepicker(%s);",
128
            implode(', ', array_map(function ($value) {
129
                return in_array($value, ['<date>']) ? $this->date : "'$value'";
130
            }, $arguments))
131
        ));
132
    }
133
134
    /**
135
     * @param string $date
136
     *   The string to parse.
137
     *
138
     * @return string
139
     */
140
    private static function jsDate($date)
141
    {
142
        return sprintf("new Date('%s')", date('c', strtotime($date)));
143
    }
144
}
145