]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - application/updater/Updater.php
88a7bc7b27337a0c572647f0d2ac1ef3027939db
[github/shaarli/Shaarli.git] / application / updater / Updater.php
1 <?php
2
3 namespace Shaarli\Updater;
4
5 use Shaarli\Bookmark\BookmarkServiceInterface;
6 use Shaarli\Config\ConfigManager;
7 use Shaarli\Updater\Exception\UpdaterException;
8
9 /**
10 * Class Updater.
11 * Used to update stuff when a new Shaarli's version is reached.
12 * Update methods are ran only once, and the stored in a TXT file.
13 */
14 class Updater
15 {
16 /**
17 * @var array Updates which are already done.
18 */
19 protected $doneUpdates;
20
21 /**
22 * @var BookmarkServiceInterface instance.
23 */
24 protected $bookmarkService;
25
26 /**
27 * @var ConfigManager $conf Configuration Manager instance.
28 */
29 protected $conf;
30
31 /**
32 * @var bool True if the user is logged in, false otherwise.
33 */
34 protected $isLoggedIn;
35
36 /**
37 * @var \ReflectionMethod[] List of current class methods.
38 */
39 protected $methods;
40
41 /**
42 * @var string $basePath Shaarli root directory (from HTTP Request)
43 */
44 protected $basePath = null;
45
46 /**
47 * Object constructor.
48 *
49 * @param array $doneUpdates Updates which are already done.
50 * @param BookmarkServiceInterface $linkDB LinksService instance.
51 * @param ConfigManager $conf Configuration Manager instance.
52 * @param boolean $isLoggedIn True if the user is logged in.
53 */
54 public function __construct($doneUpdates, $linkDB, $conf, $isLoggedIn)
55 {
56 $this->doneUpdates = $doneUpdates;
57 $this->bookmarkService = $linkDB;
58 $this->conf = $conf;
59 $this->isLoggedIn = $isLoggedIn;
60
61 // Retrieve all update methods.
62 $class = new \ReflectionClass($this);
63 $this->methods = $class->getMethods();
64 }
65
66 /**
67 * Run all new updates.
68 * Update methods have to start with 'updateMethod' and return true (on success).
69 *
70 * @param string $basePath Shaarli root directory (from HTTP Request)
71 *
72 * @return array An array containing ran updates.
73 *
74 * @throws UpdaterException If something went wrong.
75 */
76 public function update(string $basePath = null)
77 {
78 $updatesRan = [];
79
80 // If the user isn't logged in, exit without updating.
81 if ($this->isLoggedIn !== true) {
82 return $updatesRan;
83 }
84
85 if ($this->methods === null) {
86 throw new UpdaterException('Couldn\'t retrieve LegacyUpdater class methods.');
87 }
88
89 foreach ($this->methods as $method) {
90 // Not an update method or already done, pass.
91 if (! startsWith($method->getName(), 'updateMethod')
92 || in_array($method->getName(), $this->doneUpdates)
93 ) {
94 continue;
95 }
96
97 try {
98 $method->setAccessible(true);
99 $res = $method->invoke($this);
100 // Update method must return true to be considered processed.
101 if ($res === true) {
102 $updatesRan[] = $method->getName();
103 }
104 } catch (\Exception $e) {
105 throw new UpdaterException($method, $e);
106 }
107 }
108
109 $this->doneUpdates = array_merge($this->doneUpdates, $updatesRan);
110
111 return $updatesRan;
112 }
113
114 /**
115 * @return array Updates methods already processed.
116 */
117 public function getDoneUpdates()
118 {
119 return $this->doneUpdates;
120 }
121
122 public function readUpdates(string $updatesFilepath): array
123 {
124 return UpdaterUtils::read_updates_file($updatesFilepath);
125 }
126
127 public function writeUpdates(string $updatesFilepath, array $updates): void
128 {
129 UpdaterUtils::write_updates_file($updatesFilepath, $updates);
130 }
131
132 /**
133 * With the Slim routing system, default header link should be `/subfolder/` instead of `?`.
134 * Otherwise you can not go back to the home page.
135 * Example: `/subfolder/picture-wall` -> `/subfolder/picture-wall?` instead of `/subfolder/`.
136 */
137 public function updateMethodRelativeHomeLink(): bool
138 {
139 if ('?' === trim($this->conf->get('general.header_link'))) {
140 $this->conf->set('general.header_link', $this->basePath . '/', true, true);
141 }
142
143 return true;
144 }
145
146 /**
147 * With the Slim routing system, note bookmarks URL formatted `?abcdef`
148 * should be replaced with `/shaare/abcdef`
149 */
150 public function updateMethodMigrateExistingNotesUrl(): bool
151 {
152 $updated = false;
153
154 foreach ($this->bookmarkService->search() as $bookmark) {
155 if ($bookmark->isNote()
156 && startsWith($bookmark->getUrl(), '?')
157 && 1 === preg_match('/^\?([a-zA-Z0-9-_@]{6})($|&|#)/', $bookmark->getUrl(), $match)
158 ) {
159 $updated = true;
160 $bookmark = $bookmark->setUrl('/shaare/' . $match[1]);
161
162 $this->bookmarkService->set($bookmark, false);
163 }
164 }
165
166 if ($updated) {
167 $this->bookmarkService->save();
168 }
169
170 return true;
171 }
172
173 public function setBasePath(string $basePath): self
174 {
175 $this->basePath = $basePath;
176
177 return $this;
178 }
179 }