]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - application/History.php
namespacing: \Shaarli\History
[github/shaarli/Shaarli.git] / application / History.php
CommitLineData
4306b184 1<?php
bdc5152d
V
2namespace Shaarli;
3
4use DateTime;
5use Exception;
6use FileUtils;
4306b184
A
7
8/**
9 * Class History
10 *
11 * Handle the history file tracing events in Shaarli.
12 * The history is stored as JSON in a file set by 'resource.history' setting.
13 *
14 * Available data:
15 * - event: event key
16 * - datetime: event date, in ISO8601 format.
17 * - id: event item identifier (currently only link IDs).
18 *
19 * Available event keys:
20 * - CREATED: new link
21 * - UPDATED: link updated
22 * - DELETED: link deleted
23 * - SETTINGS: the settings have been updated through the UI.
66e74d50 24 * - IMPORT: bulk links import
4306b184
A
25 *
26 * Note: new events are put at the beginning of the file and history array.
27 */
28class History
29{
30 /**
31 * @var string Action key: a new link has been created.
32 */
33 const CREATED = 'CREATED';
34
35 /**
36 * @var string Action key: a link has been updated.
37 */
38 const UPDATED = 'UPDATED';
39
40 /**
41 * @var string Action key: a link has been deleted.
42 */
43 const DELETED = 'DELETED';
44
45 /**
46 * @var string Action key: settings have been updated.
47 */
48 const SETTINGS = 'SETTINGS';
49
66e74d50
A
50 /**
51 * @var string Action key: a bulk import has been processed.
52 */
53 const IMPORT = 'IMPORT';
54
4306b184
A
55 /**
56 * @var string History file path.
57 */
58 protected $historyFilePath;
59
60 /**
61 * @var array History data.
62 */
63 protected $history;
64
65 /**
66 * @var int History retention time in seconds (1 month).
67 */
68 protected $retentionTime = 2678400;
69
70 /**
71 * History constructor.
72 *
73 * @param string $historyFilePath History file path.
74 * @param int $retentionTime History content rentention time in seconds.
75 *
76 * @throws Exception if something goes wrong.
77 */
78 public function __construct($historyFilePath, $retentionTime = null)
79 {
80 $this->historyFilePath = $historyFilePath;
81 if ($retentionTime !== null) {
82 $this->retentionTime = $retentionTime;
83 }
d16ca2e2
A
84 }
85
86 /**
87 * Initialize: read history file.
88 *
89 * Allow lazy loading (don't read the file if it isn't necessary).
90 */
91 protected function initialize()
92 {
4306b184
A
93 $this->check();
94 $this->read();
95 }
96
97 /**
98 * Add Event: new link.
99 *
100 * @param array $link Link data.
101 */
102 public function addLink($link)
103 {
104 $this->addEvent(self::CREATED, $link['id']);
105 }
106
107 /**
108 * Add Event: update existing link.
109 *
110 * @param array $link Link data.
111 */
112 public function updateLink($link)
113 {
114 $this->addEvent(self::UPDATED, $link['id']);
115 }
116
117 /**
118 * Add Event: delete existing link.
119 *
120 * @param array $link Link data.
121 */
122 public function deleteLink($link)
123 {
124 $this->addEvent(self::DELETED, $link['id']);
125 }
126
127 /**
128 * Add Event: settings updated.
129 */
130 public function updateSettings()
131 {
132 $this->addEvent(self::SETTINGS);
133 }
134
66e74d50
A
135 /**
136 * Add Event: bulk import.
137 *
138 * Note: we don't store links add/update one by one since it can have a huge impact on performances.
139 */
140 public function importLinks()
141 {
142 $this->addEvent(self::IMPORT);
143 }
144
4306b184
A
145 /**
146 * Save a new event and write it in the history file.
147 *
148 * @param string $status Event key, should be defined as constant.
bdc5152d 149 * @param mixed $id Event item identifier (e.g. link ID).
4306b184
A
150 */
151 protected function addEvent($status, $id = null)
152 {
d16ca2e2
A
153 if ($this->history === null) {
154 $this->initialize();
155 }
156
4306b184
A
157 $item = [
158 'event' => $status,
813849e5 159 'datetime' => new DateTime(),
4306b184
A
160 'id' => $id !== null ? $id : '',
161 ];
162 $this->history = array_merge([$item], $this->history);
163 $this->write();
164 }
165
166 /**
167 * Check that the history file is writable.
168 * Create the file if it doesn't exist.
169 *
170 * @throws Exception if it isn't writable.
171 */
172 protected function check()
173 {
bdc5152d 174 if (!is_file($this->historyFilePath)) {
4306b184
A
175 FileUtils::writeFlatDB($this->historyFilePath, []);
176 }
177
bdc5152d 178 if (!is_writable($this->historyFilePath)) {
12266213 179 throw new Exception(t('History file isn\'t readable or writable'));
4306b184
A
180 }
181 }
182
183 /**
184 * Read JSON history file.
185 */
186 protected function read()
187 {
188 $this->history = FileUtils::readFlatDB($this->historyFilePath, []);
189 if ($this->history === false) {
12266213 190 throw new Exception(t('Could not parse history file'));
4306b184
A
191 }
192 }
193
194 /**
195 * Write JSON history file and delete old entries.
196 */
197 protected function write()
198 {
bdc5152d 199 $comparaison = new DateTime('-' . $this->retentionTime . ' seconds');
4306b184 200 foreach ($this->history as $key => $value) {
813849e5 201 if ($value['datetime'] < $comparaison) {
4306b184
A
202 unset($this->history[$key]);
203 }
204 }
205 FileUtils::writeFlatDB($this->historyFilePath, array_values($this->history));
206 }
207
208 /**
209 * Get the History.
210 *
211 * @return array
212 */
213 public function getHistory()
214 {
d16ca2e2
A
215 if ($this->history === null) {
216 $this->initialize();
217 }
218
4306b184
A
219 return $this->history;
220 }
221}