aboutsummaryrefslogtreecommitdiffhomepage
path: root/application/History.php
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2017-05-06 17:12:06 +0200
committerGitHub <noreply@github.com>2017-05-06 17:12:06 +0200
commitf9ff7f1b69f19b42569ffa67280807ba56f5d48a (patch)
tree22126f1de7aac6c03a0b2c609380057740b840ac /application/History.php
parenta271c5f34f99bab38a167d491b69e5942cd6da94 (diff)
parentd16ca2e22f3d7325fc9593fccd8523eebe226567 (diff)
downloadShaarli-f9ff7f1b69f19b42569ffa67280807ba56f5d48a.tar.gz
Shaarli-f9ff7f1b69f19b42569ffa67280807ba56f5d48a.tar.zst
Shaarli-f9ff7f1b69f19b42569ffa67280807ba56f5d48a.zip
Merge pull request #764 from ArthurHoaro/feature/history
History mechanism
Diffstat (limited to 'application/History.php')
-rw-r--r--application/History.php200
1 files changed, 200 insertions, 0 deletions
diff --git a/application/History.php b/application/History.php
new file mode 100644
index 00000000..f93b0356
--- /dev/null
+++ b/application/History.php
@@ -0,0 +1,200 @@
1<?php
2
3/**
4 * Class History
5 *
6 * Handle the history file tracing events in Shaarli.
7 * The history is stored as JSON in a file set by 'resource.history' setting.
8 *
9 * Available data:
10 * - event: event key
11 * - datetime: event date, in ISO8601 format.
12 * - id: event item identifier (currently only link IDs).
13 *
14 * Available event keys:
15 * - CREATED: new link
16 * - UPDATED: link updated
17 * - DELETED: link deleted
18 * - SETTINGS: the settings have been updated through the UI.
19 *
20 * Note: new events are put at the beginning of the file and history array.
21 */
22class History
23{
24 /**
25 * @var string Action key: a new link has been created.
26 */
27 const CREATED = 'CREATED';
28
29 /**
30 * @var string Action key: a link has been updated.
31 */
32 const UPDATED = 'UPDATED';
33
34 /**
35 * @var string Action key: a link has been deleted.
36 */
37 const DELETED = 'DELETED';
38
39 /**
40 * @var string Action key: settings have been updated.
41 */
42 const SETTINGS = 'SETTINGS';
43
44 /**
45 * @var string History file path.
46 */
47 protected $historyFilePath;
48
49 /**
50 * @var array History data.
51 */
52 protected $history;
53
54 /**
55 * @var int History retention time in seconds (1 month).
56 */
57 protected $retentionTime = 2678400;
58
59 /**
60 * History constructor.
61 *
62 * @param string $historyFilePath History file path.
63 * @param int $retentionTime History content rentention time in seconds.
64 *
65 * @throws Exception if something goes wrong.
66 */
67 public function __construct($historyFilePath, $retentionTime = null)
68 {
69 $this->historyFilePath = $historyFilePath;
70 if ($retentionTime !== null) {
71 $this->retentionTime = $retentionTime;
72 }
73 }
74
75 /**
76 * Initialize: read history file.
77 *
78 * Allow lazy loading (don't read the file if it isn't necessary).
79 */
80 protected function initialize()
81 {
82 $this->check();
83 $this->read();
84 }
85
86 /**
87 * Add Event: new link.
88 *
89 * @param array $link Link data.
90 */
91 public function addLink($link)
92 {
93 $this->addEvent(self::CREATED, $link['id']);
94 }
95
96 /**
97 * Add Event: update existing link.
98 *
99 * @param array $link Link data.
100 */
101 public function updateLink($link)
102 {
103 $this->addEvent(self::UPDATED, $link['id']);
104 }
105
106 /**
107 * Add Event: delete existing link.
108 *
109 * @param array $link Link data.
110 */
111 public function deleteLink($link)
112 {
113 $this->addEvent(self::DELETED, $link['id']);
114 }
115
116 /**
117 * Add Event: settings updated.
118 */
119 public function updateSettings()
120 {
121 $this->addEvent(self::SETTINGS);
122 }
123
124 /**
125 * Save a new event and write it in the history file.
126 *
127 * @param string $status Event key, should be defined as constant.
128 * @param mixed $id Event item identifier (e.g. link ID).
129 */
130 protected function addEvent($status, $id = null)
131 {
132 if ($this->history === null) {
133 $this->initialize();
134 }
135
136 $item = [
137 'event' => $status,
138 'datetime' => (new DateTime())->format(DateTime::ATOM),
139 'id' => $id !== null ? $id : '',
140 ];
141 $this->history = array_merge([$item], $this->history);
142 $this->write();
143 }
144
145 /**
146 * Check that the history file is writable.
147 * Create the file if it doesn't exist.
148 *
149 * @throws Exception if it isn't writable.
150 */
151 protected function check()
152 {
153 if (! is_file($this->historyFilePath)) {
154 FileUtils::writeFlatDB($this->historyFilePath, []);
155 }
156
157 if (! is_writable($this->historyFilePath)) {
158 throw new Exception('History file isn\'t readable or writable');
159 }
160 }
161
162 /**
163 * Read JSON history file.
164 */
165 protected function read()
166 {
167 $this->history = FileUtils::readFlatDB($this->historyFilePath, []);
168 if ($this->history === false) {
169 throw new Exception('Could not parse history file');
170 }
171 }
172
173 /**
174 * Write JSON history file and delete old entries.
175 */
176 protected function write()
177 {
178 $comparaison = new DateTime('-'. $this->retentionTime . ' seconds');
179 foreach ($this->history as $key => $value) {
180 if (DateTime::createFromFormat(DateTime::ATOM, $value['datetime']) < $comparaison) {
181 unset($this->history[$key]);
182 }
183 }
184 FileUtils::writeFlatDB($this->historyFilePath, array_values($this->history));
185 }
186
187 /**
188 * Get the History.
189 *
190 * @return array
191 */
192 public function getHistory()
193 {
194 if ($this->history === null) {
195 $this->initialize();
196 }
197
198 return $this->history;
199 }
200}