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