Passed
Branch master (0074a9)
by Jakub
01:45
created

Generator::generate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 22
ccs 16
cts 16
cp 1
rs 9.2
cc 3
eloc 17
nc 3
nop 0
crap 3
1
<?php
2
declare(strict_types=1);
3
4
namespace Nexendrie\Rss;
5
6
/**
7
 * RSS Channel Generator
8
 *
9
 * @author Jakub Konečný
10
 * @property string $title
11
 * @property string $description
12
 * @property string $link
13
 * @property callable $dataSource
14
 * @property int $shortenDescription
15
 * @property string $dateTimeFormat
16
 * @property callable $lastBuildDate
17
 */
18 1
class Generator {
19 1
  use \Nette\SmartObject;
20
  
21
  /** @var string */
22
  protected $title = "";
23
  /** @var string */
24
  protected $description = "";
25
  /** @var string */
26
  protected $link = "";
27
  /** @var string */
28
  protected $dateTimeFormat = "Y-m-d H:i:s";
29
  /** @var callable|null */
30
  protected $dataSource = NULL;
31
  /** @var int */
32
  protected $shortenDescription = 150;
33
  /** @var callable */
34
  protected $lastBuildDate = "time";
35
  
36
  public function getTitle(): string {
37 1
    return $this->title;
38
  }
39
  
40
  public function setTitle(string $title) {
41 1
    $this->title = $title;
42 1
  }
43
  
44
  public function getDescription(): string {
45 1
    return $this->description;
46
  }
47
  
48
  public function setDescription(string $description) {
49 1
    $this->description = $description;
50 1
  }
51
  
52
  public function getLink(): string {
53 1
    return $this->link;
54
  }
55
  
56
  public function setLink(string $link) {
57 1
    $this->link = $link;
58 1
  }
59
  
60
  public function setDataSource(callable $dataSource) {
61 1
    $this->dataSource = $dataSource;
62 1
  }
63
  
64
  public function getShortenDescription(): int {
65 1
    return $this->shortenDescription;
66
  }
67
  
68
  public function setShortenDescription(int $value) {
69 1
    $this->shortenDescription = $value;
70 1
  }
71
  
72
  public function getDateTimeFormat(): string {
73 1
    return $this->dateTimeFormat;
74
  }
75
  
76
  public function setDateTimeFormat(string $format) {
77 1
    $this->dateTimeFormat = $format;
78 1
  }
79
  
80
  public function getLastBuildDate() {
81 1
    return $this->lastBuildDate;
82
  }
83
  
84
  public function setLastBuildDate(callable $lastBuildDate) {
85 1
    $this->lastBuildDate = $lastBuildDate;
86 1
  }
87
  
88
  /**
89
   * @throws InvalidStateException
90
   * @throws \InvalidArgumentException
91
   */
92
  protected function getData(): Collection {
93 1
    if(is_null($this->dataSource)) {
94 1
      throw new InvalidStateException("Data source for RSS generator is not set.");
95
    }
96 1
    $items = call_user_func($this->dataSource);
97 1
    if(!$items instanceof Collection) {
98 1
      throw new \InvalidArgumentException("Callback for data source for RSS generator has to return " . Collection::class . ".");
0 ignored issues
show
introduced by
Line exceeds 120 characters; contains 129 characters
Loading history...
99
    }
100 1
    return $items;
101
  }
102
  
103
  protected function shortenDescription(string $description): string {
104 1
    if($this->shortenDescription < 1) {
105 1
      return $description;
106
    }
107 1
    $originalDescription = $description;
108 1
    $description = substr($description, 0, $this->shortenDescription);
109 1
    if($description !== $originalDescription) {
110 1
      $description .= "...";
111
    }
112 1
    return $description;
113
  }
114
  
115
  protected function writeProperty(\SimpleXMLElement &$channel, string $property): void {
116 1
    if(isset($this->$property) AND $this->$property !== "") {
117 1
      $channel->channel->{$property}[0][0] = $this->$property;
118
    }
119 1
  }
120
  
121
  /**
122
   * @throws InvalidStateException
123
   * @throws \InvalidArgumentException
124
   */
125
  public function generate(): \SimpleXMLElement {
126 1
    $items = $this->getData();
127 1
    $lastBuildDate = call_user_func($this->lastBuildDate);
128 1
    if(!is_int($lastBuildDate)) {
129 1
      throw new \InvalidArgumentException("Callback for last build date for RSS generator has to return integer.");
130
    }
131 1
    $channel = simplexml_load_file(__DIR__ . "/template.xml");
132 1
    $channel->channel->lastBuildDate[0][0] = date($this->dateTimeFormat, $lastBuildDate);
133 1
    $this->writeProperty($channel, "link");
134 1
    $this->writeProperty($channel, "title");
135 1
    $this->writeProperty($channel, "description");
136
    /** @var RssChannelItem $item */
137 1
    foreach($items as $item) {
138
      /** @var \SimpleXMLElement $i */
139 1
      $i = $channel->channel->addChild("item");
140 1
      $i->addChild("title", $item->title);
141 1
      $i->addChild("link", $item->link);
142 1
      $i->addChild("pubDate", $item->pubDate);
143 1
      $i->addChild("description", $this->shortenDescription($item->description));
144
    }
145 1
    return $channel;
146
  }
147
  
148
  /**
149
   * @throws InvalidStateException
150
   * @throws \InvalidArgumentException
151
   */
152
  public function response(): RssResponse {
153
    try {
154 1
      return new RssResponse($this->generate());
155 1
    } catch(InvalidStateException | \InvalidArgumentException $e) {
156 1
      throw $e;
157
    }
158
  }
159
}
160
?>