Completed
Push — master ( 9a76dc...c891c4 )
by Henrik
02:05
created

Crss   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 221
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 55.86%

Importance

Changes 7
Bugs 0 Features 3
Metric Value
wmc 19
c 7
b 0
f 3
lcom 1
cbo 0
dl 0
loc 221
ccs 62
cts 111
cp 0.5586
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 50 4
A clearRSS() 0 5 1
A connect() 0 22 3
A createDB() 0 4 1
A insertRSS() 0 5 1
B checkValidity() 0 27 4
B createRSS() 0 38 2
A getRSS() 0 14 3
1
<?php
2
3
namespace henaro\rss;
4
5
class Crss {
6
7
    private $table = 'RSSFeed';
8
    private $rssFile;
9
    private $valid = false;
10
    private $dbOptions = [];
11
    private $dbStructure;
12
    private $db;
13
    private $newsCount;
14
    private $feedDescription;
15
    private $sendHeader;
16
    /**
17
     * Initiates the class, takes parameters as input but should work with standard settings.
18
     * Connects to the DB and makes sure the table exists.
19
     * @param $params is the input to adjust standard settings. I recommend to change only the 'feedDescription' part.
20
     */
21 1
    public function __construct($params = [])
22
    {
23 1
        date_default_timezone_set('Europe/Stockholm');
24
        $options = [
25 1
            'rssFile' => REALPATH(__DIR__) . '/rsscache/rss.xml',
26 1
            'table' => $this->table,
27 1
            'newsCount' => 5,
28 1
            'sendHeader' => true,
29
            'db' => [
30 1
                'dsn' => 'sqlite:' . REALPATH(__DIR__) . '/src.sqlite',
31 1
                'username' => null,
32 1
                'password' => null,
33 1
                'driver_options' => null,
34
                'debug' => false
35 1
            ],
36
            'feedDescription' => [
37 1
                'title' => 'CRSS easy feed',
38 1
                'link' => 'http://www.github.com',
39
                'description' => 'Description of the amazing feed.'
40 1
            ]
41 1
        ];
42
43 1
        foreach ($params as $key => $value) {
44 1
            if (is_array($value)) {
45
                foreach ($value as $subKey => $subValue) {
46
                    $options[$key][$subKey] = $subValue;
47
                }
48
            } else {
49 1
                $options[$key] = $value;
50
            }
51 1
        }
52
53 1
        $this->rssFile = $options['rssFile'];
54 1
        $this->table = $options['table'];
55 1
        $this->dbOptions = $options['db'];
56 1
        $this->newsCount = $options['newsCount'];
57 1
        $this->feedDescription = $options['feedDescription'];
58 1
        $this->sendHeader = $options['sendHeader'];
59
60 1
        $this->dbStructure = 'CREATE TABLE IF NOT EXISTS ' . $this->table . ' (
61
            ID INTEGER PRIMARY KEY NOT NULL,
62
            TITLE CHAR(50) NOT NULL,
63
            LINK CHAR(50) NOT NULL,
64
            DESCRIPTION CHAR(255) NOT NULL,
65
            CREATED DATETIME
66 1
        )';
67
68 1
        $this->connect();
69 1
        $this->createDB();
70 1
    }
71
72
    /**
73
     * Function to clear the whole database from rss input
74
     *
75
     * @return void
76
     */
77 1
    public function clearRSS()
78
    {
79 1
        $stmt = $this->db->prepare("DELETE FROM " . $this->table);
80 1
        $stmt->execute();
81 1
    }
82
83
    /**
84
     * Internal function for connecting to the database
85
     *
86
     * @return void
87
     */
88 1
    private function connect()
89
    {
90
        try {
91 1
            $this->db = new \PDO(
92 1
                $this->dbOptions['dsn'],
93 1
                $this->dbOptions['username'],
94 1
                $this->dbOptions['password'],
95 1
                $this->dbOptions['driver_options']
96 1
            );
97
98 1
        } catch (\Exception $e) {
99
            //Change to true to debug database connection
100
            if ($this->dbOptions['debug']) {
101
                // For debug purpose, shows all connection details
102
                throw $e;
103
            } else {
104
                // Hide connection details.
105
                throw new \PDOException("Could not connect to database, hiding connection details.");
106
            }
107
        }
108 1
        $this->db->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
109 1
    }
