aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--application/Config.php27
-rw-r--r--application/LinkDB.php10
-rw-r--r--application/LinkFilter.php1
-rw-r--r--application/Updater.php228
-rw-r--r--index.php41
-rw-r--r--plugins/wallabag/wallabag.meta2
-rw-r--r--tests/ConfigTest.php42
-rw-r--r--tests/Updater/DummyUpdater.php68
-rw-r--r--tests/Updater/UpdaterTest.php227
9 files changed, 557 insertions, 89 deletions
diff --git a/application/Config.php b/application/Config.php
index 9af5a535..05a59452 100644
--- a/application/Config.php
+++ b/application/Config.php
@@ -174,33 +174,6 @@ function load_plugin_parameter_values($plugins, $config)
174} 174}
175 175
176/** 176/**
177 * Milestone 0.9 - shaarli/Shaarli#41: options.php is not supported anymore.
178 * ==> if user is loggedIn, merge its content with config.php, then delete options.php.
179 *
180 * @param array $config contains all configuration fields.
181 * @param bool $isLoggedIn true if user is logged in.
182 *
183 * @return void
184 */
185function mergeDeprecatedConfig($config, $isLoggedIn)
186{
187 $config_file = $config['config']['CONFIG_FILE'];
188
189 if (is_file($config['config']['DATADIR'].'/options.php') && $isLoggedIn) {
190 include $config['config']['DATADIR'].'/options.php';
191
192 // Load GLOBALS into config
193 foreach ($GLOBALS as $key => $value) {
194 $config[$key] = $value;
195 }
196 $config['config']['CONFIG_FILE'] = $config_file;
197 writeConfig($config, $isLoggedIn);
198
199 unlink($config['config']['DATADIR'].'/options.php');
200 }
201}
202
203/**
204 * Exception used if a mandatory field is missing in given configuration. 177 * Exception used if a mandatory field is missing in given configuration.
205 */ 178 */
206class MissingFieldConfigException extends Exception 179class MissingFieldConfigException extends Exception
diff --git a/application/LinkDB.php b/application/LinkDB.php
index 19ca6435..a95b3f36 100644
--- a/application/LinkDB.php
+++ b/application/LinkDB.php
@@ -260,14 +260,11 @@ You use the community supported version of the original Shaarli project, by Seba
260 } 260 }
261 } 261 }
262 262
263 // Keep the list of the mapping URLs-->linkdate up-to-date.
264 $this->_urls = array(); 263 $this->_urls = array();
265 foreach ($this->_links as $link) { 264 foreach ($this->_links as &$link) {
265 // Keep the list of the mapping URLs-->linkdate up-to-date.
266 $this->_urls[$link['url']] = $link['linkdate']; 266 $this->_urls[$link['url']] = $link['linkdate'];
267 } 267 // Sanitize data fields.
268
269 // Escape links data
270 foreach($this->_links as &$link) {
271 sanitizeLink($link); 268 sanitizeLink($link);
272 // Do not use the redirector for internal links (Shaarli note URL starting with a '?'). 269 // Do not use the redirector for internal links (Shaarli note URL starting with a '?').
273 if (!empty($this->_redirector) && !startsWith($link['url'], '?')) { 270 if (!empty($this->_redirector) && !startsWith($link['url'], '?')) {
@@ -381,6 +378,7 @@ You use the community supported version of the original Shaarli project, by Seba
381 } 378 }
382 $linkDays = array_keys($linkDays); 379 $linkDays = array_keys($linkDays);
383 sort($linkDays); 380 sort($linkDays);
381
384 return $linkDays; 382 return $linkDays;
385 } 383 }
386} 384}
diff --git a/application/LinkFilter.php b/application/LinkFilter.php
index b2e6530f..096d3b04 100644
--- a/application/LinkFilter.php
+++ b/application/LinkFilter.php
@@ -260,7 +260,6 @@ class LinkFilter
260 * Convert a list of tags (str) to an array. Also 260 * Convert a list of tags (str) to an array. Also
261 * - handle case sensitivity. 261 * - handle case sensitivity.
262 * - accepts spaces commas as separator. 262 * - accepts spaces commas as separator.
263 * - remove private tags for loggedout users.
264 * 263 *
265 * @param string $tags string containing a list of tags. 264 * @param string $tags string containing a list of tags.
266 * @param bool $casesensitive will convert everything to lowercase if false. 265 * @param bool $casesensitive will convert everything to lowercase if false.
diff --git a/application/Updater.php b/application/Updater.php
new file mode 100644
index 00000000..20ae0c4d
--- /dev/null
+++ b/application/Updater.php
@@ -0,0 +1,228 @@
1<?php
2
3/**
4 * Class Updater.
5 * Used to update stuff when a new Shaarli's version is reached.
6 * Update methods are ran only once, and the stored in a JSON file.
7 */
8class Updater
9{
10 /**
11 * @var array Updates which are already done.
12 */
13 protected $doneUpdates;
14
15 /**
16 * @var array Shaarli's configuration array.
17 */
18 protected $config;
19
20 /**
21 * @var LinkDB instance.
22 */
23 protected $linkDB;
24
25 /**
26 * @var bool True if the user is logged in, false otherwise.
27 */
28 protected $isLoggedIn;
29
30 /**
31 * @var ReflectionMethod[] List of current class methods.
32 */
33 protected $methods;
34
35 /**
36 * Object constructor.
37 *
38 * @param array $doneUpdates Updates which are already done.
39 * @param array $config Shaarli's configuration array.
40 * @param LinkDB $linkDB LinkDB instance.
41 * @param boolean $isLoggedIn True if the user is logged in.
42 */
43 public function __construct($doneUpdates, $config, $linkDB, $isLoggedIn)
44 {
45 $this->doneUpdates = $doneUpdates;
46 $this->config = $config;
47 $this->linkDB = $linkDB;
48 $this->isLoggedIn = $isLoggedIn;
49
50 // Retrieve all update methods.
51 $class = new ReflectionClass($this);
52 $this->methods = $class->getMethods();
53 }
54
55 /**
56 * Run all new updates.
57 * Update methods have to start with 'updateMethod' and return true (on success).
58 *
59 * @return array An array containing ran updates.
60 *
61 * @throws UpdaterException If something went wrong.
62 */
63 public function update()
64 {
65 $updatesRan = array();
66
67 // If the user isn't logged in, exit without updating.
68 if ($this->isLoggedIn !== true) {
69 return $updatesRan;
70 }
71
72 if ($this->methods == null) {
73 throw new UpdaterException('Couldn\'t retrieve Updater class methods.');
74 }
75
76 foreach ($this->methods as $method) {
77 // Not an update method or already done, pass.
78 if (! startsWith($method->getName(), 'updateMethod')
79 || in_array($method->getName(), $this->doneUpdates)
80 ) {
81 continue;
82 }
83
84 try {
85 $method->setAccessible(true);
86 $res = $method->invoke($this);
87 // Update method must return true to be considered processed.
88 if ($res === true) {
89 $updatesRan[] = $method->getName();
90 }
91 } catch (Exception $e) {
92 throw new UpdaterException($method, $e);
93 }
94 }
95
96 $this->doneUpdates = array_merge($this->doneUpdates, $updatesRan);
97
98 return $updatesRan;
99 }
100
101 /**
102 * @return array Updates methods already processed.
103 */
104 public function getDoneUpdates()
105 {
106 return $this->doneUpdates;
107 }
108
109 /**
110 * Move deprecated options.php to config.php.
111 *
112 * Milestone 0.9 (old versioning) - shaarli/Shaarli#41:
113 * options.php is not supported anymore.
114 */
115 public function updateMethodMergeDeprecatedConfigFile()
116 {
117 $config_file = $this->config['config']['CONFIG_FILE'];
118
119 if (is_file($this->config['config']['DATADIR'].'/options.php')) {
120 include $this->config['config']['DATADIR'].'/options.php';
121
122 // Load GLOBALS into config
123 foreach ($GLOBALS as $key => $value) {
124 $this->config[$key] = $value;
125 }
126 $this->config['config']['CONFIG_FILE'] = $config_file;
127 writeConfig($this->config, $this->isLoggedIn);
128
129 unlink($this->config['config']['DATADIR'].'/options.php');
130 }
131
132 return true;
133 }
134}
135
136/**
137 * Class UpdaterException.
138 */
139class UpdaterException extends Exception
140{
141 /**
142 * @var string Method where the error occurred.
143 */
144 protected $method;
145
146 /**
147 * @var Exception The parent exception.
148 */
149 protected $previous;
150
151 /**
152 * Constructor.
153 *
154 * @param string $message Force the error message if set.
155 * @param string $method Method where the error occurred.
156 * @param Exception|bool $previous Parent exception.
157 */
158 public function __construct($message = '', $method = '', $previous = false)
159 {
160 $this->method = $method;
161 $this->previous = $previous;
162 $this->message = $this->buildMessage($message);
163 }
164
165 /**
166 * Build the exception error message.
167 *
168 * @param string $message Optional given error message.
169 *
170 * @return string The built error message.
171 */
172 private function buildMessage($message)
173 {
174 $out = '';
175 if (! empty($message)) {
176 $out .= $message . PHP_EOL;
177 }
178
179 if (! empty($this->method)) {
180 $out .= 'An error occurred while running the update '. $this->method . PHP_EOL;
181 }
182
183 if (! empty($this->previous)) {
184 $out .= ' '. $this->previous->getMessage();
185 }
186
187 return $out;
188 }
189}
190
191
192/**
193 * Read the updates file, and return already done updates.
194 *
195 * @param string $updatesFilepath Updates file path.
196 *
197 * @return array Already done update methods.
198 */
199function read_updates_file($updatesFilepath)
200{
201 if (! empty($updatesFilepath) && is_file($updatesFilepath)) {
202 $content = file_get_contents($updatesFilepath);
203 if (! empty($content)) {
204 return explode(';', $content);
205 }
206 }
207 return array();
208}
209
210/**
211 * Write updates file.
212 *
213 * @param string $updatesFilepath Updates file path.
214 * @param array $updates Updates array to write.
215 *
216 * @throws Exception Couldn't write version number.
217 */
218function write_updates_file($updatesFilepath, $updates)
219{
220 if (empty($updatesFilepath)) {
221 throw new Exception('Updates file path is not set, can\'t write updates.');
222 }
223
224 $res = file_put_contents($updatesFilepath, implode(';', $updates));
225 if ($res === false) {
226 throw new Exception('Unable to write updates in '. $updatesFilepath . '.');
227 }
228}
diff --git a/index.php b/index.php
index 30223661..5de60425 100644
--- a/index.php
+++ b/index.php
@@ -44,12 +44,18 @@ $GLOBALS['config']['DATASTORE'] = $GLOBALS['config']['DATADIR'].'/datastore.php'
44// Banned IPs 44// Banned IPs
45$GLOBALS['config']['IPBANS_FILENAME'] = $GLOBALS['config']['DATADIR'].'/ipbans.php'; 45$GLOBALS['config']['IPBANS_FILENAME'] = $GLOBALS['config']['DATADIR'].'/ipbans.php';
46 46
47// Processed updates file.
48$GLOBALS['config']['UPDATES_FILE'] = $GLOBALS['config']['DATADIR'].'/updates.txt';
49
47// Access log 50// Access log
48$GLOBALS['config']['LOG_FILE'] = $GLOBALS['config']['DATADIR'].'/log.txt'; 51$GLOBALS['config']['LOG_FILE'] = $GLOBALS['config']['DATADIR'].'/log.txt';
49 52
50// For updates check of Shaarli 53// For updates check of Shaarli
51$GLOBALS['config']['UPDATECHECK_FILENAME'] = $GLOBALS['config']['DATADIR'].'/lastupdatecheck.txt'; 54$GLOBALS['config']['UPDATECHECK_FILENAME'] = $GLOBALS['config']['DATADIR'].'/lastupdatecheck.txt';
52 55
56// Set ENABLE_UPDATECHECK to disabled by default.
57$GLOBALS['config']['ENABLE_UPDATECHECK'] = false;
58
53// RainTPL cache directory (keep the trailing slash!) 59// RainTPL cache directory (keep the trailing slash!)
54$GLOBALS['config']['RAINTPL_TMP'] = 'tmp/'; 60$GLOBALS['config']['RAINTPL_TMP'] = 'tmp/';
55// Raintpl template directory (keep the trailing slash!) 61// Raintpl template directory (keep the trailing slash!)
@@ -61,7 +67,6 @@ $GLOBALS['config']['CACHEDIR'] = 'cache';
61// Atom & RSS feed cache directory 67// Atom & RSS feed cache directory
62$GLOBALS['config']['PAGECACHE'] = 'pagecache'; 68$GLOBALS['config']['PAGECACHE'] = 'pagecache';
63 69
64
65/* 70/*
66 * Global configuration 71 * Global configuration
67 */ 72 */
@@ -111,7 +116,8 @@ $GLOBALS['config']['UPDATECHECK_INTERVAL'] = 86400;
111//); 116//);
112$GLOBALS['config']['ENABLED_PLUGINS'] = array('qrcode'); 117$GLOBALS['config']['ENABLED_PLUGINS'] = array('qrcode');
113 118
114//$GLOBALS['plugins']['WALLABAG_URL'] = 'https://demo.wallabag.org/'; 119// Initialize plugin parameters array.
120$GLOBALS['plugins'] = array();
115 121
116// PubSubHubbub support. Put an empty string to disable, or put your hub url here to enable. 122// PubSubHubbub support. Put an empty string to disable, or put your hub url here to enable.
117$GLOBALS['config']['PUBSUBHUB_URL'] = ''; 123$GLOBALS['config']['PUBSUBHUB_URL'] = '';
@@ -159,6 +165,7 @@ require_once 'application/Utils.php';
159require_once 'application/Config.php'; 165require_once 'application/Config.php';
160require_once 'application/PluginManager.php'; 166require_once 'application/PluginManager.php';
161require_once 'application/Router.php'; 167require_once 'application/Router.php';
168require_once 'application/Updater.php';
162 169
163// Ensure the PHP version is supported 170// Ensure the PHP version is supported
164try { 171try {
@@ -1110,6 +1117,25 @@ function renderPage()
1110 $GLOBALS['redirector'] 1117 $GLOBALS['redirector']
1111 ); 1118 );
1112 1119
1120 $updater = new Updater(
1121 read_updates_file($GLOBALS['config']['UPDATES_FILE']),
1122 $GLOBALS,
1123 $LINKSDB,
1124 isLoggedIn()
1125 );
1126 try {
1127 $newUpdates = $updater->update();
1128 if (! empty($newUpdates)) {
1129 write_updates_file(
1130 $GLOBALS['config']['UPDATES_FILE'],
1131 $updater->getDoneUpdates()
1132 );
1133 }
1134 }
1135 catch(Exception $e) {
1136 die($e->getMessage());
1137 }
1138
1113 $PAGE = new pageBuilder; 1139 $PAGE = new pageBuilder;
1114 1140
1115 // Determine which page will be rendered. 1141 // Determine which page will be rendered.
@@ -1119,9 +1145,9 @@ function renderPage()
1119 // Call plugin hooks for header, footer and includes, specifying which page will be rendered. 1145 // Call plugin hooks for header, footer and includes, specifying which page will be rendered.
1120 // Then assign generated data to RainTPL. 1146 // Then assign generated data to RainTPL.
1121 $common_hooks = array( 1147 $common_hooks = array(
1148 'includes',
1122 'header', 1149 'header',
1123 'footer', 1150 'footer',
1124 'includes',
1125 ); 1151 );
1126 $pluginManager = PluginManager::getInstance(); 1152 $pluginManager = PluginManager::getInstance();
1127 foreach($common_hooks as $name) { 1153 foreach($common_hooks as $name) {
@@ -2536,15 +2562,6 @@ function resizeImage($filepath)
2536 return true; 2562 return true;
2537} 2563}
2538 2564
2539try {
2540 mergeDeprecatedConfig($GLOBALS, isLoggedIn());
2541} catch(Exception $e) {
2542 error_log(
2543 'ERROR while merging deprecated options.php file.' . PHP_EOL .
2544 $e->getMessage()
2545 );
2546}
2547
2548if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=genthumbnail')) { genThumbnail(); exit; } // Thumbnail generation/cache does not need the link database. 2565if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=genthumbnail')) { genThumbnail(); exit; } // Thumbnail generation/cache does not need the link database.
2549if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=rss')) { showRSS(); exit; } 2566if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=rss')) { showRSS(); exit; }
2550if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=atom')) { showATOM(); exit; } 2567if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=atom')) { showATOM(); exit; }
diff --git a/plugins/wallabag/wallabag.meta b/plugins/wallabag/wallabag.meta
index 8763c4a2..26e1ea63 100644
--- a/plugins/wallabag/wallabag.meta
+++ b/plugins/wallabag/wallabag.meta
@@ -1,2 +1,2 @@
1description="For each link, add a Wallabag icon to save it in your instance." 1description="For each link, add a Wallabag icon to save it in your instance."
2parameters="WALLABAG_URL" \ No newline at end of file 2parameters="WALLABAG_URL;WALLABAG_VERSION" \ No newline at end of file
diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php
index 492ddd3b..7200aae6 100644
--- a/tests/ConfigTest.php
+++ b/tests/ConfigTest.php
@@ -134,48 +134,6 @@ class ConfigTest extends PHPUnit_Framework_TestCase
134 } 134 }
135 135
136 /** 136 /**
137 * Test mergeDeprecatedConfig while being logged in:
138 * 1. init a config file.
139 * 2. init a options.php file with update value.
140 * 3. merge.
141 * 4. check updated value in config file.
142 */
143 public function testMergeDeprecatedConfig()
144 {
145 // init
146 writeConfig(self::$configFields, true);
147 $configCopy = self::$configFields;
148 $invert = !$configCopy['privateLinkByDefault'];
149 $configCopy['privateLinkByDefault'] = $invert;
150
151 // Use writeConfig to create a options.php
152 $configCopy['config']['CONFIG_FILE'] = 'tests/options.php';
153 writeConfig($configCopy, true);
154
155 $this->assertTrue(is_file($configCopy['config']['CONFIG_FILE']));
156
157 // merge configs
158 mergeDeprecatedConfig(self::$configFields, true);
159
160 // make sure updated field is changed
161 include self::$configFields['config']['CONFIG_FILE'];
162 $this->assertEquals($invert, $GLOBALS['privateLinkByDefault']);
163 $this->assertFalse(is_file($configCopy['config']['CONFIG_FILE']));
164 }
165
166 /**
167 * Test mergeDeprecatedConfig while being logged in without options file.
168 */
169 public function testMergeDeprecatedConfigNoFile()
170 {
171 writeConfig(self::$configFields, true);
172 mergeDeprecatedConfig(self::$configFields, true);
173
174 include self::$configFields['config']['CONFIG_FILE'];
175 $this->assertEquals(self::$configFields['login'], $GLOBALS['login']);
176 }
177
178 /**
179 * Test save_plugin_config with valid data. 137 * Test save_plugin_config with valid data.
180 * 138 *
181 * @throws PluginConfigOrderException 139 * @throws PluginConfigOrderException
diff --git a/tests/Updater/DummyUpdater.php b/tests/Updater/DummyUpdater.php
new file mode 100644
index 00000000..e9ef2aaa
--- /dev/null
+++ b/tests/Updater/DummyUpdater.php
@@ -0,0 +1,68 @@
1<?php
2
3require_once 'application/Updater.php';
4
5/**
6 * Class DummyUpdater.
7 * Extends Updater to add update method designed for unit tests.
8 */
9class DummyUpdater extends Updater
10{
11 /**
12 * Object constructor.
13 *
14 * @param array $doneUpdates Updates which are already done.
15 * @param array $config Shaarli's configuration array.
16 * @param LinkDB $linkDB LinkDB instance.
17 * @param boolean $isLoggedIn True if the user is logged in.
18 */
19 public function __construct($doneUpdates, $config, $linkDB, $isLoggedIn)
20 {
21 parent::__construct($doneUpdates, $config, $linkDB, $isLoggedIn);
22
23 // Retrieve all update methods.
24 // For unit test, only retrieve final methods,
25 $class = new ReflectionClass($this);
26 $this->methods = $class->getMethods(ReflectionMethod::IS_FINAL);
27 }
28
29 /**
30 * Update method 1.
31 *
32 * @return bool true.
33 */
34 private final function updateMethodDummy1()
35 {
36 return true;
37 }
38
39 /**
40 * Update method 2.
41 *
42 * @return bool true.
43 */
44 private final function updateMethodDummy2()
45 {
46 return true;
47 }
48
49 /**
50 * Update method 3.
51 *
52 * @return bool true.
53 */
54 private final function updateMethodDummy3()
55 {
56 return true;
57 }
58
59 /**
60 * Update method 4, raise an exception.
61 *
62 * @throws Exception error.
63 */
64 private final function updateMethodException()
65 {
66 throw new Exception('whatever');
67 }
68}
diff --git a/tests/Updater/UpdaterTest.php b/tests/Updater/UpdaterTest.php
new file mode 100644
index 00000000..63ed5e03
--- /dev/null
+++ b/tests/Updater/UpdaterTest.php
@@ -0,0 +1,227 @@
1<?php
2
3require_once 'tests/Updater/DummyUpdater.php';
4
5/**
6 * Class UpdaterTest.
7 * Runs unit tests against the Updater class.
8 */
9class UpdaterTest extends PHPUnit_Framework_TestCase
10{
11 /**
12 * @var array Configuration input set.
13 */
14 private static $configFields;
15
16 /**
17 * Executed before each test.
18 */
19 public function setUp()
20 {
21 self::$configFields = array(
22 'login' => 'login',
23 'hash' => 'hash',
24 'salt' => 'salt',
25 'timezone' => 'Europe/Paris',
26 'title' => 'title',
27 'titleLink' => 'titleLink',
28 'redirector' => '',
29 'disablesessionprotection' => false,
30 'privateLinkByDefault' => false,
31 'config' => array(
32 'CONFIG_FILE' => 'tests/Updater/config.php',
33 'DATADIR' => 'tests/Updater',
34 'config1' => 'config1data',
35 'config2' => 'config2data',
36 )
37 );
38 }
39
40 /**
41 * Executed after each test.
42 *
43 * @return void
44 */
45 public function tearDown()
46 {
47 if (is_file(self::$configFields['config']['CONFIG_FILE'])) {
48 unlink(self::$configFields['config']['CONFIG_FILE']);
49 }
50
51 if (is_file(self::$configFields['config']['DATADIR'] . '/options.php')) {
52 unlink(self::$configFields['config']['DATADIR'] . '/options.php');
53 }
54
55 if (is_file(self::$configFields['config']['DATADIR'] . '/updates.json')) {
56 unlink(self::$configFields['config']['DATADIR'] . '/updates.json');
57 }
58 }
59
60 /**
61 * Test read_updates_file with an empty/missing file.
62 */
63 public function testReadEmptyUpdatesFile()
64 {
65 $this->assertEquals(array(), read_updates_file(''));
66 $updatesFile = self::$configFields['config']['DATADIR'] . '/updates.json';
67 touch($updatesFile);
68 $this->assertEquals(array(), read_updates_file($updatesFile));
69 }
70
71 /**
72 * Test read/write updates file.
73 */
74 public function testReadWriteUpdatesFile()
75 {
76 $updatesFile = self::$configFields['config']['DATADIR'] . '/updates.json';
77 $updatesMethods = array('m1', 'm2', 'm3');
78
79 write_updates_file($updatesFile, $updatesMethods);
80 $readMethods = read_updates_file($updatesFile);
81 $this->assertEquals($readMethods, $updatesMethods);
82
83 // Update
84 $updatesMethods[] = 'm4';
85 write_updates_file($updatesFile, $updatesMethods);
86 $readMethods = read_updates_file($updatesFile);
87 $this->assertEquals($readMethods, $updatesMethods);
88 }
89
90 /**
91 * Test errors in write_updates_file(): empty updates file.
92 *
93 * @expectedException Exception
94 * @expectedExceptionMessageRegExp /Updates file path is not set(.*)/
95 */
96 public function testWriteEmptyUpdatesFile()
97 {
98 write_updates_file('', array('test'));
99 }
100
101 /**
102 * Test errors in write_updates_file(): not writable updates file.
103 *
104 * @expectedException Exception
105 * @expectedExceptionMessageRegExp /Unable to write(.*)/
106 */
107 public function testWriteUpdatesFileNotWritable()
108 {
109 $updatesFile = self::$configFields['config']['DATADIR'] . '/updates.json';
110 touch($updatesFile);
111 chmod($updatesFile, 0444);
112 @write_updates_file($updatesFile, array('test'));
113 }
114
115 /**
116 * Test the update() method, with no update to run.
117 * 1. Everything already run.
118 * 2. User is logged out.
119 */
120 public function testNoUpdates()
121 {
122 $updates = array(
123 'updateMethodDummy1',
124 'updateMethodDummy2',
125 'updateMethodDummy3',
126 'updateMethodException',
127 );
128 $updater = new DummyUpdater($updates, array(), array(), true);
129 $this->assertEquals(array(), $updater->update());
130
131 $updater = new DummyUpdater(array(), array(), array(), false);
132 $this->assertEquals(array(), $updater->update());
133 }
134
135 /**
136 * Test the update() method, with all updates to run (except the failing one).
137 */
138 public function testUpdatesFirstTime()
139 {
140 $updates = array('updateMethodException',);
141 $expectedUpdates = array(
142 'updateMethodDummy1',
143 'updateMethodDummy2',
144 'updateMethodDummy3',
145 );
146 $updater = new DummyUpdater($updates, array(), array(), true);
147 $this->assertEquals($expectedUpdates, $updater->update());
148 }
149
150 /**
151 * Test the update() method, only one update to run.
152 */
153 public function testOneUpdate()
154 {
155 $updates = array(
156 'updateMethodDummy1',
157 'updateMethodDummy3',
158 'updateMethodException',
159 );
160 $expectedUpdate = array('updateMethodDummy2');
161
162 $updater = new DummyUpdater($updates, array(), array(), true);
163 $this->assertEquals($expectedUpdate, $updater->update());
164 }
165
166 /**
167 * Test Update failed.
168 *
169 * @expectedException UpdaterException
170 */
171 public function testUpdateFailed()
172 {
173 $updates = array(
174 'updateMethodDummy1',
175 'updateMethodDummy2',
176 'updateMethodDummy3',
177 );
178
179 $updater = new DummyUpdater($updates, array(), array(), true);
180 $updater->update();
181 }
182
183 /**
184 * Test update mergeDeprecatedConfig:
185 * 1. init a config file.
186 * 2. init a options.php file with update value.
187 * 3. merge.
188 * 4. check updated value in config file.
189 */
190 public function testUpdateMergeDeprecatedConfig()
191 {
192 // init
193 writeConfig(self::$configFields, true);
194 $configCopy = self::$configFields;
195 $invert = !$configCopy['privateLinkByDefault'];
196 $configCopy['privateLinkByDefault'] = $invert;
197
198 // Use writeConfig to create a options.php
199 $configCopy['config']['CONFIG_FILE'] = 'tests/Updater/options.php';
200 writeConfig($configCopy, true);
201
202 $this->assertTrue(is_file($configCopy['config']['CONFIG_FILE']));
203
204 // merge configs
205 $updater = new Updater(array(), self::$configFields, array(), true);
206 $updater->updateMethodMergeDeprecatedConfigFile();
207
208 // make sure updated field is changed
209 include self::$configFields['config']['CONFIG_FILE'];
210 $this->assertEquals($invert, $GLOBALS['privateLinkByDefault']);
211 $this->assertFalse(is_file($configCopy['config']['CONFIG_FILE']));
212 }
213
214 /**
215 * Test mergeDeprecatedConfig in without options file.
216 */
217 public function testMergeDeprecatedConfigNoFile()
218 {
219 writeConfig(self::$configFields, true);
220
221 $updater = new Updater(array(), self::$configFields, array(), true);
222 $updater->updateMethodMergeDeprecatedConfigFile();
223
224 include self::$configFields['config']['CONFIG_FILE'];
225 $this->assertEquals(self::$configFields['login'], $GLOBALS['login']);
226 }
227}