EntityMap::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * Spiral, Core Components
4
 *
5
 * @author Wolfy-J
6
 */
7
8
namespace Spiral\ORM;
9
10
use Spiral\Models\EntityInterface;
11
use Spiral\ORM\Exceptions\MapException;
12
13
/**
14
 * Entity cache provides ability to access already retrieved entities from memory instead of
15
 * calling database. Attention, cache WILL BE isolated in a selection scope in order to prevent
16
 * data collision, ie:
17
 *
18
 * $user1 => $users->findOne();
19
 * $user2 => $users->findOne();
20
 *
21
 * //Will work ONLY when both selections in a same scope, or it's same selector
22
 * assert($user1 !== $user2);
23
 */
24
final class EntityMap
25
{
26
    /**
27
     * @var EntityInterface[]
28
     */
29
    private $entities = [];
30
31
    /**
32
     * Maximum entity cache size. Null is unlimited.
33
     *
34
     * @var int|null
35
     */
36
    private $maxSize = null;
37
38
    /**
39
     * @param int|null $maxSize Set to null to make cache size unlimited.
40
     */
41
    public function __construct(int $maxSize = null)
42
    {
43
        $this->maxSize = $maxSize;
44
    }
45
46
    /**
47
     * Add Record to entity cache. Primary key value will be used as
48
     * identifier.
49
     *
50
     * Attention, existed entity will be replaced!
51
     *
52
     * @param RecordInterface $entity
53
     * @param bool            $ignoreLimit Cache overflow will be ignored.
54
     *
55
     * @return RecordInterface Returns given entity.
56
     *
57
     * @throws MapException When cache size exceeded.
58
     */
59
    public function remember(RecordInterface $entity, bool $ignoreLimit = false): RecordInterface
60
    {
61
        if (!$ignoreLimit && !is_null($this->maxSize) && count($this->entities) > $this->maxSize - 1) {
62
            throw new MapException('Entity cache size exceeded');
63
        }
64
65
        if (empty($entity->primaryKey())) {
66
            throw new MapException("Unable to store non identified entity " . get_class($entity));
67
        }
68
69
        $cacheID = get_class($entity) . ':' . $entity->primaryKey();
70
71
        return $this->entities[$cacheID] = $entity;
72
    }
73
74
    /**
75
     * Remove entity record from entity cache. Primary key value will be used as identifier.
76
     *
77
     * @param RecordInterface $entity
78
     */
79
    public function forget(RecordInterface $entity)
80
    {
81
        $cacheID = get_class($entity) . ':' . $entity->primaryKey();
82
        unset($this->entities[$cacheID]);
83
    }
84
85
    /**
86
     * Check if desired entity was already cached.
87
     *
88
     * @param string $class
89
     * @param string $identity
90
     *
91
     * @return bool
92
     */
93
    public function has(string $class, string $identity): bool
94
    {
95
        return isset($this->entities["{$class}:{$identity}"]);
96
    }
97
98
    /**
99
     * Fetch entity from cache.
100
     *
101
     * @param string $class
102
     * @param string $identity
103
     *
104
     * @return null|mixed
105
     */
106
    public function get(string $class, string $identity)
107
    {
108
        if (!$this->has($class, $identity)) {
109
            return null;
110
        }
111
112
        return $this->entities["{$class}:{$identity}"];
113
    }
114
115
    /**
116
     * Flush content of entity cache.
117
     */
118
    public function flush()
119
    {
120
        $this->entities = [];
121
    }
122
123
    /**
124
     * Destructing.
125
     */
126
    public function __destruct()
127
    {
128
        $this->flush();
129
    }
130
}
131