Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

435 lines
12 KiB

  1. <?php
  2. use Friendica\Core\Addon;
  3. use Friendica\Core\Config;
  4. use Friendica\Core\L10n;
  5. use Friendica\Core\Logger;
  6. use Friendica\Core\Update;
  7. use Friendica\Core\Worker;
  8. use Friendica\Database\DBA;
  9. use Friendica\DI;
  10. use Friendica\Model\Contact;
  11. use Friendica\Model\GContact;
  12. use Friendica\Model\Item;
  13. use Friendica\Model\User;
  14. use Friendica\Model\Storage;
  15. use Friendica\Util\DateTimeFormat;
  16. use Friendica\Worker\Delivery;
  17. /**
  18. *
  19. * update.php - automatic system update
  20. *
  21. * This function is responsible for doing post update changes to the data
  22. * (not the structure) in the database.
  23. *
  24. * Database structure changes are done in static/dbstructure.config.php
  25. *
  26. * If there is a need for a post process to a structure change, update this file
  27. * by adding a new function at the end with the number of the new DB_UPDATE_VERSION.
  28. *
  29. * The numbered script in this file has to be exactly like the DB_UPDATE_VERSION
  30. *
  31. * Example:
  32. * You are currently on version 4711 and you are preparing changes that demand an update script.
  33. *
  34. * 1. Create a function "update_4712()" here in the update.php
  35. * 2. Apply the needed structural changes in static/dbStructure.php
  36. * 3. Set DB_UPDATE_VERSION in static/dbstructure.config.php to 4712.
  37. *
  38. * If you need to run a script before the database update, name the function "pre_update_4712()"
  39. */
  40. function update_1178()
  41. {
  42. require_once 'mod/profiles.php';
  43. $profiles = q("SELECT `uid`, `about`, `locality`, `pub_keywords`, `gender` FROM `profile` WHERE `is-default`");
  44. foreach ($profiles as $profile) {
  45. if ($profile["about"].$profile["locality"].$profile["pub_keywords"].$profile["gender"] == "") {
  46. continue;
  47. }
  48. $profile["pub_keywords"] = profile_clean_keywords($profile["pub_keywords"]);
  49. $r = q("UPDATE `contact` SET `about` = '%s', `location` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `self` AND `uid` = %d",
  50. DBA::escape($profile["about"]),
  51. DBA::escape($profile["locality"]),
  52. DBA::escape($profile["pub_keywords"]),
  53. DBA::escape($profile["gender"]),
  54. intval($profile["uid"])
  55. );
  56. }
  57. }
  58. function update_1179()
  59. {
  60. if (Config::get('system', 'no_community_page')) {
  61. Config::set('system', 'community_page_style', CP_NO_COMMUNITY_PAGE);
  62. }
  63. // Update the central item storage with uid=0
  64. Worker::add(PRIORITY_LOW, "threadupdate");
  65. return Update::SUCCESS;
  66. }
  67. function update_1181()
  68. {
  69. // Fill the new fields in the term table.
  70. Worker::add(PRIORITY_LOW, "TagUpdate");
  71. return Update::SUCCESS;
  72. }
  73. function update_1189()
  74. {
  75. if (strlen(Config::get('system', 'directory_submit_url')) &&
  76. !strlen(Config::get('system', 'directory'))) {
  77. Config::set('system', 'directory', dirname(Config::get('system', 'directory_submit_url')));
  78. Config::delete('system', 'directory_submit_url');
  79. }
  80. return Update::SUCCESS;
  81. }
  82. function update_1191()
  83. {
  84. Config::set('system', 'maintenance', 1);
  85. if (Addon::isEnabled('forumlist')) {
  86. $addon = 'forumlist';
  87. $addons = Config::get('system', 'addon');
  88. $addons_arr = [];
  89. if ($addons) {
  90. $addons_arr = explode(",", str_replace(" ", "", $addons));
  91. $idx = array_search($addon, $addons_arr);
  92. if ($idx !== false) {
  93. unset($addons_arr[$idx]);
  94. //delete forumlist manually from addon and hook table
  95. // since Addon::uninstall() don't work here
  96. q("DELETE FROM `addon` WHERE `name` = 'forumlist' ");
  97. q("DELETE FROM `hook` WHERE `file` = 'addon/forumlist/forumlist.php' ");
  98. Config::set('system', 'addon', implode(", ", $addons_arr));
  99. }
  100. }
  101. }
  102. // select old formlist addon entries
  103. $r = q("SELECT `uid`, `cat`, `k`, `v` FROM `pconfig` WHERE `cat` = '%s' ",
  104. DBA::escape('forumlist')
  105. );
  106. // convert old forumlist addon entries in new config entries
  107. if (DBA::isResult($r)) {
  108. foreach ($r as $rr) {
  109. $uid = $rr['uid'];
  110. $family = $rr['cat'];
  111. $key = $rr['k'];
  112. $value = $rr['v'];
  113. if ($key === 'randomise') {
  114. DI::pConfig()->delete($uid, $family, $key);
  115. }
  116. if ($key === 'show_on_profile') {
  117. if ($value) {
  118. DI::pConfig()->set($uid, feature, forumlist_profile, $value);
  119. }
  120. DI::pConfig()->delete($uid, $family, $key);
  121. }
  122. if ($key === 'show_on_network') {
  123. if ($value) {
  124. DI::pConfig()->set($uid, feature, forumlist_widget, $value);
  125. }
  126. DI::pConfig()->delete($uid, $family, $key);
  127. }
  128. }
  129. }
  130. Config::set('system', 'maintenance', 0);
  131. return Update::SUCCESS;
  132. }
  133. function update_1203()
  134. {
  135. $r = q("UPDATE `user` SET `account-type` = %d WHERE `page-flags` IN (%d, %d)",
  136. DBA::escape(User::ACCOUNT_TYPE_COMMUNITY),
  137. DBA::escape(User::PAGE_FLAGS_COMMUNITY),
  138. DBA::escape(User::PAGE_FLAGS_PRVGROUP)
  139. );
  140. }
  141. function update_1244()
  142. {
  143. // Sets legacy_password for all legacy hashes
  144. DBA::update('user', ['legacy_password' => true], ['SUBSTR(password, 1, 4) != "$2y$"']);
  145. // All legacy hashes are re-hashed using the new secure hashing function
  146. $stmt = DBA::select('user', ['uid', 'password'], ['legacy_password' => true]);
  147. while ($user = DBA::fetch($stmt)) {
  148. DBA::update('user', ['password' => User::hashPassword($user['password'])], ['uid' => $user['uid']]);
  149. }
  150. // Logged in users are forcibly logged out
  151. DBA::delete('session', ['1 = 1']);
  152. return Update::SUCCESS;
  153. }
  154. function update_1245()
  155. {
  156. $rino = Config::get('system', 'rino_encrypt');
  157. if (!$rino) {
  158. return Update::SUCCESS;
  159. }
  160. Config::set('system', 'rino_encrypt', 1);
  161. return Update::SUCCESS;
  162. }
  163. function update_1247()
  164. {
  165. // Removing hooks with the old name
  166. DBA::e("DELETE FROM `hook`
  167. WHERE `hook` LIKE 'plugin_%'");
  168. // Make sure we install the new renamed ones
  169. Addon::reload();
  170. }
  171. function update_1260()
  172. {
  173. Config::set('system', 'maintenance', 1);
  174. Config::set(
  175. 'system',
  176. 'maintenance_reason',
  177. L10n::t(
  178. '%s: Updating author-id and owner-id in item and thread table. ',
  179. DateTimeFormat::utcNow().' '.date('e')
  180. )
  181. );
  182. $items = DBA::p("SELECT `id`, `owner-link`, `owner-name`, `owner-avatar`, `network` FROM `item`
  183. WHERE `owner-id` = 0 AND `owner-link` != ''");
  184. while ($item = DBA::fetch($items)) {
  185. $contact = ['url' => $item['owner-link'], 'name' => $item['owner-name'],
  186. 'photo' => $item['owner-avatar'], 'network' => $item['network']];
  187. $cid = Contact::getIdForURL($item['owner-link'], 0, false, $contact);
  188. if (empty($cid)) {
  189. continue;
  190. }
  191. Item::update(['owner-id' => $cid], ['id' => $item['id']]);
  192. }
  193. DBA::close($items);
  194. DBA::e("UPDATE `thread` INNER JOIN `item` ON `thread`.`iid` = `item`.`id`
  195. SET `thread`.`owner-id` = `item`.`owner-id` WHERE `thread`.`owner-id` = 0");
  196. $items = DBA::p("SELECT `id`, `author-link`, `author-name`, `author-avatar`, `network` FROM `item`
  197. WHERE `author-id` = 0 AND `author-link` != ''");
  198. while ($item = DBA::fetch($items)) {
  199. $contact = ['url' => $item['author-link'], 'name' => $item['author-name'],
  200. 'photo' => $item['author-avatar'], 'network' => $item['network']];
  201. $cid = Contact::getIdForURL($item['author-link'], 0, false, $contact);
  202. if (empty($cid)) {
  203. continue;
  204. }
  205. Item::update(['author-id' => $cid], ['id' => $item['id']]);
  206. }
  207. DBA::close($items);
  208. DBA::e("UPDATE `thread` INNER JOIN `item` ON `thread`.`iid` = `item`.`id`
  209. SET `thread`.`author-id` = `item`.`author-id` WHERE `thread`.`author-id` = 0");
  210. Config::set('system', 'maintenance', 0);
  211. return Update::SUCCESS;
  212. }
  213. function update_1261()
  214. {
  215. // This fixes the results of an issue in the develop branch of 2018-05.
  216. DBA::update('contact', ['blocked' => false, 'pending' => false], ['uid' => 0, 'blocked' => true, 'pending' => true]);
  217. return Update::SUCCESS;
  218. }
  219. function update_1278()
  220. {
  221. Config::set('system', 'maintenance', 1);
  222. Config::set(
  223. 'system',
  224. 'maintenance_reason',
  225. L10n::t(
  226. '%s: Updating post-type.',
  227. DateTimeFormat::utcNow().' '.date('e')
  228. )
  229. );
  230. Item::update(['post-type' => Item::PT_PAGE], ['bookmark' => true]);
  231. Item::update(['post-type' => Item::PT_PERSONAL_NOTE], ['type' => 'note']);
  232. Config::set('system', 'maintenance', 0);
  233. return Update::SUCCESS;
  234. }
  235. function update_1288()
  236. {
  237. // Updates missing `uri-id` values
  238. DBA::e("UPDATE `item-activity` INNER JOIN `item` ON `item`.`iaid` = `item-activity`.`id` SET `item-activity`.`uri-id` = `item`.`uri-id` WHERE `item-activity`.`uri-id` IS NULL OR `item-activity`.`uri-id` = 0");
  239. DBA::e("UPDATE `item-content` INNER JOIN `item` ON `item`.`icid` = `item-content`.`id` SET `item-content`.`uri-id` = `item`.`uri-id` WHERE `item-content`.`uri-id` IS NULL OR `item-content`.`uri-id` = 0");
  240. return Update::SUCCESS;
  241. }
  242. // Post-update script of PR 5751
  243. function update_1298()
  244. {
  245. $keys = ['gender', 'marital', 'sexual'];
  246. foreach ($keys as $translateKey) {
  247. $allData = DBA::select('profile', ['id', $translateKey]);
  248. $allLangs = L10n::getAvailableLanguages();
  249. $success = 0;
  250. $fail = 0;
  251. foreach ($allData as $key => $data) {
  252. $toTranslate = $data[$translateKey];
  253. if ($toTranslate != '') {
  254. foreach ($allLangs as $key => $lang) {
  255. $a = new \stdClass();
  256. $a->strings = [];
  257. // First we get the the localizations
  258. if (file_exists("view/lang/$lang/strings.php")) {
  259. include "view/lang/$lang/strings.php";
  260. }
  261. if (file_exists("addon/morechoice/lang/$lang/strings.php")) {
  262. include "addon/morechoice/lang/$lang/strings.php";
  263. }
  264. $localizedStrings = $a->strings;
  265. unset($a);
  266. $key = array_search($toTranslate, $localizedStrings);
  267. if ($key !== false) {
  268. break;
  269. }
  270. // defaulting to empty string
  271. $key = '';
  272. }
  273. if ($key == '') {
  274. $fail++;
  275. } else {
  276. DBA::update('profile', [$translateKey => $key], ['id' => $data['id']]);
  277. Logger::notice('Updated contact', ['action' => 'update', 'contact' => $data['id'], "$translateKey" => $key,
  278. 'was' => $data[$translateKey]]);
  279. Worker::add(PRIORITY_LOW, 'ProfileUpdate', $data['id']);
  280. Contact::updateSelfFromUserID($data['id']);
  281. GContact::updateForUser($data['id']);
  282. $success++;
  283. }
  284. }
  285. }
  286. Logger::notice($translateKey . " fix completed", ['action' => 'update', 'translateKey' => $translateKey, 'Success' => $success, 'Fail' => $fail ]);
  287. }
  288. return Update::SUCCESS;
  289. }
  290. function update_1309()
  291. {
  292. $queue = DBA::select('queue', ['id', 'cid', 'guid']);
  293. while ($entry = DBA::fetch($queue)) {
  294. $contact = DBA::selectFirst('contact', ['uid'], ['id' => $entry['cid']]);
  295. if (!DBA::isResult($contact)) {
  296. continue;
  297. }
  298. $item = Item::selectFirst(['id', 'gravity'], ['uid' => $contact['uid'], 'guid' => $entry['guid']]);
  299. if (!DBA::isResult($item)) {
  300. continue;
  301. }
  302. $deliver_options = ['priority' => PRIORITY_MEDIUM, 'dont_fork' => true];
  303. Worker::add($deliver_options, 'Delivery', Delivery::POST, $item['id'], $entry['cid']);
  304. Logger::info('Added delivery worker', ['command' => $cmd, 'item' => $item['id'], 'contact' => $entry['cid']]);
  305. DBA::delete('queue', ['id' => $entry['id']]);
  306. }
  307. return Update::SUCCESS;
  308. }
  309. function update_1315()
  310. {
  311. DBA::delete('item-delivery-data', ['postopts' => '', 'inform' => '', 'queue_count' => 0, 'queue_done' => 0]);
  312. return Update::SUCCESS;
  313. }
  314. function update_1318()
  315. {
  316. DBA::update('profile', ['marital' => "In a relation"], ['marital' => "Unavailable"]);
  317. DBA::update('profile', ['marital' => "Single"], ['marital' => "Available"]);
  318. Worker::add(PRIORITY_LOW, 'ProfileUpdate');
  319. return Update::SUCCESS;
  320. }
  321. function update_1323()
  322. {
  323. $users = DBA::select('user', ['uid']);
  324. while ($user = DBA::fetch($users)) {
  325. Contact::updateSelfFromUserID($user['uid']);
  326. }
  327. DBA::close($users);
  328. return Update::SUCCESS;
  329. }
  330. function update_1327()
  331. {
  332. $contacts = DBA::select('contact', ['uid', 'id', 'blocked', 'readonly'], ["`uid` != ? AND (`blocked` OR `readonly`) AND NOT `pending`", 0]);
  333. while ($contact = DBA::fetch($contacts)) {
  334. Contact::setBlockedForUser($contact['id'], $contact['uid'], $contact['blocked']);
  335. Contact::setIgnoredForUser($contact['id'], $contact['uid'], $contact['readonly']);
  336. }
  337. DBA::close($contacts);
  338. return Update::SUCCESS;
  339. }
  340. function update_1330()
  341. {
  342. $currStorage = Config::get('storage', 'class', '');
  343. // set the name of the storage instead of the classpath as config
  344. if (!empty($currStorage)) {
  345. /** @var Storage\IStorage $currStorage */
  346. if (!Config::set('storage', 'name', $currStorage::getName())) {
  347. return Update::FAILED;
  348. }
  349. // try to delete the class since it isn't needed. This won't work with config files
  350. Config::delete('storage', 'class');
  351. }
  352. // Update attachments and photos
  353. if (!DBA::p("UPDATE `photo` SET `photo`.`backend-class` = SUBSTR(`photo`.`backend-class`, 25) WHERE `photo`.`backend-class` LIKE 'Friendica\\\Model\\\Storage\\\%' ESCAPE '|'") ||
  354. !DBA::p("UPDATE `attach` SET `attach`.`backend-class` = SUBSTR(`attach`.`backend-class`, 25) WHERE `attach`.`backend-class` LIKE 'Friendica\\\Model\\\Storage\\\%' ESCAPE '|'")) {
  355. return Update::FAILED;
  356. };
  357. return Update::SUCCESS;
  358. }