Completed
Push — master ( 24d9ce...08c521 )
by Henrik
01:53
created

Crss::clearRSS()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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