1
+ <?php
2
+ /*
3
+ * This file is part of the Sonata package.
4
+ *
5
+ * (c) Thomas Rabaix <[email protected] >
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+
11
+ namespace Sonata \CacheBundle \Adapter ;
12
+
13
+ use Symfony \Component \Routing \Router ;
14
+ use Symfony \Component \HttpFoundation \Response ;
15
+ use Symfony \Component \Security \Core \Exception \AccessDeniedException ;
16
+ use Symfony \Component \Routing \RouterInterface ;
17
+
18
+ use Sonata \BlockBundle \Cache \CacheInterface ;
19
+ use Sonata \CacheBundle \Cache \CacheElement ;
20
+
21
+ class ApcCache implements CacheInterface
22
+ {
23
+ protected $ servers ;
24
+
25
+ protected $ prefix ;
26
+
27
+ protected $ collection ;
28
+
29
+ protected $ router ;
30
+
31
+ /**
32
+ * @param \Symfony\Component\Routing\RouterInterface $router
33
+ * @param string $token
34
+ * @param string $prefix
35
+ * @param array $servers
36
+ */
37
+ public function __construct (RouterInterface $ router , $ token , $ prefix , array $ servers )
38
+ {
39
+ $ this ->token = $ token ;
40
+ $ this ->prefix = $ prefix ;
41
+ $ this ->servers = $ servers ;
42
+ $ this ->router = $ router ;
43
+ }
44
+
45
+ /**
46
+ * @return string
47
+ */
48
+ private function getToken ()
49
+ {
50
+ return $ this ->token ;
51
+ }
52
+
53
+ /**
54
+ * @return bool
55
+ */
56
+ public function flushAll ()
57
+ {
58
+ $ result = true ;
59
+ foreach ($ this ->servers as $ server ) {
60
+ if (count (explode ('. ' , $ server ['ip ' ]) == 3 )) {
61
+ $ socket = socket_create (AF_INET , SOCK_STREAM , SOL_TCP );
62
+ } else {
63
+ $ socket = socket_create (AF_INET6 , SOCK_STREAM , SOL_TCP );
64
+ }
65
+
66
+ // generate the raw http request
67
+ $ command = sprintf ("GET %s HTTP/1.1 \r\n" , $ this ->router ->generate ('sonata_cache_apc ' , array ('token ' => $ this ->token )));
68
+ $ command .= sprintf ("Host: %s \r\n" , $ server ['domain ' ]);
69
+ $ command .= "Connection: Close \r\n\r\n" ;
70
+
71
+ // setup the default timeout (avoid max execution time)
72
+ socket_set_option ($ socket , SOL_SOCKET , SO_SNDTIMEO , array ('sec ' => 2 , 'usec ' => 0 ));
73
+ socket_set_option ($ socket , SOL_SOCKET , SO_RCVTIMEO , array ('sec ' => 2 , 'usec ' => 0 ));
74
+
75
+ socket_connect ($ socket , $ server ['ip ' ], $ server ['port ' ]);
76
+
77
+ socket_write ($ socket , $ command );
78
+
79
+ $ content = socket_read ($ socket , 1024 );
80
+
81
+ if ($ result ) {
82
+ $ result = substr ($ content , -2 ) == 'ok ' ? true : false ;
83
+ }
84
+ }
85
+
86
+ return $ result ;
87
+ }
88
+
89
+ /**
90
+ * @param array $keys
91
+ * @return bool
92
+ */
93
+ public function flush (array $ keys = array ())
94
+ {
95
+ return $ this ->flushAll ();
96
+ }
97
+
98
+ /**
99
+ * @param CacheElement $cacheElement
100
+ * @return bool|\string[]
101
+ */
102
+ public function has (CacheElement $ cacheElement )
103
+ {
104
+ return apc_exists ($ this ->computeCacheKeys ($ cacheElement ));
105
+ }
106
+
107
+ /**
108
+ * @param CacheElement $cacheElement
109
+ * @return mixed
110
+ */
111
+ public function set (CacheElement $ cacheElement )
112
+ {
113
+ $ return = apc_store (
114
+ $ this ->computeCacheKeys ($ cacheElement ),
115
+ $ cacheElement ->getValue (),
116
+ $ cacheElement ->getTtl ()
117
+ );
118
+
119
+ return $ return ;
120
+ }
121
+
122
+ /**
123
+ * @param CacheElement $cacheElement
124
+ * @return string
125
+ */
126
+ private function computeCacheKeys (CacheElement $ cacheElement )
127
+ {
128
+ $ keys = $ cacheElement ->getKeys ();
129
+
130
+ ksort ($ keys );
131
+
132
+ return md5 ($ this ->prefix .serialize ($ keys ));
133
+ }
134
+
135
+ /**
136
+ * @param CacheElement $cacheElement
137
+ * @return mixed
138
+ */
139
+ public function get (CacheElement $ cacheElement )
140
+ {
141
+ return apc_fetch ($ this ->computeCacheKeys ($ cacheElement ));
142
+ }
143
+
144
+ /**
145
+ * @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException
146
+ * @param $token
147
+ * @return \Symfony\Component\HttpFoundation\Response
148
+ */
149
+ public function cacheAction ($ token )
150
+ {
151
+ if ($ this ->getToken () == $ token ) {
152
+ apc_clear_cache ('user ' );
153
+
154
+ return new Response ('ok ' , 200 , array (
155
+ 'Cache-Control ' => 'no-cache, must-revalidate '
156
+ ));
157
+ }
158
+
159
+ throw new AccessDeniedException ('invalid token ' );
160
+ }
161
+
162
+ /**
163
+ * @return bool
164
+ */
165
+ public function isContextual ()
166
+ {
167
+ return false ;
168
+ }
169
+ }
0 commit comments