1<?php
2/**
3 * SimplePie
4 *
5 * A PHP-Based RSS and Atom Feed Framework.
6 * Takes the hard work out of managing a complete RSS/Atom solution.
7 *
8 * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without modification, are
12 * permitted provided that the following conditions are met:
13 *
14 * 	* Redistributions of source code must retain the above copyright notice, this list of
15 * 	  conditions and the following disclaimer.
16 *
17 * 	* Redistributions in binary form must reproduce the above copyright notice, this list
18 * 	  of conditions and the following disclaimer in the documentation and/or other materials
19 * 	  provided with the distribution.
20 *
21 * 	* Neither the name of the SimplePie Team nor the names of its contributors may be used
22 * 	  to endorse or promote products derived from this software without specific prior
23 * 	  written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * @package SimplePie
36 * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue
37 * @author Ryan Parman
38 * @author Sam Sneddon
39 * @author Ryan McCue
40 * @link http://simplepie.org/ SimplePie
41 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42 */
43
44/**
45 * Caches data to memcached
46 *
47 * Registered for URLs with the "memcached" protocol
48 *
49 * For example, `memcached://localhost:11211/?timeout=3600&prefix=sp_` will
50 * connect to memcached on `localhost` on port 11211. All tables will be
51 * prefixed with `sp_` and data will expire after 3600 seconds
52 *
53 * @package    SimplePie
54 * @subpackage Caching
55 * @author     Paul L. McNeely
56 * @uses       Memcached
57 */
58class SimplePie_Cache_Memcached implements SimplePie_Cache_Base
59{
60    /**
61     * Memcached instance
62     * @var Memcached
63     */
64    protected $cache;
65
66    /**
67     * Options
68     * @var array
69     */
70    protected $options;
71
72    /**
73     * Cache name
74     * @var string
75     */
76    protected $name;
77
78    /**
79     * Create a new cache object
80     * @param string $location Location string (from SimplePie::$cache_location)
81     * @param string $name     Unique ID for the cache
82     * @param string $type     Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
83     */
84    public function __construct($location, $name, $type) {
85        $this->options = array(
86            'host'   => '127.0.0.1',
87            'port'   => 11211,
88            'extras' => array(
89                'timeout' => 3600, // one hour
90                'prefix'  => 'simplepie_',
91            ),
92        );
93        $this->options = SimplePie_Misc::array_merge_recursive($this->options, SimplePie_Cache::parse_URL($location));
94
95        $this->name = $this->options['extras']['prefix'] . md5("$name:$type");
96
97        $this->cache = new Memcached();
98        $this->cache->addServer($this->options['host'], (int)$this->options['port']);
99    }
100
101    /**
102     * Save data to the cache
103     * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
104     * @return bool Successfulness
105     */
106    public function save($data) {
107        if ($data instanceof SimplePie) {
108            $data = $data->data;
109        }
110
111        return $this->setData(serialize($data));
112    }
113
114    /**
115     * Retrieve the data saved to the cache
116     * @return array Data for SimplePie::$data
117     */
118    public function load() {
119        $data = $this->cache->get($this->name);
120
121        if ($data !== false) {
122            return unserialize($data);
123        }
124        return false;
125    }
126
127    /**
128     * Retrieve the last modified time for the cache
129     * @return int Timestamp
130     */
131    public function mtime() {
132        $data = $this->cache->get($this->name . '_mtime');
133        return (int) $data;
134    }
135
136    /**
137     * Set the last modified time to the current time
138     * @return bool Success status
139     */
140    public function touch() {
141        $data = $this->cache->get($this->name);
142        return $this->setData($data);
143    }
144
145    /**
146     * Remove the cache
147     * @return bool Success status
148     */
149    public function unlink() {
150        return $this->cache->delete($this->name, 0);
151    }
152
153    /**
154     * Set the last modified time and data to Memcached
155     * @return bool Success status
156     */
157    private function setData($data) {
158
159        if ($data !== false) {
160            $this->cache->set($this->name . '_mtime', time(), (int)$this->options['extras']['timeout']);
161            return $this->cache->set($this->name, $data, (int)$this->options['extras']['timeout']);
162        }
163
164        return false;
165    }
166}
167