Completed
Pull Request — master (#16)
by Sergii
04:07
created

JQuery::datePicker()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 6
nc 1
nop 1
1
<?php
2
/**
3
 * @author Sergii Bondarenko, <[email protected]>
4
 */
5
namespace Drupal\TqExtension\Utils\DatePicker;
6
7
class JQuery extends DatePickerBase
8
{
9
    const DATE_ADJUSTER = 'window.__behatDatePickerDateAdjuster';
10
11
    /**
12
     * {@inheritdoc}
13
     */
14
    public function setDate()
15
    {
16
        // @todo setDate will not work if browser window is not active.
17
        $this->datePicker([__FUNCTION__, '<date>']);
18
19
        return $this;
20
    }
21
22
    /**
23
     * {@inheritdoc}
24
     */
25
    public function isDateSelected()
26
    {
27
        $value = $this->datePicker(['getDate']);
28
        $initial = $this->execute($this->date);
29
30
        // By some reasons DatePicker could not return a date using "getDate" method
31
        // and we'll try to use it from input value directly. An issue could occur
32
        // after saving the form and/or reloading the page.
33
        if (empty($value)) {
34
            $value = $this->execute(self::jsDate($this->element->getValue()));
35
        } else {
36
            $value = $this->adjustTimezone($value);
37
        }
38
39
        self::debug(['Comparing "%s" with "%s".'], [$value, $initial]);
40
41
        if ($value !== $initial) {
42
            throw new \Exception(sprintf('DatePicker contains the "%s" but should "%s".', $value, $initial));
43
        }
44
45
        return $this;
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function isDateAvailable()
52
    {
53
        // @todo For now, any out of scope variable inside of "beforeShowDay" method will be undefined.
54
        // @link https://github.com/refactoror/SelBlocks/issues/5#issuecomment-68511965
55
        $beforeShowDay = $this->datePicker(['option', 'beforeShowDay']);
56
57
        if (!empty($beforeShowDay) && !empty($this->execute("$beforeShowDay($this->date)")[0])) {
58
            throw new \Exception(sprintf('The "%s" is not available for choosing.', $this->date));
59
        }
60
61
        return $this;
62
    }
63
64
    /**
65
     * @param array $arguments
66
     *   jQuery.fn.datepicker arguments.
67
     *
68
     * @return mixed
69
     *   Result of JS execution.
70
     */
71
    private function datePicker(array $arguments)
72
    {
73
        return $this->context->executeJsOnElement($this->element, sprintf(
74
            "return jQuery({{ELEMENT}}).datepicker(%s);",
75
            implode(', ', array_map(function ($value) {
76
                return in_array($value, ['<date>']) ? $this->date : "'$value'";
77
            }, $arguments))
78
        ));
79
    }
80
81
    /**
82
     * Adjust timezone of date returned by DatePicker.
83
     *
84
     * @param string $date
85
     *   Date returned by "jQuery('#selector').datepicker('getDate')".
86
     *
87
     * @return string
88
     *   Date with correct timezone.
89
     *
90
     * @link http://stackoverflow.com/a/31560608
91
     */
92
    private function adjustTimezone($date)
93
    {
94
        $session = $this->context->getSession();
95
96
        $session->executeScript(sprintf(
97
            '%s=%s;%1$s.setMinutes(%1$s.getMinutes()-%1$s.getTimezoneOffset());',
98
            self::DATE_ADJUSTER,
99
            self::jsDate($date)
100
        ));
101
102
        return $session->evaluateScript(self::DATE_ADJUSTER);
103
    }
104
}
105