2018-02-09 03:49:49 +00:00
< ? php
/**
2020-02-09 14:45:36 +00:00
* @ copyright Copyright ( C ) 2020 , Friendica
*
* @ license GNU AGPL version 3 or any later version
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*
2018-02-09 03:49:49 +00:00
*/
2020-02-09 14:45:36 +00:00
2018-02-09 03:49:49 +00:00
namespace Friendica\Database ;
2018-10-29 21:20:46 +00:00
use Friendica\Core\Logger ;
2018-08-11 20:40:44 +00:00
use Friendica\Core\Protocol ;
2020-01-19 20:26:42 +00:00
use Friendica\DI ;
2018-02-09 03:49:49 +00:00
use Friendica\Model\Contact ;
2020-05-22 04:19:32 +00:00
use Friendica\Model\GServer ;
2018-07-01 19:02:29 +00:00
use Friendica\Model\Item ;
2018-08-06 16:40:41 +00:00
use Friendica\Model\ItemURI ;
2018-07-19 13:52:05 +00:00
use Friendica\Model\PermissionSet ;
2020-05-03 15:13:40 +00:00
use Friendica\Model\Post\Category ;
2020-04-30 06:09:57 +00:00
use Friendica\Model\Tag ;
2020-01-19 14:24:46 +00:00
use Friendica\Model\UserItem ;
2020-05-09 15:38:40 +00:00
use Friendica\Model\Verb ;
2020-04-30 06:09:57 +00:00
use Friendica\Util\Strings ;
2018-02-09 03:49:49 +00:00
/**
2020-01-19 14:24:46 +00:00
* These database - intensive post update routines are meant to be executed in the background by the cronjob .
*
* If there is a need for a intensive migration after a database structure change , update this file
* by adding a new method at the end with the number of the new DB_UPDATE_VERSION .
2018-02-09 03:49:49 +00:00
*/
class PostUpdate
{
2020-05-15 06:50:20 +00:00
// Needed for the helper function to read from the legacy term table
const OBJECT_TYPE_POST = 1 ;
2018-05-03 20:49:32 +00:00
/**
2020-01-19 06:05:23 +00:00
* Calls the post update functions
2018-05-03 20:49:32 +00:00
*/
public static function update ()
{
if ( ! self :: update1194 ()) {
2018-08-10 21:20:25 +00:00
return false ;
2018-05-03 20:49:32 +00:00
}
if ( ! self :: update1206 ()) {
2018-08-10 21:20:25 +00:00
return false ;
2018-05-03 20:49:32 +00:00
}
2018-07-19 21:56:52 +00:00
if ( ! self :: update1279 ()) {
2018-08-10 21:20:25 +00:00
return false ;
2018-07-06 05:17:44 +00:00
}
2018-08-06 16:40:41 +00:00
if ( ! self :: update1281 ()) {
2018-08-10 21:20:25 +00:00
return false ;
2018-08-06 16:40:41 +00:00
}
2019-01-23 05:02:00 +00:00
if ( ! self :: update1297 ()) {
return false ;
}
2019-08-29 04:06:41 +00:00
if ( ! self :: update1322 ()) {
return false ;
}
2020-01-05 09:10:32 +00:00
if ( ! self :: update1329 ()) {
return false ;
}
2020-04-30 06:09:57 +00:00
if ( ! self :: update1341 ()) {
return false ;
}
if ( ! self :: update1342 ()) {
return false ;
}
2020-05-02 21:27:37 +00:00
if ( ! self :: update1345 ()) {
return false ;
}
2020-05-03 15:13:40 +00:00
if ( ! self :: update1346 ()) {
return false ;
}
2020-05-09 15:38:40 +00:00
if ( ! self :: update1347 ()) {
return false ;
}
2020-05-22 04:19:32 +00:00
if ( ! self :: update1348 ()) {
return false ;
}
if ( ! self :: update1349 ()) {
return false ;
}
2018-08-10 21:20:25 +00:00
return true ;
2018-05-03 20:49:32 +00:00
}
/**
2020-01-19 06:05:23 +00:00
* Updates the " global " field in the item table
2018-05-03 20:49:32 +00:00
*
* @ return bool " true " when the job is done
2019-01-06 21:06:53 +00:00
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
2018-05-03 20:49:32 +00:00
*/
private static function update1194 ()
{
// Was the script completed?
2020-01-19 20:21:13 +00:00
if ( DI :: config () -> get ( " system " , " post_update_version " ) >= 1194 ) {
2018-05-03 20:49:32 +00:00
return true ;
}
2018-10-30 13:58:45 +00:00
Logger :: log ( " Start " , Logger :: DEBUG );
2018-05-03 20:49:32 +00:00
2020-01-19 20:21:13 +00:00
$end_id = DI :: config () -> get ( " system " , " post_update_1194_end " );
2018-05-03 20:49:32 +00:00
if ( ! $end_id ) {
$r = q ( " SELECT `id` FROM `item` WHERE `uid` != 0 ORDER BY `id` DESC LIMIT 1 " );
if ( $r ) {
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( " system " , " post_update_1194_end " , $r [ 0 ][ " id " ]);
2020-01-19 20:21:13 +00:00
$end_id = DI :: config () -> get ( " system " , " post_update_1194_end " );
2018-05-03 20:49:32 +00:00
}
}
2018-10-30 13:58:45 +00:00
Logger :: log ( " End ID: " . $end_id , Logger :: DEBUG );
2018-05-03 20:49:32 +00:00
2020-01-19 20:21:13 +00:00
$start_id = DI :: config () -> get ( " system " , " post_update_1194_start " );
2018-05-03 20:49:32 +00:00
$query1 = " SELECT `item`.`id` FROM `item` " ;
$query2 = " INNER JOIN `item` AS `shadow` ON `item`.`uri` = `shadow`.`uri` AND `shadow`.`uid` = 0 " ;
$query3 = " WHERE `item`.`uid` != 0 AND `item`.`id` >= %d AND `item`.`id` <= %d
AND `item` . `visible` AND NOT `item` . `private`
AND NOT `item` . `deleted` AND NOT `item` . `moderated`
AND `item` . `network` IN ( '%s' , '%s' , '%s' , '' )
AND NOT `item` . `global` " ;
$r = q ( $query1 . $query2 . $query3 . " ORDER BY `item`.`id` LIMIT 1 " ,
intval ( $start_id ), intval ( $end_id ),
2018-08-11 20:40:44 +00:00
DBA :: escape ( Protocol :: DFRN ), DBA :: escape ( Protocol :: DIASPORA ), DBA :: escape ( Protocol :: OSTATUS ));
2018-05-03 20:49:32 +00:00
if ( ! $r ) {
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( " system " , " post_update_version " , 1194 );
2018-10-30 13:58:45 +00:00
Logger :: log ( " Update is done " , Logger :: DEBUG );
2018-05-03 20:49:32 +00:00
return true ;
} else {
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( " system " , " post_update_1194_start " , $r [ 0 ][ " id " ]);
2020-01-19 20:21:13 +00:00
$start_id = DI :: config () -> get ( " system " , " post_update_1194_start " );
2018-05-03 20:49:32 +00:00
}
2018-10-30 13:58:45 +00:00
Logger :: log ( " Start ID: " . $start_id , Logger :: DEBUG );
2018-05-03 20:49:32 +00:00
$r = q ( $query1 . $query2 . $query3 . " ORDER BY `item`.`id` LIMIT 1000,1 " ,
intval ( $start_id ), intval ( $end_id ),
2018-08-11 20:40:44 +00:00
DBA :: escape ( Protocol :: DFRN ), DBA :: escape ( Protocol :: DIASPORA ), DBA :: escape ( Protocol :: OSTATUS ));
2018-05-03 20:49:32 +00:00
if ( $r ) {
$pos_id = $r [ 0 ][ " id " ];
} else {
$pos_id = $end_id ;
}
2018-10-30 13:58:45 +00:00
Logger :: log ( " Progress: Start: " . $start_id . " position: " . $pos_id . " end: " . $end_id , Logger :: DEBUG );
2018-05-03 20:49:32 +00:00
q ( " UPDATE `item` " . $query2 . " SET `item`.`global` = 1 " . $query3 ,
intval ( $start_id ), intval ( $pos_id ),
2018-08-11 20:40:44 +00:00
DBA :: escape ( Protocol :: DFRN ), DBA :: escape ( Protocol :: DIASPORA ), DBA :: escape ( Protocol :: OSTATUS ));
2018-05-03 20:49:32 +00:00
2018-10-30 13:58:45 +00:00
Logger :: log ( " Done " , Logger :: DEBUG );
2018-05-03 20:49:32 +00:00
}
/**
2020-01-19 06:05:23 +00:00
* update the " last-item " field in the " self " contact
2018-05-03 20:49:32 +00:00
*
* This field avoids cost intensive calls in the admin panel and in " nodeinfo "
*
* @ return bool " true " when the job is done
2019-01-06 21:06:53 +00:00
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
2018-05-03 20:49:32 +00:00
*/
private static function update1206 ()
{
// Was the script completed?
2020-01-19 20:21:13 +00:00
if ( DI :: config () -> get ( " system " , " post_update_version " ) >= 1206 ) {
2018-05-03 20:49:32 +00:00
return true ;
}
2018-10-30 13:58:45 +00:00
Logger :: log ( " Start " , Logger :: DEBUG );
2018-05-03 20:49:32 +00:00
$r = q ( " SELECT `contact`.`id`, `contact`.`last-item`,
( SELECT MAX ( `changed` ) FROM `item` USE INDEX ( `uid_wall_changed` ) WHERE `wall` AND `uid` = `user` . `uid` ) AS `lastitem_date`
FROM `user`
INNER JOIN `contact` ON `contact` . `uid` = `user` . `uid` AND `contact` . `self` " );
2018-07-21 12:46:04 +00:00
if ( ! DBA :: isResult ( $r )) {
2018-05-03 20:49:32 +00:00
return false ;
}
foreach ( $r as $user ) {
if ( ! empty ( $user [ " lastitem_date " ]) && ( $user [ " lastitem_date " ] > $user [ " last-item " ])) {
2018-07-20 12:19:26 +00:00
DBA :: update ( 'contact' , [ 'last-item' => $user [ 'lastitem_date' ]], [ 'id' => $user [ 'id' ]]);
2018-05-03 20:49:32 +00:00
}
}
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( " system " , " post_update_version " , 1206 );
2018-10-30 13:58:45 +00:00
Logger :: log ( " Done " , Logger :: DEBUG );
2018-05-03 20:49:32 +00:00
return true ;
}
2018-07-01 19:02:29 +00:00
/**
2020-01-19 06:05:23 +00:00
* update the item related tables
2018-07-01 19:02:29 +00:00
*
* @ return bool " true " when the job is done
2019-01-06 21:06:53 +00:00
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
* @ throws \ImagickException
2018-07-01 19:02:29 +00:00
*/
2018-07-19 21:56:52 +00:00
private static function update1279 ()
2018-07-01 19:02:29 +00:00
{
// Was the script completed?
2020-01-19 20:21:13 +00:00
if ( DI :: config () -> get ( " system " , " post_update_version " ) >= 1279 ) {
2018-07-01 19:02:29 +00:00
return true ;
}
2020-01-19 20:21:13 +00:00
$id = DI :: config () -> get ( " system " , " post_update_version_1279_id " , 0 );
2018-07-01 19:02:29 +00:00
2018-10-30 13:58:45 +00:00
Logger :: log ( " Start from item " . $id , Logger :: DEBUG );
2018-07-01 19:02:29 +00:00
2018-07-15 18:36:20 +00:00
$fields = array_merge ( Item :: MIXED_CONTENT_FIELDLIST , [ 'network' , 'author-id' , 'owner-id' , 'tag' , 'file' ,
2018-07-19 13:52:05 +00:00
'author-name' , 'author-avatar' , 'author-link' , 'owner-name' , 'owner-avatar' , 'owner-link' , 'id' ,
2018-07-19 21:56:52 +00:00
'uid' , 'allow_cid' , 'allow_gid' , 'deny_cid' , 'deny_gid' , 'psid' , 'post-type' , 'bookmark' , 'type' ,
2018-07-27 23:24:26 +00:00
'inform' , 'postopts' , 'icid' ]);
2018-07-01 19:02:29 +00:00
2018-07-15 18:36:20 +00:00
$start_id = $id ;
2018-07-01 19:02:29 +00:00
$rows = 0 ;
2018-07-15 18:36:20 +00:00
$condition = [ " `id` > ? " , $id ];
$params = [ 'order' => [ 'id' ], 'limit' => 10000 ];
$items = Item :: select ( $fields , $condition , $params );
2018-08-28 11:56:25 +00:00
if ( DBA :: errorNo () != 0 ) {
2018-10-29 21:20:46 +00:00
Logger :: log ( 'Database error ' . DBA :: errorNo () . ':' . DBA :: errorMessage ());
2018-08-28 11:56:25 +00:00
return false ;
}
2018-07-01 19:02:29 +00:00
while ( $item = Item :: fetch ( $items )) {
2018-07-15 18:36:20 +00:00
$id = $item [ 'id' ];
if ( empty ( $item [ 'author-id' ])) {
$default = [ 'url' => $item [ 'author-link' ], 'name' => $item [ 'author-name' ],
'photo' => $item [ 'author-avatar' ], 'network' => $item [ 'network' ]];
2020-07-15 21:08:42 +00:00
$item [ 'author-id' ] = Contact :: getIdForURL ( $item [ " author-link " ], 0 , null , $default );
2018-07-01 19:33:42 +00:00
}
2018-07-15 18:36:20 +00:00
if ( empty ( $item [ 'owner-id' ])) {
$default = [ 'url' => $item [ 'owner-link' ], 'name' => $item [ 'owner-name' ],
'photo' => $item [ 'owner-avatar' ], 'network' => $item [ 'network' ]];
2020-07-15 21:08:42 +00:00
$item [ 'owner-id' ] = Contact :: getIdForURL ( $item [ " owner-link " ], 0 , null , $default );
2018-07-01 19:33:42 +00:00
}
2018-07-28 17:11:46 +00:00
if ( empty ( $item [ 'psid' ])) {
2019-11-05 13:27:22 +00:00
$item [ 'psid' ] = PermissionSet :: getIdFromACL (
$item [ 'uid' ],
$item [ 'allow_cid' ],
$item [ 'allow_gid' ],
$item [ 'deny_cid' ],
$item [ 'deny_gid' ]
);
2018-07-19 13:52:05 +00:00
}
2019-11-05 13:27:22 +00:00
$item [ 'allow_cid' ] = null ;
$item [ 'allow_gid' ] = null ;
$item [ 'deny_cid' ] = null ;
$item [ 'deny_gid' ] = null ;
2018-07-19 13:52:05 +00:00
if ( $item [ 'post-type' ] == 0 ) {
if ( ! empty ( $item [ 'type' ]) && ( $item [ 'type' ] == 'note' )) {
$item [ 'post-type' ] = Item :: PT_PERSONAL_NOTE ;
} elseif ( ! empty ( $item [ 'type' ]) && ( $item [ 'type' ] == 'photo' )) {
$item [ 'post-type' ] = Item :: PT_IMAGE ;
} elseif ( ! empty ( $item [ 'bookmark' ]) && $item [ 'bookmark' ]) {
$item [ 'post-type' ] = Item :: PT_PAGE ;
}
}
2018-07-27 23:24:26 +00:00
self :: createLanguage ( $item );
if ( ! empty ( $item [ 'icid' ]) && ! empty ( $item [ 'language' ])) {
DBA :: update ( 'item-content' , [ 'language' => $item [ 'language' ]], [ 'id' => $item [ 'icid' ]]);
}
unset ( $item [ 'language' ]);
2018-07-15 18:36:20 +00:00
Item :: update ( $item , [ 'id' => $id ]);
2018-07-01 19:02:29 +00:00
++ $rows ;
}
2018-07-20 12:19:26 +00:00
DBA :: close ( $items );
2018-07-01 19:02:29 +00:00
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( " system " , " post_update_version_1279_id " , $id );
2018-07-06 05:17:44 +00:00
2018-10-30 13:58:45 +00:00
Logger :: log ( " Processed rows: " . $rows . " - last processed item: " . $id , Logger :: DEBUG );
2018-07-06 05:17:44 +00:00
2018-07-15 18:36:20 +00:00
if ( $start_id == $id ) {
2018-07-27 23:24:26 +00:00
// Set all deprecated fields to "null" if they contain an empty string
$nullfields = [ 'allow_cid' , 'allow_gid' , 'deny_cid' , 'deny_gid' , 'postopts' , 'inform' , 'type' ,
'bookmark' , 'file' , 'location' , 'coord' , 'tag' , 'plink' , 'title' , 'content-warning' ,
'body' , 'app' , 'verb' , 'object-type' , 'object' , 'target-type' , 'target' ,
'author-name' , 'author-link' , 'author-avatar' , 'owner-name' , 'owner-link' , 'owner-avatar' ,
'rendered-hash' , 'rendered-html' ];
foreach ( $nullfields as $field ) {
$fields = [ $field => null ];
$condition = [ $field => '' ];
2018-10-30 13:58:45 +00:00
Logger :: log ( " Setting ' " . $field . " ' to null if empty. " , Logger :: DEBUG );
2018-07-27 23:24:26 +00:00
// Important: This has to be a "DBA::update", not a "Item::update"
DBA :: update ( 'item' , $fields , $condition );
}
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( " system " , " post_update_version " , 1279 );
2018-10-30 13:58:45 +00:00
Logger :: log ( " Done " , Logger :: DEBUG );
2018-07-06 05:17:44 +00:00
return true ;
}
2018-07-15 18:36:20 +00:00
return false ;
2018-07-01 19:02:29 +00:00
}
2018-07-27 23:24:26 +00:00
private static function createLanguage ( & $item )
{
if ( empty ( $item [ 'postopts' ])) {
return ;
}
$opts = explode ( ',' , $item [ 'postopts' ]);
$postopts = [];
foreach ( $opts as $opt ) {
if ( strstr ( $opt , 'lang=' )) {
$language = substr ( $opt , 5 );
} else {
$postopts [] = $opt ;
}
}
if ( empty ( $language )) {
return ;
}
if ( ! empty ( $postopts )) {
$item [ 'postopts' ] = implode ( ',' , $postopts );
} else {
$item [ 'postopts' ] = null ;
}
$lang_pairs = explode ( ':' , $language );
$lang_arr = [];
foreach ( $lang_pairs as $pair ) {
$lang_pair_arr = explode ( ';' , $pair );
if ( count ( $lang_pair_arr ) == 2 ) {
$lang_arr [ $lang_pair_arr [ 0 ]] = $lang_pair_arr [ 1 ];
}
}
$item [ 'language' ] = json_encode ( $lang_arr );
}
2018-08-06 16:40:41 +00:00
/**
2020-01-19 06:05:23 +00:00
* update item - uri data . Prerequisite for the next item structure update .
2018-08-06 16:40:41 +00:00
*
* @ return bool " true " when the job is done
2019-01-06 21:06:53 +00:00
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
2018-08-06 16:40:41 +00:00
*/
private static function update1281 ()
{
// Was the script completed?
2020-01-19 20:21:13 +00:00
if ( DI :: config () -> get ( " system " , " post_update_version " ) >= 1281 ) {
2018-08-06 16:40:41 +00:00
return true ;
}
2020-01-19 20:21:13 +00:00
$id = DI :: config () -> get ( " system " , " post_update_version_1281_id " , 0 );
2018-08-06 16:40:41 +00:00
2018-10-30 13:58:45 +00:00
Logger :: log ( " Start from item " . $id , Logger :: DEBUG );
2018-08-06 16:40:41 +00:00
$fields = [ 'id' , 'guid' , 'uri' , 'uri-id' , 'parent-uri' , 'parent-uri-id' , 'thr-parent' , 'thr-parent-id' ];
$start_id = $id ;
$rows = 0 ;
$condition = [ " `id` > ? " , $id ];
$params = [ 'order' => [ 'id' ], 'limit' => 10000 ];
$items = DBA :: select ( 'item' , $fields , $condition , $params );
2018-08-28 11:56:25 +00:00
if ( DBA :: errorNo () != 0 ) {
2018-10-29 21:20:46 +00:00
Logger :: log ( 'Database error ' . DBA :: errorNo () . ':' . DBA :: errorMessage ());
2018-08-28 11:56:25 +00:00
return false ;
}
2018-08-06 16:40:41 +00:00
while ( $item = DBA :: fetch ( $items )) {
$id = $item [ 'id' ];
if ( empty ( $item [ 'uri' ])) {
// Should not happen
continue ;
} elseif ( empty ( $item [ 'uri-id' ])) {
$item [ 'uri-id' ] = ItemURI :: insert ([ 'uri' => $item [ 'uri' ], 'guid' => $item [ 'guid' ]]);
}
if ( empty ( $item [ 'parent-uri' ])) {
$item [ 'parent-uri-id' ] = $item [ 'uri-id' ];
} elseif ( empty ( $item [ 'parent-uri-id' ])) {
$item [ 'parent-uri-id' ] = ItemURI :: getIdByURI ( $item [ 'parent-uri' ]);
}
// Very old items don't have this field
if ( empty ( $item [ 'thr-parent' ])) {
$item [ 'thr-parent-id' ] = $item [ 'parent-uri-id' ];
} elseif ( empty ( $item [ 'thr-parent-id' ])) {
$item [ 'thr-parent-id' ] = ItemURI :: getIdByURI ( $item [ 'thr-parent' ]);
}
unset ( $item [ 'id' ]);
unset ( $item [ 'guid' ]);
unset ( $item [ 'uri' ]);
unset ( $item [ 'parent-uri' ]);
unset ( $item [ 'thr-parent' ]);
DBA :: update ( 'item' , $item , [ 'id' => $id ]);
++ $rows ;
}
DBA :: close ( $items );
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( " system " , " post_update_version_1281_id " , $id );
2018-08-06 16:40:41 +00:00
2018-10-30 13:58:45 +00:00
Logger :: log ( " Processed rows: " . $rows . " - last processed item: " . $id , Logger :: DEBUG );
2018-08-06 16:40:41 +00:00
if ( $start_id == $id ) {
2018-10-30 13:58:45 +00:00
Logger :: log ( " Updating item-uri in item-activity " , Logger :: DEBUG );
2018-08-06 16:40:41 +00:00
DBA :: e ( " UPDATE `item-activity` INNER JOIN `item-uri` ON `item-uri`.`uri` = `item-activity`.`uri` SET `item-activity`.`uri-id` = `item-uri`.`id` WHERE `item-activity`.`uri-id` IS NULL " );
2018-10-30 13:58:45 +00:00
Logger :: log ( " Updating item-uri in item-content " , Logger :: DEBUG );
2018-08-06 16:40:41 +00:00
DBA :: e ( " UPDATE `item-content` INNER JOIN `item-uri` ON `item-uri`.`uri` = `item-content`.`uri` SET `item-content`.`uri-id` = `item-uri`.`id` WHERE `item-content`.`uri-id` IS NULL " );
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( " system " , " post_update_version " , 1281 );
2018-10-30 13:58:45 +00:00
Logger :: log ( " Done " , Logger :: DEBUG );
2018-08-06 16:40:41 +00:00
return true ;
}
return false ;
}
2019-01-23 05:02:00 +00:00
/**
* Set the delivery queue count to a negative value for all items preceding the feature .
*
* @ return bool " true " when the job is done
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function update1297 ()
{
// Was the script completed?
2020-01-19 20:21:13 +00:00
if ( DI :: config () -> get ( 'system' , 'post_update_version' ) >= 1297 ) {
2019-01-23 05:02:00 +00:00
return true ;
}
2020-08-22 05:22:08 +00:00
if ( ! DBStructure :: existsTable ( 'item-delivery-data' )) {
DI :: config () -> set ( 'system' , 'post_update_version' , 1297 );
return true ;
}
2019-01-23 05:02:00 +00:00
$max_item_delivery_data = DBA :: selectFirst ( 'item-delivery-data' , [ 'iid' ], [ 'queue_count > 0 OR queue_done > 0' ], [ 'order' => [ 'iid' ]]);
$max_iid = $max_item_delivery_data [ 'iid' ];
Logger :: info ( 'Start update1297 with max iid: ' . $max_iid );
$condition = [ '`queue_count` = 0 AND `iid` < ?' , $max_iid ];
DBA :: update ( 'item-delivery-data' , [ 'queue_count' => - 1 ], $condition );
if ( DBA :: errorNo () != 0 ) {
Logger :: error ( 'Database error ' . DBA :: errorNo () . ':' . DBA :: errorMessage ());
return false ;
}
Logger :: info ( 'Processed rows: ' . DBA :: affectedRows ());
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( 'system' , 'post_update_version' , 1297 );
2019-01-23 05:02:00 +00:00
Logger :: info ( 'Done' );
2019-08-29 04:06:41 +00:00
return true ;
}
/**
2019-08-30 05:38:42 +00:00
* Remove contact duplicates
2019-08-29 04:06:41 +00:00
*
* @ return bool " true " when the job is done
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function update1322 ()
{
// Was the script completed?
2020-01-19 20:21:13 +00:00
if ( DI :: config () -> get ( 'system' , 'post_update_version' ) >= 1322 ) {
2019-08-29 04:06:41 +00:00
return true ;
}
Logger :: info ( 'Start' );
2019-08-30 05:52:21 +00:00
$contacts = DBA :: p ( " SELECT `nurl`, `uid` FROM `contact`
2019-08-29 04:06:41 +00:00
WHERE EXISTS ( SELECT `nurl` FROM `contact` AS `c2`
2019-08-29 05:22:29 +00:00
WHERE `c2` . `nurl` = `contact` . `nurl` AND `c2` . `id` != `contact` . `id` AND `c2` . `uid` = `contact` . `uid` AND `c2` . `network` IN ( ? , ? , ? ) AND NOT `deleted` )
AND ( `network` IN ( ? , ? , ? ) OR ( `uid` = ? )) AND NOT `deleted` GROUP BY `nurl` , `uid` " ,
2019-08-29 04:55:36 +00:00
Protocol :: DIASPORA , Protocol :: OSTATUS , Protocol :: ACTIVITYPUB ,
Protocol :: DIASPORA , Protocol :: OSTATUS , Protocol :: ACTIVITYPUB , 0 );
2019-08-29 04:06:41 +00:00
while ( $contact = DBA :: fetch ( $contacts )) {
2019-08-30 05:52:21 +00:00
Logger :: info ( 'Remove duplicates' , [ 'nurl' => $contact [ 'nurl' ], 'uid' => $contact [ 'uid' ]]);
Contact :: removeDuplicates ( $contact [ 'nurl' ], $contact [ 'uid' ]);
2019-08-29 04:06:41 +00:00
}
DBA :: close ( $contact );
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( 'system' , 'post_update_version' , 1322 );
2019-08-29 04:06:41 +00:00
Logger :: info ( 'Done' );
2019-01-23 05:02:00 +00:00
return true ;
}
2020-01-05 09:10:32 +00:00
/**
2020-01-19 06:05:23 +00:00
* update user - item data with notifications
2020-01-05 09:10:32 +00:00
*
* @ return bool " true " when the job is done
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function update1329 ()
{
// Was the script completed?
2020-01-19 20:21:13 +00:00
if ( DI :: config () -> get ( 'system' , 'post_update_version' ) >= 1329 ) {
2020-01-05 09:10:32 +00:00
return true ;
}
2020-01-19 20:21:13 +00:00
$id = DI :: config () -> get ( 'system' , 'post_update_version_1329_id' , 0 );
2020-01-05 09:10:32 +00:00
Logger :: info ( 'Start' , [ 'item' => $id ]);
$start_id = $id ;
$rows = 0 ;
$condition = [ " `id` > ? " , $id ];
$params = [ 'order' => [ 'id' ], 'limit' => 10000 ];
$items = DBA :: select ( 'item' , [ 'id' ], $condition , $params );
if ( DBA :: errorNo () != 0 ) {
Logger :: error ( 'Database error' , [ 'no' => DBA :: errorNo (), 'message' => DBA :: errorMessage ()]);
return false ;
}
while ( $item = DBA :: fetch ( $items )) {
2020-01-05 10:16:01 +00:00
$id = $item [ 'id' ];
2020-01-05 09:10:32 +00:00
UserItem :: setNotification ( $item [ 'id' ]);
++ $rows ;
}
DBA :: close ( $items );
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( 'system' , 'post_update_version_1329_id' , $id );
2020-01-05 09:10:32 +00:00
Logger :: info ( 'Processed' , [ 'rows' => $rows , 'last' => $id ]);
if ( $start_id == $id ) {
2020-01-19 20:21:53 +00:00
DI :: config () -> set ( 'system' , 'post_update_version' , 1329 );
2020-01-05 09:10:32 +00:00
Logger :: info ( 'Done' );
return true ;
}
return false ;
}
2020-04-30 06:09:57 +00:00
/**
* Fill the " tag " table with tags and mentions from the body
*
* @ return bool " true " when the job is done
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function update1341 ()
{
// Was the script completed?
if ( DI :: config () -> get ( 'system' , 'post_update_version' ) >= 1341 ) {
return true ;
}
$id = DI :: config () -> get ( 'system' , 'post_update_version_1341_id' , 0 );
Logger :: info ( 'Start' , [ 'item' => $id ]);
$rows = 0 ;
$items = DBA :: p ( " SELECT `uri-id`,`body` FROM `item-content` WHERE
( `body` LIKE ? OR `body` LIKE ? OR `body` LIKE ? ) AND `uri-id` >= ?
ORDER BY `uri-id` LIMIT 100000 " , '%#%', '%@%', '%!%', $id );
if ( DBA :: errorNo () != 0 ) {
Logger :: error ( 'Database error' , [ 'no' => DBA :: errorNo (), 'message' => DBA :: errorMessage ()]);
return false ;
}
while ( $item = DBA :: fetch ( $items )) {
Tag :: storeFromBody ( $item [ 'uri-id' ], $item [ 'body' ], '#!@' , false );
$id = $item [ 'uri-id' ];
++ $rows ;
if ( $rows % 1000 == 0 ) {
DI :: config () -> set ( 'system' , 'post_update_version_1341_id' , $id );
}
}
DBA :: close ( $items );
DI :: config () -> set ( 'system' , 'post_update_version_1341_id' , $id );
Logger :: info ( 'Processed' , [ 'rows' => $rows , 'last' => $id ]);
2020-04-30 12:13:13 +00:00
// When there are less than 1,000 items processed this means that we reached the end
2020-04-30 09:03:05 +00:00
// The other entries will then be processed with the regular functionality
2020-04-30 12:13:13 +00:00
if ( $rows < 1000 ) {
2020-04-30 06:09:57 +00:00
DI :: config () -> set ( 'system' , 'post_update_version' , 1341 );
Logger :: info ( 'Done' );
return true ;
}
return false ;
}
/**
* Fill the " tag " table with tags and mentions from the " term " table
*
* @ return bool " true " when the job is done
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function update1342 ()
{
// Was the script completed?
if ( DI :: config () -> get ( 'system' , 'post_update_version' ) >= 1342 ) {
return true ;
}
$id = DI :: config () -> get ( 'system' , 'post_update_version_1342_id' , 0 );
Logger :: info ( 'Start' , [ 'item' => $id ]);
$rows = 0 ;
$terms = DBA :: p ( " SELECT `term`.`tid`, `item`.`uri-id`, `term`.`type`, `term`.`term`, `term`.`url`, `item-content`.`body`
FROM `term`
INNER JOIN `item` ON `item` . `id` = `term` . `oid`
INNER JOIN `item-content` ON `item-content` . `uri-id` = `item` . `uri-id`
WHERE term . type IN ( ? , ? , ? , ? ) AND `tid` >= ? ORDER BY `tid` LIMIT 100000 " ,
Tag :: HASHTAG , Tag :: MENTION , Tag :: EXCLUSIVE_MENTION , Tag :: IMPLICIT_MENTION , $id );
if ( DBA :: errorNo () != 0 ) {
Logger :: error ( 'Database error' , [ 'no' => DBA :: errorNo (), 'message' => DBA :: errorMessage ()]);
return false ;
}
while ( $term = DBA :: fetch ( $terms )) {
if (( $term [ 'type' ] == Tag :: MENTION ) && ! empty ( $term [ 'url' ]) && ! strstr ( $term [ 'body' ], $term [ 'url' ])) {
$condition = [ 'nurl' => Strings :: normaliseLink ( $term [ 'url' ]), 'uid' => 0 , 'deleted' => false ];
$contact = DBA :: selectFirst ( 'contact' , [ 'url' , 'alias' ], $condition , [ 'order' => [ 'id' ]]);
if ( ! DBA :: isResult ( $contact )) {
$ssl_url = str_replace ( 'http://' , 'https://' , $term [ 'url' ]);
$condition = [ '`alias` IN (?, ?, ?) AND `uid` = ? AND NOT `deleted`' , $term [ 'url' ], Strings :: normaliseLink ( $term [ 'url' ]), $ssl_url , 0 ];
$contact = DBA :: selectFirst ( 'contact' , [ 'url' , 'alias' ], $condition , [ 'order' => [ 'id' ]]);
}
if ( DBA :: isResult ( $contact ) && ( ! strstr ( $term [ 'body' ], $contact [ 'url' ]) && ( empty ( $contact [ 'alias' ]) || ! strstr ( $term [ 'body' ], $contact [ 'alias' ])))) {
$term [ 'type' ] = Tag :: IMPLICIT_MENTION ;
}
}
Tag :: store ( $term [ 'uri-id' ], $term [ 'type' ], $term [ 'term' ], $term [ 'url' ], false );
$id = $term [ 'tid' ];
++ $rows ;
if ( $rows % 1000 == 0 ) {
DI :: config () -> set ( 'system' , 'post_update_version_1342_id' , $id );
}
}
DBA :: close ( $terms );
DI :: config () -> set ( 'system' , 'post_update_version_1342_id' , $id );
Logger :: info ( 'Processed' , [ 'rows' => $rows , 'last' => $id ]);
2020-04-30 12:13:13 +00:00
// When there are less than 1,000 items processed this means that we reached the end
2020-04-30 09:03:05 +00:00
// The other entries will then be processed with the regular functionality
2020-04-30 12:13:13 +00:00
if ( $rows < 1000 ) {
2020-04-30 06:09:57 +00:00
DI :: config () -> set ( 'system' , 'post_update_version' , 1342 );
Logger :: info ( 'Done' );
return true ;
}
return false ;
}
2020-05-03 15:13:40 +00:00
2020-05-02 21:27:37 +00:00
/**
* Fill the " post-delivery-data " table with data from the " item-delivery-data " table
*
* @ return bool " true " when the job is done
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function update1345 ()
{
// Was the script completed?
if ( DI :: config () -> get ( 'system' , 'post_update_version' ) >= 1345 ) {
return true ;
}
2020-08-22 05:22:08 +00:00
if ( ! DBStructure :: existsTable ( 'item-delivery-data' )) {
DI :: config () -> set ( 'system' , 'post_update_version' , 1345 );
return true ;
}
2020-05-02 21:27:37 +00:00
$id = DI :: config () -> get ( 'system' , 'post_update_version_1345_id' , 0 );
2020-05-05 15:47:35 +00:00
2020-05-02 21:27:37 +00:00
Logger :: info ( 'Start' , [ 'item' => $id ]);
$rows = 0 ;
$deliveries = DBA :: p ( " SELECT `uri-id`, `iid`, `item-delivery-data`.`postopts`, `item-delivery-data`.`inform`,
`queue_count` , `queue_done` , `activitypub` , `dfrn` , `diaspora` , `ostatus` , `legacy_dfrn` , `queue_failed`
FROM `item-delivery-data`
INNER JOIN `item` ON `item` . `id` = `item-delivery-data` . `iid`
WHERE `iid` >= ? ORDER BY `iid` LIMIT 10000 " , $id );
if ( DBA :: errorNo () != 0 ) {
Logger :: error ( 'Database error' , [ 'no' => DBA :: errorNo (), 'message' => DBA :: errorMessage ()]);
return false ;
}
while ( $delivery = DBA :: fetch ( $deliveries )) {
$id = $delivery [ 'iid' ];
unset ( $delivery [ 'iid' ]);
2020-05-05 21:49:48 +00:00
DBA :: insert ( 'post-delivery-data' , $delivery , true );
2020-05-02 21:27:37 +00:00
++ $rows ;
}
DBA :: close ( $deliveries );
DI :: config () -> set ( 'system' , 'post_update_version_1345_id' , $id );
Logger :: info ( 'Processed' , [ 'rows' => $rows , 'last' => $id ]);
// When there are less than 100 items processed this means that we reached the end
// The other entries will then be processed with the regular functionality
if ( $rows < 100 ) {
DI :: config () -> set ( 'system' , 'post_update_version' , 1345 );
Logger :: info ( 'Done' );
return true ;
}
return false ;
}
2020-05-05 15:44:24 +00:00
2020-05-15 06:50:20 +00:00
/**
* Generates the legacy item . file field string from an item ID .
* Includes only file and category terms .
*
* @ param int $item_id
* @ return string
* @ throws \Exception
*/
private static function fileTextFromItemId ( $item_id )
{
$file_text = '' ;
$condition = [ 'otype' => self :: OBJECT_TYPE_POST , 'oid' => $item_id , 'type' => [ Category :: FILE , Category :: CATEGORY ]];
$tags = DBA :: selectToArray ( 'term' , [ 'type' , 'term' , 'url' ], $condition );
foreach ( $tags as $tag ) {
if ( $tag [ 'type' ] == Category :: CATEGORY ) {
$file_text .= '<' . $tag [ 'term' ] . '>' ;
} else {
$file_text .= '[' . $tag [ 'term' ] . ']' ;
}
}
return $file_text ;
}
2020-05-03 15:13:40 +00:00
/**
* Fill the " tag " table with tags and mentions from the " term " table
*
* @ return bool " true " when the job is done
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function update1346 ()
{
// Was the script completed?
if ( DI :: config () -> get ( 'system' , 'post_update_version' ) >= 1346 ) {
return true ;
}
$id = DI :: config () -> get ( 'system' , 'post_update_version_1346_id' , 0 );
Logger :: info ( 'Start' , [ 'item' => $id ]);
$rows = 0 ;
$terms = DBA :: select ( 'term' , [ 'oid' ],
[ " `type` IN (?, ?) AND `oid` >= ? " , Category :: CATEGORY , Category :: FILE , $id ],
[ 'order' => [ 'oid' ], 'limit' => 1000 , 'group_by' => [ 'oid' ]]);
if ( DBA :: errorNo () != 0 ) {
Logger :: error ( 'Database error' , [ 'no' => DBA :: errorNo (), 'message' => DBA :: errorMessage ()]);
return false ;
}
while ( $term = DBA :: fetch ( $terms )) {
$item = Item :: selectFirst ([ 'uri-id' , 'uid' ], [ 'id' => $term [ 'oid' ]]);
if ( ! DBA :: isResult ( $item )) {
continue ;
}
2020-05-15 06:50:20 +00:00
$file = self :: fileTextFromItemId ( $term [ 'oid' ]);
2020-05-03 15:13:40 +00:00
if ( ! empty ( $file )) {
Category :: storeTextByURIId ( $item [ 'uri-id' ], $item [ 'uid' ], $file );
}
$id = $term [ 'oid' ];
++ $rows ;
if ( $rows % 100 == 0 ) {
DI :: config () -> set ( 'system' , 'post_update_version_1346_id' , $id );
}
}
DBA :: close ( $terms );
DI :: config () -> set ( 'system' , 'post_update_version_1346_id' , $id );
Logger :: info ( 'Processed' , [ 'rows' => $rows , 'last' => $id ]);
// When there are less than 10 items processed this means that we reached the end
// The other entries will then be processed with the regular functionality
if ( $rows < 10 ) {
DI :: config () -> set ( 'system' , 'post_update_version' , 1346 );
Logger :: info ( 'Done' );
return true ;
}
return false ;
2020-05-09 15:38:40 +00:00
}
/**
2020-05-31 15:48:31 +00:00
* update the " vid " ( verb ) field in the item table
2020-05-09 15:38:40 +00:00
*
* @ return bool " true " when the job is done
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
* @ throws \ImagickException
*/
private static function update1347 ()
{
// Was the script completed?
if ( DI :: config () -> get ( " system " , " post_update_version " ) >= 1347 ) {
return true ;
}
$id = DI :: config () -> get ( " system " , " post_update_version_1347_id " , 0 );
Logger :: info ( 'Start' , [ 'item' => $id ]);
$start_id = $id ;
$rows = 0 ;
2020-05-26 21:45:57 +00:00
2020-05-31 15:48:31 +00:00
$items = DBA :: p ( " SELECT `item`.`id`, `item`.`verb` AS `item-verb`, `item-content`.`verb`, `item-activity`.`activity`
2020-05-26 21:45:57 +00:00
FROM `item` LEFT JOIN `item-content` ON `item-content` . `uri-id` = `item` . `uri-id`
LEFT JOIN `item-activity` ON `item-activity` . `uri-id` = `item` . `uri-id` AND `item` . `gravity` = ?
2020-05-31 15:48:31 +00:00
WHERE `item` . `id` >= ? AND `item` . `vid` IS NULL ORDER BY `item` . `id` LIMIT 10000 " , GRAVITY_ACTIVITY, $id );
2020-05-09 15:38:40 +00:00
if ( DBA :: errorNo () != 0 ) {
Logger :: error ( 'Database error' , [ 'no' => DBA :: errorNo (), 'message' => DBA :: errorMessage ()]);
return false ;
}
2020-05-26 21:45:57 +00:00
while ( $item = DBA :: fetch ( $items )) {
2020-05-09 15:38:40 +00:00
$id = $item [ 'id' ];
2020-05-26 21:45:57 +00:00
$verb = $item [ 'item-verb' ];
if ( empty ( $verb )) {
$verb = $item [ 'verb' ];
}
if ( empty ( $verb ) && is_int ( $item [ 'activity' ])) {
$verb = Item :: ACTIVITIES [ $item [ 'activity' ]];
}
if ( empty ( $verb )) {
continue ;
}
2020-05-09 15:38:40 +00:00
2020-05-26 21:45:57 +00:00
DBA :: update ( 'item' , [ 'vid' => Verb :: getID ( $verb )], [ 'id' => $item [ 'id' ]]);
2020-05-09 15:38:40 +00:00
++ $rows ;
}
DBA :: close ( $items );
DI :: config () -> set ( " system " , " post_update_version_1347_id " , $id );
Logger :: info ( 'Processed' , [ 'rows' => $rows , 'last' => $id ]);
if ( $start_id == $id ) {
DI :: config () -> set ( " system " , " post_update_version " , 1347 );
Logger :: info ( 'Done' );
return true ;
}
return false ;
}
2020-05-22 04:19:32 +00:00
/**
2020-06-14 16:09:59 +00:00
* update the " gsid " ( global server id ) field in the contact table
2020-05-22 04:19:32 +00:00
*
* @ return bool " true " when the job is done
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
* @ throws \ImagickException
*/
private static function update1348 ()
{
// Was the script completed?
if ( DI :: config () -> get ( " system " , " post_update_version " ) >= 1348 ) {
return true ;
}
$id = DI :: config () -> get ( " system " , " post_update_version_1348_id " , 0 );
Logger :: info ( 'Start' , [ 'contact' => $id ]);
$start_id = $id ;
$rows = 0 ;
$condition = [ " `id` > ? AND `gsid` IS NULL AND `baseurl` != '' AND NOT `baseurl` IS NULL " , $id ];
$params = [ 'order' => [ 'id' ], 'limit' => 10000 ];
$contacts = DBA :: select ( 'contact' , [ 'id' , 'baseurl' ], $condition , $params );
if ( DBA :: errorNo () != 0 ) {
Logger :: error ( 'Database error' , [ 'no' => DBA :: errorNo (), 'message' => DBA :: errorMessage ()]);
return false ;
}
while ( $contact = DBA :: fetch ( $contacts )) {
$id = $contact [ 'id' ];
DBA :: update ( 'contact' ,
2020-06-14 16:09:59 +00:00
[ 'gsid' => GServer :: getID ( $contact [ 'baseurl' ], true ), 'baseurl' => GServer :: cleanURL ( $contact [ 'baseurl' ])],
2020-05-22 04:19:32 +00:00
[ 'id' => $contact [ 'id' ]]);
++ $rows ;
}
DBA :: close ( $contacts );
DI :: config () -> set ( " system " , " post_update_version_1348_id " , $id );
Logger :: info ( 'Processed' , [ 'rows' => $rows , 'last' => $id ]);
if ( $start_id == $id ) {
DI :: config () -> set ( " system " , " post_update_version " , 1348 );
Logger :: info ( 'Done' );
return true ;
}
return false ;
}
/**
2020-06-14 16:09:59 +00:00
* update the " gsid " ( global server id ) field in the apcontact table
2020-05-22 04:19:32 +00:00
*
* @ return bool " true " when the job is done
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
* @ throws \ImagickException
*/
private static function update1349 ()
{
// Was the script completed?
if ( DI :: config () -> get ( " system " , " post_update_version " ) >= 1349 ) {
return true ;
}
2020-06-14 16:09:59 +00:00
$id = DI :: config () -> get ( " system " , " post_update_version_1349_id " , '' );
2020-05-22 04:19:32 +00:00
Logger :: info ( 'Start' , [ 'apcontact' => $id ]);
$start_id = $id ;
$rows = 0 ;
$condition = [ " `url` > ? AND `gsid` IS NULL AND `baseurl` != '' AND NOT `baseurl` IS NULL " , $id ];
$params = [ 'order' => [ 'url' ], 'limit' => 10000 ];
$apcontacts = DBA :: select ( 'apcontact' , [ 'url' , 'baseurl' ], $condition , $params );
if ( DBA :: errorNo () != 0 ) {
Logger :: error ( 'Database error' , [ 'no' => DBA :: errorNo (), 'message' => DBA :: errorMessage ()]);
return false ;
}
while ( $apcontact = DBA :: fetch ( $apcontacts )) {
$id = $apcontact [ 'url' ];
DBA :: update ( 'apcontact' ,
2020-06-14 16:09:59 +00:00
[ 'gsid' => GServer :: getID ( $apcontact [ 'baseurl' ], true ), 'baseurl' => GServer :: cleanURL ( $apcontact [ 'baseurl' ])],
2020-05-22 04:19:32 +00:00
[ 'url' => $apcontact [ 'url' ]]);
++ $rows ;
}
DBA :: close ( $apcontacts );
DI :: config () -> set ( " system " , " post_update_version_1349_id " , $id );
Logger :: info ( 'Processed' , [ 'rows' => $rows , 'last' => $id ]);
if ( $start_id == $id ) {
DI :: config () -> set ( " system " , " post_update_version " , 1349 );
Logger :: info ( 'Done' );
return true ;
}
return false ;
}
2018-02-09 03:49:49 +00:00
}