Passed
Push — develop ( 33032a...666b96 )
by Henry
02:03
created

Versioning   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 127
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 43
c 2
b 0
f 0
dl 0
loc 127
rs 10
wmc 15

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getRevisionsByID() 0 5 1
A afterVersionedSave() 0 7 3
A getHistoryTable() 0 7 2
A beforeVersionedSave() 0 7 3
A getRevisionRecords() 0 29 5
A getRevisions() 0 3 1
1
<?php
2
/**
3
 * This file is part of the Divergence package.
4
 *
5
 * (c) Henry Paradiz <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Divergence\Models;
12
13
use Exception;
14
15
use Divergence\Helpers\Util;
16
use Divergence\IO\Database\MySQL as DB;
17
use Divergence\IO\Database\Query\Insert;
18
use Divergence\IO\Database\Query\Select;
19
20
/**
21
 * Versioning.
22
 *
23
 * @package Divergence
24
 * @author  Henry Paradiz <[email protected]>
25
 * @inheritDoc
26
 * @property int $RevisionID ID of revision in the history table.
27
 * @property static[] $History All revisions for this object. This is hooked in the Relations trait.
28
 * @property string $historyTable
29
 * @property callable $createRevisionOnSave
30
 */
31
trait Versioning
32
{
33
    public $wasDirty = false;
34
35
    public static $versioningFields = [
36
        'RevisionID' => [
37
            'columnName' => 'RevisionID',
38
            'type' => 'integer',
39
            'unsigned' => true,
40
            'notnull' => false,
41
        ],
42
    ];
43
44
    public static $versioningRelationships = [
45
        'History' => [
46
            'type' => 'history',
47
            'order' => ['RevisionID' => 'DESC'],
48
        ],
49
    ];
50
51
    /**
52
     * Returns static::$historyTable
53
     *
54
     * @throws Exception If static::$historyTable is not set.
55
     * @return string
56
     */
57
    public static function getHistoryTable()
58
    {
59
        if (!static::$historyTable) {
60
            throw new Exception('Static variable $historyTable must be defined to use model versioning.');
61
        }
62
63
        return static::$historyTable;
64
    }
65
66
    /**
67
     * The history table allows multiple records with the same ID.
68
     * The primary key becomes RevisionID.
69
     * This returns all the revisions by ID so you will get the history of that object.
70
     *
71
     * @return static[] Revisions by ID
72
     */
73
    public static function getRevisionsByID($ID, $options = [])
74
    {
75
        $options['conditions'][static::getPrimaryKey()] = $ID;
76
77
        return static::getRevisions($options);
78
    }
79
80
    /**
81
     * Gets all versions of all objects for this object.
82
     *
83
     * Use getRevisionsByID instead.
84
     *
85
     * @param array $options Query options
86
     * @return static[] Revisions
87
     */
88
    public static function getRevisions($options = [])
89
    {
90
        return static::instantiateRecords(static::getRevisionRecords($options));
91
    }
92
93
    /**
94
     * Gets raw revision data from the database and constructs a query
95
     *
96
     * @param array $options Query options
97
     * @return array
98
     */
99
    public static function getRevisionRecords($options = [])
100
    {
101
        $options = Util::prepareOptions($options, [
102
            'indexField' => false,
103
            'conditions' => [],
104
            'order' => false,
105
            'limit' => false,
106
            'offset' => 0,
107
        ]);
108
109
110
        $select = (new Select())->setTable(static::getHistoryTable());
111
112
        if ($options['conditions']) {
113
            $select->where(join(') AND (', static::_mapConditions($options['conditions'])));
114
        }
115
116
        if ($options['order']) {
117
            $select->order(join(',', static::_mapFieldOrder($options['order'])));
118
        }
119
120
        if ($options['limit']) {
121
            $select->limit(sprintf('%u,%u', $options['offset'], $options['limit']));
122
        }
123
124
        if ($options['indexField']) {
125
            return DB::table(static::_cn($options['indexField']), $select);
126
        } else {
127
            return DB::allRecords($select);
128
        }
129
    }
130
131
    /**
132
     * Sets wasDirty, isDirty, Created for the object before save
133
     *
134
     * @return void
135
     */
136
    public function beforeVersionedSave()
137
    {
138
        $this->wasDirty = false;
139
        if ($this->isDirty && static::$createRevisionOnSave) {
140
            // update creation time
141
            $this->Created = time();
142
            $this->wasDirty = true;
143
        }
144
    }
145
146
    /**
147
     * After save to regular database this saves to the history table
148
     *
149
     * @return void
150
     */
151
    public function afterVersionedSave()
152
    {
153
        if ($this->wasDirty && static::$createRevisionOnSave) {
154
            // save a copy to history table
155
            $recordValues = $this->_prepareRecordValues();
156
            $set = static::_mapValuesToSet($recordValues);
157
            DB::nonQuery((new Insert())->setTable(static::getHistoryTable())->set($set), null, [static::class,'handleError']);
158
        }
159
    }
160
}
161