PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.36.0
MailPoet – Newsletters, Email Marketing, and Automation v5.36.0
5.36.0 5.35.1 5.35.0 5.34.3 5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / vendor-prefixed / doctrine / orm / src / Cache / DefaultQueryCache.php
mailpoet / vendor-prefixed / doctrine / orm / src / Cache Last commit date
Exception 9 months ago Logging 9 months ago Persister 9 months ago Region 9 months ago AssociationCacheEntry.php 9 months ago CacheConfiguration.php 9 months ago CacheEntry.php 9 months ago CacheException.php 9 months ago CacheFactory.php 9 months ago CacheKey.php 9 months ago CollectionCacheEntry.php 9 months ago CollectionCacheKey.php 9 months ago CollectionHydrator.php 9 months ago ConcurrentRegion.php 9 months ago DefaultCache.php 9 months ago DefaultCacheFactory.php 9 months ago DefaultCollectionHydrator.php 9 months ago DefaultEntityHydrator.php 9 months ago DefaultQueryCache.php 9 months ago EntityCacheEntry.php 9 months ago EntityCacheKey.php 9 months ago EntityHydrator.php 9 months ago Lock.php 9 months ago LockException.php 9 months ago MultiGetRegion.php 9 months ago QueryCache.php 9 months ago QueryCacheEntry.php 9 months ago QueryCacheKey.php 9 months ago QueryCacheValidator.php 9 months ago Region.php 9 months ago RegionsConfiguration.php 9 months ago TimestampCacheEntry.php 9 months ago TimestampCacheKey.php 9 months ago TimestampQueryCacheValidator.php 9 months ago TimestampRegion.php 9 months ago index.php 9 months ago
DefaultQueryCache.php
305 lines
1 <?php
2 declare (strict_types=1);
3 namespace MailPoetVendor\Doctrine\ORM\Cache;
4 if (!defined('ABSPATH')) exit;
5 use MailPoetVendor\Doctrine\Common\Collections\ArrayCollection;
6 use MailPoetVendor\Doctrine\ORM\Cache;
7 use MailPoetVendor\Doctrine\ORM\Cache\Exception\FeatureNotImplemented;
8 use MailPoetVendor\Doctrine\ORM\Cache\Exception\NonCacheableEntity;
9 use MailPoetVendor\Doctrine\ORM\Cache\Logging\CacheLogger;
10 use MailPoetVendor\Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister;
11 use MailPoetVendor\Doctrine\ORM\EntityManagerInterface;
12 use MailPoetVendor\Doctrine\ORM\Mapping\ClassMetadata;
13 use MailPoetVendor\Doctrine\ORM\PersistentCollection;
14 use MailPoetVendor\Doctrine\ORM\Query;
15 use MailPoetVendor\Doctrine\ORM\Query\ResultSetMapping;
16 use MailPoetVendor\Doctrine\ORM\UnitOfWork;
17 use function array_map;
18 use function array_shift;
19 use function array_unshift;
20 use function assert;
21 use function count;
22 use function is_array;
23 use function key;
24 use function reset;
25 class DefaultQueryCache implements QueryCache
26 {
27 private $em;
28 private $uow;
29 private $region;
30 private $validator;
31 protected $cacheLogger;
32 private static $hints = [Query::HINT_CACHE_ENABLED => \true];
33 public function __construct(EntityManagerInterface $em, Region $region)
34 {
35 $cacheConfig = $em->getConfiguration()->getSecondLevelCacheConfiguration();
36 $this->em = $em;
37 $this->region = $region;
38 $this->uow = $em->getUnitOfWork();
39 $this->cacheLogger = $cacheConfig->getCacheLogger();
40 $this->validator = $cacheConfig->getQueryValidator();
41 }
42 public function get(QueryCacheKey $key, ResultSetMapping $rsm, array $hints = [])
43 {
44 if (!($key->cacheMode & Cache::MODE_GET)) {
45 return null;
46 }
47 $cacheEntry = $this->region->get($key);
48 if (!$cacheEntry instanceof QueryCacheEntry) {
49 return null;
50 }
51 if (!$this->validator->isValid($key, $cacheEntry)) {
52 $this->region->evict($key);
53 return null;
54 }
55 $result = [];
56 $entityName = reset($rsm->aliasMap);
57 $hasRelation = !empty($rsm->relationMap);
58 $persister = $this->uow->getEntityPersister($entityName);
59 assert($persister instanceof CachedEntityPersister);
60 $region = $persister->getCacheRegion();
61 $regionName = $region->getName();
62 $cm = $this->em->getClassMetadata($entityName);
63 $generateKeys = static function (array $entry) use($cm) : EntityCacheKey {
64 return new EntityCacheKey($cm->rootEntityName, $entry['identifier']);
65 };
66 $cacheKeys = new CollectionCacheEntry(array_map($generateKeys, $cacheEntry->result));
67 $entries = $region->getMultiple($cacheKeys) ?? [];
68 // @TODO - move to cache hydration component
69 foreach ($cacheEntry->result as $index => $entry) {
70 $entityEntry = $entries[$index] ?? null;
71 if (!$entityEntry instanceof EntityCacheEntry) {
72 if ($this->cacheLogger !== null) {
73 $this->cacheLogger->entityCacheMiss($regionName, $cacheKeys->identifiers[$index]);
74 }
75 return null;
76 }
77 if ($this->cacheLogger !== null) {
78 $this->cacheLogger->entityCacheHit($regionName, $cacheKeys->identifiers[$index]);
79 }
80 if (!$hasRelation) {
81 $result[$index] = $this->uow->createEntity($entityEntry->class, $entityEntry->resolveAssociationEntries($this->em), self::$hints);
82 continue;
83 }
84 $data = $entityEntry->data;
85 foreach ($entry['associations'] as $name => $assoc) {
86 $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']);
87 assert($assocPersister instanceof CachedEntityPersister);
88 $assocRegion = $assocPersister->getCacheRegion();
89 $assocMetadata = $this->em->getClassMetadata($assoc['targetEntity']);
90 if ($assoc['type'] & ClassMetadata::TO_ONE) {
91 $assocKey = new EntityCacheKey($assocMetadata->rootEntityName, $assoc['identifier']);
92 $assocEntry = $assocRegion->get($assocKey);
93 if ($assocEntry === null) {
94 if ($this->cacheLogger !== null) {
95 $this->cacheLogger->entityCacheMiss($assocRegion->getName(), $assocKey);
96 }
97 $this->uow->hydrationComplete();
98 return null;
99 }
100 $data[$name] = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), self::$hints);
101 if ($this->cacheLogger !== null) {
102 $this->cacheLogger->entityCacheHit($assocRegion->getName(), $assocKey);
103 }
104 continue;
105 }
106 if (!isset($assoc['list']) || empty($assoc['list'])) {
107 continue;
108 }
109 $generateKeys = static function ($id) use($assocMetadata) : EntityCacheKey {
110 return new EntityCacheKey($assocMetadata->rootEntityName, $id);
111 };
112 $collection = new PersistentCollection($this->em, $assocMetadata, new ArrayCollection());
113 $assocKeys = new CollectionCacheEntry(array_map($generateKeys, $assoc['list']));
114 $assocEntries = $assocRegion->getMultiple($assocKeys);
115 foreach ($assoc['list'] as $assocIndex => $assocId) {
116 $assocEntry = is_array($assocEntries) ? $assocEntries[$assocIndex] ?? null : null;
117 if ($assocEntry === null) {
118 if ($this->cacheLogger !== null) {
119 $this->cacheLogger->entityCacheMiss($assocRegion->getName(), $assocKeys->identifiers[$assocIndex]);
120 }
121 $this->uow->hydrationComplete();
122 return null;
123 }
124 $element = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), self::$hints);
125 $collection->hydrateSet($assocIndex, $element);
126 if ($this->cacheLogger !== null) {
127 $this->cacheLogger->entityCacheHit($assocRegion->getName(), $assocKeys->identifiers[$assocIndex]);
128 }
129 }
130 $data[$name] = $collection;
131 $collection->setInitialized(\true);
132 }
133 foreach ($data as $fieldName => $unCachedAssociationData) {
134 // In some scenarios, such as EAGER+ASSOCIATION+ID+CACHE, the
135 // cache key information in `$cacheEntry` will not contain details
136 // for fields that are associations.
137 //
138 // This means that `$data` keys for some associations that may
139 // actually not be cached will not be converted to actual association
140 // data, yet they contain L2 cache AssociationCacheEntry objects.
141 //
142 // We need to unwrap those associations into proxy references,
143 // since we don't have actual data for them except for identifiers.
144 if ($unCachedAssociationData instanceof AssociationCacheEntry) {
145 $data[$fieldName] = $this->em->getReference($unCachedAssociationData->class, $unCachedAssociationData->identifier);
146 }
147 }
148 $result[$index] = $this->uow->createEntity($entityEntry->class, $data, self::$hints);
149 }
150 $this->uow->hydrationComplete();
151 return $result;
152 }
153 public function put(QueryCacheKey $key, ResultSetMapping $rsm, $result, array $hints = [])
154 {
155 if ($rsm->scalarMappings) {
156 throw FeatureNotImplemented::scalarResults();
157 }
158 if (count($rsm->entityMappings) > 1) {
159 throw FeatureNotImplemented::multipleRootEntities();
160 }
161 if (!$rsm->isSelect) {
162 throw FeatureNotImplemented::nonSelectStatements();
163 }
164 if (($hints[Query\SqlWalker::HINT_PARTIAL] ?? \false) === \true || ($hints[Query::HINT_FORCE_PARTIAL_LOAD] ?? \false) === \true) {
165 throw FeatureNotImplemented::partialEntities();
166 }
167 if (!($key->cacheMode & Cache::MODE_PUT)) {
168 return \false;
169 }
170 $data = [];
171 $entityName = reset($rsm->aliasMap);
172 $rootAlias = key($rsm->aliasMap);
173 $persister = $this->uow->getEntityPersister($entityName);
174 if (!$persister instanceof CachedEntityPersister) {
175 throw NonCacheableEntity::fromEntity($entityName);
176 }
177 $region = $persister->getCacheRegion();
178 $cm = $this->em->getClassMetadata($entityName);
179 foreach ($result as $index => $entity) {
180 $identifier = $this->uow->getEntityIdentifier($entity);
181 $entityKey = new EntityCacheKey($cm->rootEntityName, $identifier);
182 if ($key->cacheMode & Cache::MODE_REFRESH || !$region->contains($entityKey)) {
183 // Cancel put result if entity put fail
184 if (!$persister->storeEntityCache($entity, $entityKey)) {
185 return \false;
186 }
187 }
188 $data[$index]['identifier'] = $identifier;
189 $data[$index]['associations'] = [];
190 // @TODO - move to cache hydration components
191 foreach ($rsm->relationMap as $alias => $name) {
192 $parentAlias = $rsm->parentAliasMap[$alias];
193 $parentClass = $rsm->aliasMap[$parentAlias];
194 $metadata = $this->em->getClassMetadata($parentClass);
195 $assoc = $metadata->associationMappings[$name];
196 $assocValue = $this->getAssociationValue($rsm, $alias, $entity);
197 if ($assocValue === null) {
198 continue;
199 }
200 // root entity association
201 if ($rootAlias === $parentAlias) {
202 // Cancel put result if association put fail
203 $assocInfo = $this->storeAssociationCache($key, $assoc, $assocValue);
204 if ($assocInfo === null) {
205 return \false;
206 }
207 $data[$index]['associations'][$name] = $assocInfo;
208 continue;
209 }
210 // store single nested association
211 if (!is_array($assocValue)) {
212 // Cancel put result if association put fail
213 if ($this->storeAssociationCache($key, $assoc, $assocValue) === null) {
214 return \false;
215 }
216 continue;
217 }
218 // store array of nested association
219 foreach ($assocValue as $aVal) {
220 // Cancel put result if association put fail
221 if ($this->storeAssociationCache($key, $assoc, $aVal) === null) {
222 return \false;
223 }
224 }
225 }
226 }
227 return $this->region->put($key, new QueryCacheEntry($data));
228 }
229 private function storeAssociationCache(QueryCacheKey $key, array $assoc, $assocValue) : ?array
230 {
231 $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']);
232 $assocMetadata = $assocPersister->getClassMetadata();
233 $assocRegion = $assocPersister->getCacheRegion();
234 // Handle *-to-one associations
235 if ($assoc['type'] & ClassMetadata::TO_ONE) {
236 $assocIdentifier = $this->uow->getEntityIdentifier($assocValue);
237 $entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier);
238 if (!$this->uow->isUninitializedObject($assocValue) && $key->cacheMode & Cache::MODE_REFRESH || !$assocRegion->contains($entityKey)) {
239 // Entity put fail
240 if (!$assocPersister->storeEntityCache($assocValue, $entityKey)) {
241 return null;
242 }
243 }
244 return ['targetEntity' => $assocMetadata->rootEntityName, 'identifier' => $assocIdentifier, 'type' => $assoc['type']];
245 }
246 // Handle *-to-many associations
247 $list = [];
248 foreach ($assocValue as $assocItemIndex => $assocItem) {
249 $assocIdentifier = $this->uow->getEntityIdentifier($assocItem);
250 $entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier);
251 if ($key->cacheMode & Cache::MODE_REFRESH || !$assocRegion->contains($entityKey)) {
252 // Entity put fail
253 if (!$assocPersister->storeEntityCache($assocItem, $entityKey)) {
254 return null;
255 }
256 }
257 $list[$assocItemIndex] = $assocIdentifier;
258 }
259 return ['targetEntity' => $assocMetadata->rootEntityName, 'type' => $assoc['type'], 'list' => $list];
260 }
261 private function getAssociationValue(ResultSetMapping $rsm, string $assocAlias, $entity)
262 {
263 $path = [];
264 $alias = $assocAlias;
265 while (isset($rsm->parentAliasMap[$alias])) {
266 $parent = $rsm->parentAliasMap[$alias];
267 $field = $rsm->relationMap[$alias];
268 $class = $rsm->aliasMap[$parent];
269 array_unshift($path, ['field' => $field, 'class' => $class]);
270 $alias = $parent;
271 }
272 return $this->getAssociationPathValue($entity, $path);
273 }
274 private function getAssociationPathValue($value, array $path)
275 {
276 $mapping = array_shift($path);
277 $metadata = $this->em->getClassMetadata($mapping['class']);
278 $assoc = $metadata->associationMappings[$mapping['field']];
279 $value = $metadata->getFieldValue($value, $mapping['field']);
280 if ($value === null) {
281 return null;
282 }
283 if ($path === []) {
284 return $value;
285 }
286 // Handle *-to-one associations
287 if ($assoc['type'] & ClassMetadata::TO_ONE) {
288 return $this->getAssociationPathValue($value, $path);
289 }
290 $values = [];
291 foreach ($value as $item) {
292 $values[] = $this->getAssociationPathValue($item, $path);
293 }
294 return $values;
295 }
296 public function clear()
297 {
298 return $this->region->evictAll();
299 }
300 public function getRegion()
301 {
302 return $this->region;
303 }
304 }
305