110
111 1
    public function createDB() {
112 1
        $stmt = $this->db->prepare($this->dbStructure);
113 1
        $stmt->execute();
114 1
    }
115
116
    /**
117
     * Compares RSS file created timestamp and database timestamp to judge if new RSS file is needed
118
     *
119
     * Sets internal variable $this->valid to true/false depending if new file needs to be generate
120
     * @return void
121
     */
122 1
    private function checkValidity()
123
    {
124
125 1
        if (!is_writable($this->rssFile)) {
126 1
            $this->valid = false;
127 1
            return;
128
        }
129
130
        $stmt = $this->db->prepare('SELECT CREATED FROM ' . $this->table . ' ORDER BY CREATED DESC LIMIT 1');
131
        $stmt->execute();
132
        $res = $stmt->fetchAll();
133
134
        if (count($res) == 0) {
135
            $this->valid = false;
136
            return;
137
        }
138
139
        $latestInput = strtotime($res[0]->CREATED);
140
141
        $rssCreated = filemtime($this->rssFile);
142
143
        if ($latestInput > $rssCreated) {
144
            $this->valid = false;
145
        } else {
146
            $this->valid = true;
147
        }
148
    }
149
150
    /**
151
     * Creates a new RSS File with information from the database. Max amount of news is configured in the initiation.
152
     *
153
     * @return void
154
     */
155 1
    private function createRSS()
156
    {
157 1
        $file = fopen($this->rssFile, "w+");
158
159
        $stmt = $this->db->prepare('SELECT * FROM ' . $this->table . ' ORDER BY CREATED DESC LIMIT ?');
160
        $stmt->execute([$this->newsCount]);
161
        $res = $stmt->fetchAll();
162
163
        $xmlVersion = '<?xml version="1.0" encoding="UTF-8" ?>';
164
165
        $startString = <<<EOD
166
{$xmlVersion}
167
<rss version="2.0">
168
<channel>
169
    <title>{$this->feedDescription['title']}</title>
170
    <link>{$this->feedDescription['link']}</link>
171
    <description>{$this->feedDescription['description']}</description>
172
EOD;
173
        fwrite($file, $startString);
174
175
        foreach ($res as $post) {
176
            $date = date("D, d M y H:i:s O", strtotime($post->CREATED));
177
            $string = <<<EOD
178
179
    <item>
180
        <title>{$post->TITLE}</title>
181
        <link>{$post->LINK}</link>
182
        <description>{$post->DESCRIPTION}</description>
183
        <pubDate>{$date}</pubDate>
184
    </item>
185
EOD;
186
            fwrite($file, $string);
187
        }
188
189
        fwrite($file, '
190
</channel>
191
</rss>');
192
    }
193
194
    /**
195
     * Function that should be called to receive the RSS feed.
196
     * Checks if the latest RSS File is up to date, if not, generates a new one.
197
     * @return void
198
     */
199 1
    public function getRSS()
200
    {
201 1
        $this->checkValidity();
202
203 1
        if (!$this->valid) {
204 1
            $this->createRSS();
205
        }
206
207
        if ($this->sendHeader) {
208
            header('Content-type: application/rss+xml; charset=UTF-8');
209
        }
210
        
211
        readfile($this->rssFile);
212
    }
213
214
    /**
215
     * Inserts information to RSS database
216
     * @param $input should be an associative array with three pars TITLE, LINK, DESCRIPTION
217
     *
218
     * @return void
219
     */
220 1
    public function insertRSS($input = [])
221
    {
222 1
        $stmt = $this->db->prepare("INSERT INTO  " . $this->table . " (TITLE, LINK, DESCRIPTION, CREATED) VALUES (?, ?, ?, datetime('now', 'localtime'))");
223 1
        $stmt->execute([$input['TITLE'], $input['LINK'], $input['DESCRIPTION']]);
224 1
    }
225
}
226