domCalendar   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 63
c 1
b 0
f 0
dl 0
loc 106
rs 10
wmc 24

9 Methods

Rating   Name   Duplication   Size   Complexity  
A buildCalendarFromDom() 0 7 1
A buildCalendar() 0 7 3
A removeTags() 0 7 3
A getHolidays() 0 5 2
A getMonthWeekendDays() 0 17 5
A __construct() 0 2 1
A buildMonth() 0 11 2
A getMonthPreNoworkholidays() 0 15 4
A isDay() 0 2 3
1
<?php
2
3
namespace Inok\ruCalendar;
4
5
use DOMDocument;
6
use DOMNode;
7
use DOMXPath;
8
9
class domCalendar
10
{
11
  private $content;
12
  /** @var DOMXPath */
13
  private $xPath;
14
15
  private $holidays = null;
16
17
  /***** DOM XPath Queries *****/
18
  private $xpathMonths = '//table[@class="cal"]';
19
  private $xpathMonthInfo = './thead/tr/th[@class="month"]';
20
  private $xpathPreholidays = './tbody/tr/td[@class="preholiday"]';
21
  private $xpathNoworkdays = './tbody/tr/td[@class="nowork"]';
22
  private $xpathWeekends = './tbody/tr/td[contains(@class, "weekend")]';
23
24
  public function __construct(string $content) {
25
    $this->content = $content;
26
  }
27
28
  public function getHolidays(): array {
29
    if (is_null($this->holidays)) {
30
      $this->buildCalendarFromDom();
31
    }
32
    return $this->holidays;
33
  }
34
35
  private function buildCalendarFromDom() {
36
    $this->holidays = [];
37
    libxml_use_internal_errors(true);
38
    $domDocument = new DOMDocument();
39
    $domDocument->loadHTML($this->content);
40
    $this->xPath = new DOMXPath($domDocument);
41
    $this->buildCalendar();
42
  }
43
44
  private function buildCalendar() {
45
    $months = $this->xPath->query($this->xpathMonths);
46
    if (!count($months)) {
47
      return;
48
    }
49
    foreach ($months as $month) {
50
      $this->buildMonth($month);
51
    }
52
  }
53
54
  private function buildMonth(DOMNode $month) {
55
    $monthInfo = $this->xPath->query($this->xpathMonthInfo, $month);
56
    if (!count($monthInfo)) {
57
      return;
58
    }
59
    $weekendDays = $this->getMonthWeekendDays($month);
60
    $this->holidays[] = ["month" => $monthInfo[0]->nodeValue,
61
                         "preholidays" => $this->getMonthPreNoworkholidays($month, $this->xpathPreholidays),
62
                         "noworkdays" => $this->getMonthPreNoworkholidays($month, $this->xpathNoworkdays),
63
                         "holidays" => $weekendDays["holidays"],
64
                         "weekends" => $weekendDays["weekends"]];
65
  }
66
67
  private function getMonthPreNoworkholidays(DOMNode $month, string $query): array {
68
    $days = $this->xPath->query($query, $month);
69
    if (!count($days)) {
70
      return [];
71
    }
72
    $daysList = [];
73
    foreach ($days as $day) {
74
      $this->removeTags($day);
75
      $dayInfo = $day->nodeValue;
76
      if (!$this->isDay($dayInfo)) {
77
        continue;
78
      }
79
      $daysList[] = (int) $dayInfo;
80
    }
81
    return $daysList;
82
  }
83
84
  private function getMonthWeekendDays(DOMNode $month): array {
85
    $daysList = ["weekends" => [],
86
                 "holidays" => []];
87
    $days = $this->xPath->query($this->xpathWeekends, $month);
88
    if (!count($days)) {
89
      return $daysList;
90
    }
91
    foreach ($days as $day) {
92
      $this->removeTags($day);
93
      $dayInfo = $day->nodeValue;
94
      if (!$this->isDay($dayInfo)) {
95
        continue;
96
      }
97
      $wClasses = explode(' ', $day->getAttribute('class'));
98
      $daysList[(in_array('holiday', $wClasses)) ? "holidays" : "weekends"][] = (int) $dayInfo;
99
    }
100
    return $daysList;
101
  }
102
103
  private function removeTags(DOMNode &$day) {
104
    $tags = $this->xPath->query('*', $day);
105
    if (!count($tags)) {
106
      return;
107
    }
108
    foreach ($tags as $tag) {
109
      $day->removeChild($tag);
110
    }
111
  }
112
113
  private function isDay($day): bool {
114
    return (is_numeric($day) && $day > 0 && $day < 32);
115
  }
116
}
117