PluginProbe
Webling / 3.2.0
Webling v3.2.0
trunk 2.0 3.0 3.0.1 3.0.2 3.0.3 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.3.0 3.4.0 3.4.1 3.5.0 3.6.0 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.9.0 3.9.1 3.9.2
webling / src / WeblingAPI / WordpressCache.php

WordpressCache.php in Webling 3.2.0, at src/WeblingAPI/WordpressCache.php

186 lines 4.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Webling\Cache;
4
5 use Webling\API\IClient;
6
7 class WordpressCache implements ICache {
8
9 public static $TABLE_NAME = 'webling_cache';
10
11 // seconds to wait until next /replicate call is made
12 public static $PAUSE_BETWEEN_SYNC = 60;
13
14 protected $client;
15
16 protected $options;
17
18 function __construct(IClient $client, $options = []) {
19 global $wpdb;
20
21 if (get_class($wpdb) != 'wpdb') {
22 throw new CacheException('Not in Wordpress Context!');
23 }
24
25 $this->client = $client;
26 $this->options = $options;
27
28 $this->updateCache();
29 }
30
31 public function updateCache() {
32
33 $cache_state = get_option('webling-cache-state');
34
35 if ($cache_state) {
36 if (isset($cache_state['revision'])) {
37 if (isset($cache_state['timestamp'])) {
38 if ($cache_state['timestamp'] > time() - self::$PAUSE_BETWEEN_SYNC) {
39 // wait a bit more for the next replication
40 return;
41 }
42 }
43 $replicate = $this->client->get('/replicate/'.$cache_state['revision'])->getData();
44 if (isset($replicate['revision'])) {
45
46 // delete cached objects
47 foreach ($replicate['objects'] as $objCategory) {
48 foreach ($objCategory as $obj) {
49 $this->deleteObjectCache($obj);
50 }
51 }
52
53 // delete all root cache objects if the revision has changed
54 // this could be done more efficient, but lets keep it simple for simplicity
55 if ($cache_state['revision'] != $replicate['revision']) {
56 $this->deleteRootCache();
57 }
58
59 // update cache state
60 $cache_state['revision'] = $replicate['revision'];
61 $cache_state['timestamp'] = time();
62 update_option('webling-cache-state', $cache_state);
63
64 } else {
65 $this->clearCache();
66 throw new CacheException('Error in replication. No revision found.');
67 }
68 return;
69 }
70 }
71
72 // write initial cache state
73 $replicate = $this->client->get('/replicate')->getData();
74 if (isset($replicate['revision'])) {
75 $data = [
76 'revision' => $replicate['revision'],
77 'timestamp' => time(),
78 ];
79 update_option('webling-cache-state', $data);
80 }
81 }
82
83 public function clearCache() {
84 global $wpdb;
85 $wpdb->get_row("TRUNCATE {$wpdb->prefix}" . self::$TABLE_NAME);
86 $this->deleteRootCache();
87 update_option('webling-cache-state', null);
88 return;
89 }
90
91 public function getObject($type, $objectId) {
92 $cached = $this->getObjectCache($objectId);
93 if ($cached != null) {
94 return json_decode($cached, true);
95 } else {
96 $response = $this->client->get($type.'/'.$objectId);
97
98 // only cache 2XX responses
99 if ($response->getStatusCode() <= 200 && $response->getStatusCode() < 300) {
100 $data = $response->getData();
101 $this->setObjectCache($objectId, $data);
102 return $data;
103 } else {
104 return null;
105 }
106 }
107 }
108
109 public function getRoot($type) {
110 $type = preg_replace('/[^a-z]/i', '', strtolower($type));
111 $cached = $this->getRootCache($type);
112 if ($cached != null) {
113 return json_decode($cached, true);
114 } else {
115 $response = $this->client->get($type);
116
117 // only cache 2XX responses
118 if ($response->getStatusCode() <= 200 && $response->getStatusCode() < 300) {
119 $data = $response->getData();
120 $this->setRootCache($type, $data);
121 return $data;
122 } else {
123 return null;
124 }
125 }
126 }
127
128 private function getObjectCache($id) {
129 global $wpdb;
130
131 $id = intval($id);
132 $entry = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}" . self::$TABLE_NAME . ' WHERE id = '.$id, 'ARRAY_A');
133
134 if ($entry) {
135 return $entry['data'];
136 } else {
137 return null;
138 }
139 }
140
141 private function setObjectCache($id, $data) {
142 global $wpdb;
143
144 $id = intval($id);
145 $type = esc_sql($data['type']);
146 $data = esc_sql(json_encode($data));
147
148 if (strlen($type) > 0 && strlen($data) > 4) {
149 $sql = "INSERT INTO {$wpdb->prefix}" . self::$TABLE_NAME
150 . " (id, type, data) VALUES('".$id. "', '".$type. "', '".$data. "')"
151 . " ON DUPLICATE KEY UPDATE id = '".$id."'";
152 $wpdb->query($sql);
153 }
154 }
155
156 private function deleteObjectCache($id) {
157 global $wpdb;
158
159 $id = intval($id);
160 $wpdb->query("DELETE FROM {$wpdb->prefix}" . self::$TABLE_NAME . " WHERE id = ".$id);
161 }
162
163 private function getRootCache($type) {
164 $type = preg_replace('/[^a-z]/i', '', strtolower($type));
165 $optionname = 'webling-cache-root-'.$type;
166 return get_option($optionname, null);
167 }
168
169 private function setRootCache($type, $data) {
170 $type = preg_replace('/[^a-z]/i', '', strtolower($type));
171 $optionname = 'webling-cache-root-'.$type;
172 update_option($optionname, json_encode($data), false);
173 }
174
175 private function deleteRootCache() {
176 global $wpdb;
177
178 $sql = "SELECT option_name FROM {$wpdb->prefix}options WHERE option_name LIKE 'webling-cache-root-%'";
179 $options = $wpdb->get_results($sql, 'ARRAY_A');
180 foreach ($options as $option) {
181 delete_option($option['option_name']);
182 }
183 }
184
185 }
186