Completed
Branch feature/pre-split (0a985a)
by Anton
05:37
created

EntityMap::flush()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\ORM;
8
9
use Spiral\Models\EntityInterface;
10
use Spiral\ORM\Exceptions\MapException;
11
12
/**
13
 * Entity cache provides ability to access already retrieved entities from memory instead of
14
 * calling database. Attention, cache WILL BE isolated in a selection scope in order to prevent
15
 * data collision, ie:
16
 *
17
 * $user1 => $users->findOne();
18
 * $user2 => $user->findOne();
19
 *
20
 * assert($user1 !== $user2);
21
 */
22
final class EntityMap
23
{
24
    /**
25
     * @var EntityInterface[]
26
     */
27
    private $entities = [];
28
29
    /**
30
     * Maximum entity cache size. Null is unlimited.
31
     *
32
     * @var int|null
33
     */
34
    private $maxSize = null;
35
36
    /**
37
     * @param int|null $maxSize Set to null to make cache size unlimited.
38
     */
39
    public function __construct(int $maxSize = null)
40
    {
41
        $this->maxSize = $maxSize;
42
    }
43
44
    /**
45
     * Add Record to entity cache. Primary key value will be used as
46
     * identifier.
47
     *
48
     * Attention, existed entity will be replaced!
49
     *
50
     * @param RecordInterface $entity
51
     * @param bool            $ignoreLimit Cache overflow will be ignored.
52
     *
53
     * @return RecordInterface Returns given entity.
54
     *
55
     * @throws MapException When cache size exceeded.
56
     */
57
    public function remember(
58
        RecordInterface $entity,
59
        $ignoreLimit = true
60
    ): RecordInterface {
61
        if (!$ignoreLimit && count($this->entities) > $this->maxSize) {
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 string $class
78
     * @param string $identity
79
     */
80
    public function forget(string $class, string $identity)
81
    {
82
        unset($this->entities["{$class}:{$identity}"]);
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 (empty($this->entities["{$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
}