Completed
Branch feature/pre-split (54fe62)
by Anton
03:12
created

Document::isLoaded()   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\ODM;
8
9
use MongoDB\BSON\ObjectID;
10
use Spiral\Models\ActiveEntityInterface;
11
use Spiral\ODM\Events\DocumentEvent;
12
13
/**
14
 * DocumentEntity with added ActiveRecord methods and ability to connect to associated source.
15
 * Document also provides an ability to specify aggregations using it's schema:
16
 *
17
 * const SCHEMA = [
18
 *     ...,
19
 *     'outer' => [
20
 *          self::ONE => Outer::class, [ //Reference to outer document using internal
21
 *              '_id' => 'self::outerID' //outerID value
22
 *          ]
23
 *      ],
24
 *     'many' => [
25
 *          self::MANY => Outer::class, [ //Reference to many outer document using
26
 *              'innerID' => 'self::_id'  //document primary key
27
 *          ]
28
 *     ]
29
 * ];
30
 *
31
 * Note: self::{name} construction will be replaced with document value in resulted query, even
32
 * in case of arrays ;) You can also use dot notation to get value from nested document.
33
 *
34
 * Attention, document will be linked to default database and named collection by default, use
35
 * properties database and collection to define your own custom database and collection.
36
 *
37
 * You can use property "index" to declare needed document indexes:
38
 *
39
 * Set of indexes to be created for associated collection. Use self::INDEX_OPTIONS or "@options"
40
 * for additional parameters.
41
 *
42
 * Example:
43
 * const INDEXES = [
44
 *      ['email' => 1, '@options' => ['unique' => true]],
45
 *      ['name' => 1]
46
 * ];
47
 *
48
 * @link http://php.net/manual/en/mongocollection.ensureindex.php
49
 *
50
 * Configuration properties:
51
 * - database
52
 * - collection
53
 * - schema
54
 * - indexes
55
 * - defaults
56
 * - secured (* by default)
57
 * - fillable
58
 */
59
abstract class Document extends DocumentEntity implements ActiveEntityInterface
60
{
61
    /**
62
     * Associated collection and database names, by default will be resolved based on a class name.
63
     */
64
    const DATABASE   = null;
65
    const COLLECTION = null;
66
67
    /**
68
     * Set of indexes to be created for associated collection. Use "@options" for additional
69
     * index options.
70
     *
71
     * Example:
72
     * const INDEXES = [
73
     *      ['email' => 1, '@options' => ['unique' => true]],
74
     *      ['name' => 1]
75
     * ];
76
     *
77
     * @link http://php.net/manual/en/mongocollection.ensureindex.php
78
     * @var array
79
     */
80
    const INDEXES = [];
81
82
    /**
83
     * Documents must ALWAYS have _id field.
84
     */
85
    const SCHEMA = [
86
        '_id' => ObjectID::class
87
    ];
88
89
    /**
90
     * _id is always nullable.
91
     */
92
    const DEFAULTS = [
93
        '_id' => null
94
    ];
95
96
    /**
97
     * {@inheritdoc}
98
     */
99
    public function __construct($fields = [], array $schema = [], ODMInterface $odm = null)
100
    {
101
        parent::__construct($fields, $schema, $odm);
102
103
        if (!$this->isLoaded()) {
104
            //Automatically force solidState for newly created documents
105
            $this->solidState(true);
106
        }
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function isLoaded(): bool
113
    {
114
        return !is_null($this->primaryKey());
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     */
120
    public function primaryKey()
121
    {
122
        return $this->getField('_id', null, false);
123
    }
124
125
    /**
126
     * {@inheritdoc}
127
     *
128
     * @return array
129
     */
130
    public function publicFields(bool $deun = false): array
131
    {
132
        return parent::publicFields();
133
    }
134
135
    /**
136
     * {@inheritdoc}
137
     *
138
     * @event creating(DocumentEvent)
139
     * @event created(DocumentEvent)
140
     * @event updating(DocumentEvent)
141
     * @event updated(DocumentEvent)
142
     */
143
    public function save(): int
144
    {
145
        if (!$this->isLoaded()) {
146
            $this->dispatch('creating', new DocumentEvent($this));
147
148
            //Performing creation
149
            $result = $this->odm->collection(static::class)->insertOne(
150
                $this->packValue(false)
151
            );
152
153
            $this->setField('_id', $result->getInsertedId());
154
            //Done with creation
155
156
            $this->flushUpdates();
157
            $this->dispatch('created', new DocumentEvent($this));
158
159
            return self::CREATED;
160
        }
161
162
        if ($this->isSolid() || $this->hasUpdates()) {
163
164
            /*
165
             * Performing an update using ODM class mapper.
166
             */
167
            $this->dispatch('updating', new DocumentEvent($this));
168
169
            //Performing an update
170
            $this->odm->collection(static::class)->updateOne(
171
                ['_id' => $this->primaryKey()],
172
                $this->buildAtomics()
173
            );
174
            //Done with update
175
176
            $this->flushUpdates();
177
            $this->dispatch('updated', new DocumentEvent($this));
178
179
            return self::UPDATED;
180
        }
181
182
        return self::UNCHANGED;
183
    }
184
185
    /**
186
     * {@inheritdoc}
187
     *
188
     * @event deleting(DocumentEvent)
189
     * @event deleted(DocumentEvent)
190
     */
191
    public function delete()
192
    {
193
        $this->dispatch('deleting', new DocumentEvent($this));
194
195
        /*
196
         * Performing deletion using ODM class mapper.
197
         */
198
        if ($this->isLoaded()) {
199
            $this->odm->collection(static::class)->deleteOne(['_id' => $this->primaryKey()]);
200
            $this->setField('_id', null, false);
201
        }
202
203
        $this->dispatch('deleted', new DocumentEvent($this));
204
    }
205
206
    //Aggregations???
207
}