composer package updates
[openemr.git] / vendor / zendframework / zend-cache / src / Storage / Adapter / ExtMongoDb.php
blobc96bc01d825f60dd026e9731df6e4c754294ca78
1 <?php
2 /**
3 * @see https://github.com/zendframework/zend-cache for the canonical source repository
4 * @copyright Copyright (c) 2018 Zend Technologies USA Inc. (https://www.zend.com)
5 * @license https://github.com/zendframework/zend-cache/blob/master/LICENSE.md New BSD License
6 */
8 namespace Zend\Cache\Storage\Adapter;
10 use MongoDB\Client;
11 use MongoDB\Collection;
12 use MongoDB\BSON\UTCDateTime as MongoDate;
13 use MongoDB\Driver\Exception\Exception as MongoDriverException;
14 use stdClass;
15 use Zend\Cache\Exception;
16 use Zend\Cache\Storage\Capabilities;
17 use Zend\Cache\Storage\FlushableInterface;
19 /**
20 * Cache storage adapter for ext-mongodb
22 * If you are using ext-mongo, use the MongoDb adapter instead.
24 class ExtMongoDb extends AbstractAdapter implements FlushableInterface
26 /**
27 * Has this instance be initialized
29 * @var bool
31 private $initialized = false;
33 /**
34 * the mongodb resource manager
36 * @var null|ExtMongoDbResourceManager
38 private $resourceManager;
40 /**
41 * The mongodb resource id
43 * @var null|string
45 private $resourceId;
47 /**
48 * The namespace prefix
50 * @var string
52 private $namespacePrefix = '';
54 /**
55 * {@inheritDoc}
57 * @throws Exception\ExtensionNotLoadedException
59 public function __construct($options = null)
61 if (! extension_loaded('mongodb') || ! class_exists(Client::class)) {
62 throw new Exception\ExtensionNotLoadedException(
63 'mongodb extension not loaded or Mongo PHP client library not installed'
67 parent::__construct($options);
69 $initialized = & $this->initialized;
71 $this->getEventManager()->attach(
72 'option',
73 function () use (& $initialized) {
74 $initialized = false;
79 /**
80 * get mongodb resource
82 * @return Collection
84 private function getMongoCollection()
86 if (! $this->initialized) {
87 $options = $this->getOptions();
89 $this->resourceManager = $options->getResourceManager();
90 $this->resourceId = $options->getResourceId();
91 $namespace = $options->getNamespace();
92 $this->namespacePrefix = ($namespace === '' ? '' : $namespace . $options->getNamespaceSeparator());
93 $this->initialized = true;
96 return $this->resourceManager->getResource($this->resourceId);
99 /**
100 * {@inheritDoc}
102 public function setOptions($options)
104 return parent::setOptions(
105 $options instanceof ExtMongoDbOptions
106 ? $options
107 : new ExtMongoDbOptions($options)
112 * Get options.
114 * @see setOptions()
115 * @return ExtMongoDbOptions
117 public function getOptions()
119 return $this->options;
123 * {@inheritDoc}
125 * @throws Exception\RuntimeException
127 protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
129 $result = $this->fetchFromCollection($normalizedKey);
130 $success = false;
132 if (null === $result) {
133 return;
136 if (isset($result['expires'])) {
137 if (! $result['expires'] instanceof MongoDate) {
138 throw new Exception\RuntimeException(sprintf(
139 "The found item _id '%s' for key '%s' is not a valid cache item"
140 . ": the field 'expired' isn't an instance of MongoDate, '%s' found instead",
141 (string) $result['_id'],
142 $this->namespacePrefix . $normalizedKey,
143 is_object($result['expires']) ? get_class($result['expires']) : gettype($result['expires'])
147 if ($result['expires']->sec < (new MongoDate())) {
148 $this->internalRemoveItem($normalizedKey);
149 return;
153 if (! array_key_exists('value', $result)) {
154 throw new Exception\RuntimeException(sprintf(
155 "The found item _id '%s' for key '%s' is not a valid cache item: missing the field 'value'",
156 (string) $result['_id'],
157 $this->namespacePrefix . $normalizedKey
161 $success = true;
163 return $casToken = $result['value'];
167 * {@inheritDoc}
169 * @throws Exception\RuntimeException
171 protected function internalSetItem(& $normalizedKey, & $value)
173 $mongo = $this->getMongoCollection();
174 $key = $this->namespacePrefix . $normalizedKey;
175 $ttl = $this->getOptions()->getTTl();
176 $expires = null;
177 $cacheItem = [
178 'key' => $key,
179 'value' => $value,
182 if ($ttl > 0) {
183 $ttlSeconds = round((microtime(true) + $ttl) * 1000);
184 $cacheItem['expires'] = new MongoDate($ttlSeconds);
187 try {
188 $mongo->deleteOne(['key' => $key]);
189 $result = $mongo->insertOne($cacheItem);
190 } catch (MongoDriverException $e) {
191 throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e);
194 return null !== $result && $result->isAcknowledged();
198 * {@inheritDoc}
200 * @throws Exception\RuntimeException
202 protected function internalRemoveItem(& $normalizedKey)
204 try {
205 $result = $this->getMongoCollection()->deleteOne(['key' => $this->namespacePrefix . $normalizedKey]);
206 } catch (MongoDriverException $e) {
207 throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e);
210 return null !== $result && $result->getDeletedCount() > 0;
214 * {@inheritDoc}
216 public function flush()
218 $result = $this->getMongoCollection()->drop();
219 return ((float) 1) === $result['ok'];
223 * {@inheritDoc}
225 protected function internalGetCapabilities()
227 if ($this->capabilities) {
228 return $this->capabilities;
231 return $this->capabilities = new Capabilities(
232 $this,
233 $this->capabilityMarker = new stdClass(),
235 'supportedDatatypes' => [
236 'NULL' => true,
237 'boolean' => true,
238 'integer' => true,
239 'double' => true,
240 'string' => true,
241 'array' => true,
242 'object' => false,
243 'resource' => false,
245 'supportedMetadata' => [
246 '_id',
248 'minTtl' => 1,
249 'staticTtl' => true,
250 'maxKeyLength' => 255,
251 'namespaceIsPrefix' => true,
257 * {@inheritDoc}
259 * @throws Exception\ExceptionInterface
261 protected function internalGetMetadata(& $normalizedKey)
263 $result = $this->fetchFromCollection($normalizedKey);
264 return null !== $result ? ['_id' => $result['_id']] : false;
268 * Return raw records from MongoCollection
270 * @param string $normalizedKey
272 * @return array|null
274 * @throws Exception\RuntimeException
276 private function fetchFromCollection(& $normalizedKey)
278 try {
279 return $this->getMongoCollection()->findOne(['key' => $this->namespacePrefix . $normalizedKey]);
280 } catch (MongoDriverException $e) {
281 throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e);