1 <?php
  2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43 
 44 
 45  46  47  48  49  50  51  52  53  54  55  56 
 57 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
 58 {
 59      60  61  62  63 
 64     protected $mysql;
 65 
 66      67  68  69  70 
 71     protected $options;
 72 
 73      74  75  76  77 
 78     protected $id;
 79 
 80      81  82  83  84  85  86 
 87     public function __construct($location, $name, $type)
 88     {
 89         $this->options = array(
 90             'user' => null,
 91             'pass' => null,
 92             'host' => '127.0.0.1',
 93             'port' => '3306',
 94             'path' => '',
 95             'extras' => array(
 96                 'prefix' => '',
 97             ),
 98         );
 99         $this->options = array_merge_recursive($this->options, SimplePie_Cache::parse_URL($location));
100 
101         
102         $this->options['dbname'] = substr($this->options['path'], 1);
103 
104         try
105         {
106             $this->mysql = new PDO("mysql:dbname={$this->options['dbname']};host={$this->options['host']};port={$this->options['port']}", $this->options['user'], $this->options['pass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
107         }
108         catch (PDOException $e)
109         {
110             $this->mysql = null;
111             return;
112         }
113 
114         $this->id = $name . $type;
115 
116         if (!$query = $this->mysql->query('SHOW TABLES'))
117         {
118             $this->mysql = null;
119             return;
120         }
121 
122         $db = array();
123         while ($row = $query->fetchColumn())
124         {
125             $db[] = $row;
126         }
127 
128         if (!in_array($this->options['extras']['prefix'] . 'cache_data', $db))
129         {
130             $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))');
131             if ($query === false)
132             {
133                 $this->mysql = null;
134             }
135         }
136 
137         if (!in_array($this->options['extras']['prefix'] . 'items', $db))
138         {
139             $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))');
140             if ($query === false)
141             {
142                 $this->mysql = null;
143             }
144         }
145     }
146 
147     148 149 150 151 152 
153     public function save($data)
154     {
155         if ($this->mysql === null)
156         {
157             return false;
158         }
159 
160         if ($data instanceof SimplePie)
161         {
162             $data = clone $data;
163 
164             $prepared = self::prepare_simplepie_object_for_cache($data);
165 
166             $query = $this->mysql->prepare('SELECT COUNT(*) FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
167             $query->bindValue(':feed', $this->id);
168             if ($query->execute())
169             {
170                 if ($query->fetchColumn() > 0)
171                 {
172                     $items = count($prepared[1]);
173                     if ($items)
174                     {
175                         $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = :items, `data` = :data, `mtime` = :time WHERE `id` = :feed';
176                         $query = $this->mysql->prepare($sql);
177                         $query->bindValue(':items', $items);
178                     }
179                     else
180                     {
181                         $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `data` = :data, `mtime` = :time WHERE `id` = :feed';
182                         $query = $this->mysql->prepare($sql);
183                     }
184 
185                     $query->bindValue(':data', $prepared[0]);
186                     $query->bindValue(':time', time());
187                     $query->bindValue(':feed', $this->id);
188                     if (!$query->execute())
189                     {
190                         return false;
191                     }
192                 }
193                 else
194                 {
195                     $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:feed, :count, :data, :time)');
196                     $query->bindValue(':feed', $this->id);
197                     $query->bindValue(':count', count($prepared[1]));
198                     $query->bindValue(':data', $prepared[0]);
199                     $query->bindValue(':time', time());
200                     if (!$query->execute())
201                     {
202                         return false;
203                     }
204                 }
205 
206                 $ids = array_keys($prepared[1]);
207                 if (!empty($ids))
208                 {
209                     foreach ($ids as $id)
210                     {
211                         $database_ids[] = $this->mysql->quote($id);
212                     }
213 
214                     $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `id` = ' . implode(' OR `id` = ', $database_ids) . ' AND `feed_id` = :feed');
215                     $query->bindValue(':feed', $this->id);
216 
217                     if ($query->execute())
218                     {
219                         $existing_ids = array();
220                         while ($row = $query->fetchColumn())
221                         {
222                             $existing_ids[] = $row;
223                         }
224 
225                         $new_ids = array_diff($ids, $existing_ids);
226 
227                         foreach ($new_ids as $new_id)
228                         {
229                             if (!($date = $prepared[1][$new_id]->get_date('U')))
230                             {
231                                 $date = time();
232                             }
233 
234                             $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(:feed, :id, :data, :date)');
235                             $query->bindValue(':feed', $this->id);
236                             $query->bindValue(':id', $new_id);
237                             $query->bindValue(':data', serialize($prepared[1][$new_id]->data));
238                             $query->bindValue(':date', $date);
239                             if (!$query->execute())
240                             {
241                                 return false;
242                             }
243                         }
244                         return true;
245                     }
246                 }
247                 else
248                 {
249                     return true;
250                 }
251             }
252         }
253         else
254         {
255             $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
256             $query->bindValue(':feed', $this->id);
257             if ($query->execute())
258             {
259                 if ($query->rowCount() > 0)
260                 {
261                     $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = 0, `data` = :data, `mtime` = :time WHERE `id` = :feed');
262                     $query->bindValue(':data', serialize($data));
263                     $query->bindValue(':time', time());
264                     $query->bindValue(':feed', $this->id);
265                     if ($this->execute())
266                     {
267                         return true;
268                     }
269                 }
270                 else
271                 {
272                     $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:id, 0, :data, :time)');
273                     $query->bindValue(':id', $this->id);
274                     $query->bindValue(':data', serialize($data));
275                     $query->bindValue(':time', time());
276                     if ($query->execute())
277                     {
278                         return true;
279                     }
280                 }
281             }
282         }
283         return false;
284     }
285 
286     287 288 289 290 
291     public function load()
292     {
293         if ($this->mysql === null)
294         {
295             return false;
296         }
297 
298         $query = $this->mysql->prepare('SELECT `items`, `data` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
299         $query->bindValue(':id', $this->id);
300         if ($query->execute() && ($row = $query->fetch()))
301         {
302             $data = unserialize($row[1]);
303 
304             if (isset($this->options['items'][0]))
305             {
306                 $items = (int) $this->options['items'][0];
307             }
308             else
309             {
310                 $items = (int) $row[0];
311             }
312 
313             if ($items !== 0)
314             {
315                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
316                 {
317                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
318                 }
319                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
320                 {
321                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
322                 }
323                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
324                 {
325                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
326                 }
327                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
328                 {
329                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
330                 }
331                 else
332                 {
333                     $feed = null;
334                 }
335 
336                 if ($feed !== null)
337                 {
338                     $sql = 'SELECT `data` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :feed ORDER BY `posted` DESC';
339                     if ($items > 0)
340                     {
341                         $sql .= ' LIMIT ' . $items;
342                     }
343 
344                     $query = $this->mysql->prepare($sql);
345                     $query->bindValue(':feed', $this->id);
346                     if ($query->execute())
347                     {
348                         while ($row = $query->fetchColumn())
349                         {
350                             $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row);
351                         }
352                     }
353                     else
354                     {
355                         return false;
356                     }
357                 }
358             }
359             return $data;
360         }
361         return false;
362     }
363 
364     365 366 367 368 
369     public function mtime()
370     {
371         if ($this->mysql === null)
372         {
373             return false;
374         }
375 
376         $query = $this->mysql->prepare('SELECT `mtime` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
377         $query->bindValue(':id', $this->id);
378         if ($query->execute() && ($time = $query->fetchColumn()))
379         {
380             return $time;
381         }
382         else
383         {
384             return false;
385         }
386     }
387 
388     389 390 391 392 
393     public function touch()
394     {
395         if ($this->mysql === null)
396         {
397             return false;
398         }
399 
400         $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `mtime` = :time WHERE `id` = :id');
401         $query->bindValue(':time', time());
402         $query->bindValue(':id', $this->id);
403         if ($query->execute() && $query->rowCount() > 0)
404         {
405             return true;
406         }
407         else
408         {
409             return false;
410         }
411     }
412 
413     414 415 416 417 
418     public function unlink()
419     {
420         if ($this->mysql === null)
421         {
422             return false;
423         }
424 
425         $query = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
426         $query->bindValue(':id', $this->id);
427         $query2 = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :id');
428         $query2->bindValue(':id', $this->id);
429         if ($query->execute() && $query2->execute())
430         {
431             return true;
432         }
433         else
434         {
435             return false;
436         }
437     }
438 }
439