2010-07-18 15:02:55 +02:00
< ? php
2016-11-24 01:11:22 +01:00
/**
* @ file include / items . php
*/
2017-04-30 06:07:00 +02:00
use Friendica\App ;
2017-12-04 15:04:36 +01:00
use Friendica\Content\Feature ;
2018-01-17 19:42:40 +01:00
use Friendica\Core\Addon ;
2017-07-23 07:51:55 +02:00
use Friendica\Core\Config ;
2018-01-21 19:33:59 +01:00
use Friendica\Core\L10n ;
2017-11-07 03:22:52 +01:00
use Friendica\Core\PConfig ;
2017-11-05 13:15:53 +01:00
use Friendica\Core\Worker ;
2017-11-15 16:53:16 +01:00
use Friendica\Core\System ;
2017-11-08 04:57:46 +01:00
use Friendica\Database\DBM ;
2017-12-07 15:04:24 +01:00
use Friendica\Model\Contact ;
2017-12-07 15:09:28 +01:00
use Friendica\Model\GContact ;
2017-12-09 19:45:17 +01:00
use Friendica\Model\Group ;
2018-01-10 18:05:20 +01:00
use Friendica\Model\Term ;
2017-12-09 19:45:17 +01:00
use Friendica\Model\User ;
2018-01-16 23:23:19 +01:00
use Friendica\Model\Item ;
2018-01-21 00:52:54 +01:00
use Friendica\Model\Conversation ;
2017-12-07 14:56:11 +01:00
use Friendica\Object\Image ;
2017-11-08 04:57:46 +01:00
use Friendica\Protocol\DFRN ;
2017-11-16 05:09:11 +01:00
use Friendica\Protocol\OStatus ;
2017-12-13 08:02:52 +01:00
use Friendica\Protocol\Feed ;
2018-01-04 18:03:15 +01:00
use Friendica\Util\ParseUrl ;
2016-11-24 01:11:22 +01:00
2017-04-08 19:30:35 +02:00
require_once 'include/bbcode.php' ;
require_once 'include/tags.php' ;
require_once 'include/text.php' ;
require_once 'include/threads.php' ;
require_once 'include/plaintext.php' ;
require_once 'mod/share.php' ;
require_once 'include/enotify.php' ;
2012-07-07 01:09:23 +02:00
/* limit_body_size ()
*
2018-01-04 03:12:19 +01:00
*
*
2012-07-07 01:09:23 +02:00
*/
2018-01-04 03:12:19 +01:00
/**
* The purpose of this function is to apply system message length limits to
* imported messages without including any embedded photos in the length
*
* @ brief Truncates imported message body string length to max_import_size
* @ param string $body
* @ return string
*/
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2018-01-04 03:12:19 +01:00
function limit_body_size ( $body )
{
2012-07-07 01:09:23 +02:00
$maxlen = get_max_import_size ();
// If the length of the body, including the embedded images, is smaller
2012-07-08 00:20:24 +02:00
// than the maximum, then don't waste time looking for the images
2016-10-22 12:14:41 +02:00
if ( $maxlen && ( strlen ( $body ) > $maxlen )) {
2012-07-07 01:09:23 +02:00
2012-07-08 00:20:24 +02:00
logger ( 'limit_body_size: the total body length exceeds the limit' , LOGGER_DEBUG );
$orig_body = $body ;
$new_body = '' ;
$textlen = 0 ;
2012-07-07 01:09:23 +02:00
2012-07-08 00:20:24 +02:00
$img_start = strpos ( $orig_body , '[img' );
$img_st_close = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), ']' ) : false );
$img_end = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), '[/img]' ) : false );
2017-04-08 19:30:35 +02:00
while (( $img_st_close !== false ) && ( $img_end !== false )) {
2012-07-07 01:09:23 +02:00
2012-07-08 00:20:24 +02:00
$img_st_close ++ ; // make it point to AFTER the closing bracket
$img_end += $img_start ;
$img_end += strlen ( '[/img]' );
2012-07-07 01:09:23 +02:00
2016-10-22 12:14:41 +02:00
if ( ! strcmp ( substr ( $orig_body , $img_start + $img_st_close , 5 ), 'data:' )) {
2012-07-08 00:20:24 +02:00
// This is an embedded image
2012-07-07 01:09:23 +02:00
2017-04-08 19:30:35 +02:00
if (( $textlen + $img_start ) > $maxlen ) {
2016-10-22 12:14:41 +02:00
if ( $textlen < $maxlen ) {
2012-07-08 00:20:24 +02:00
logger ( 'limit_body_size: the limit happens before an embedded image' , LOGGER_DEBUG );
$new_body = $new_body . substr ( $orig_body , 0 , $maxlen - $textlen );
$textlen = $maxlen ;
}
2016-10-22 12:14:41 +02:00
} else {
2012-07-08 00:20:24 +02:00
$new_body = $new_body . substr ( $orig_body , 0 , $img_start );
2012-07-08 02:47:13 +02:00
$textlen += $img_start ;
2012-07-08 00:20:24 +02:00
}
$new_body = $new_body . substr ( $orig_body , $img_start , $img_end - $img_start );
2016-10-22 12:14:41 +02:00
} else {
2012-07-07 01:09:23 +02:00
2017-04-08 19:30:35 +02:00
if (( $textlen + $img_end ) > $maxlen ) {
2016-10-22 12:14:41 +02:00
if ( $textlen < $maxlen ) {
2012-07-08 00:20:24 +02:00
logger ( 'limit_body_size: the limit happens before the end of a non-embedded image' , LOGGER_DEBUG );
$new_body = $new_body . substr ( $orig_body , 0 , $maxlen - $textlen );
$textlen = $maxlen ;
}
2016-10-22 12:14:41 +02:00
} else {
2012-07-08 00:20:24 +02:00
$new_body = $new_body . substr ( $orig_body , 0 , $img_end );
$textlen += $img_end ;
}
2012-07-07 01:09:23 +02:00
}
2012-07-08 00:20:24 +02:00
$orig_body = substr ( $orig_body , $img_end );
2012-07-07 01:09:23 +02:00
2017-04-08 19:30:35 +02:00
if ( $orig_body === false ) {
// in case the body ends on a closing image tag
2012-07-08 00:20:24 +02:00
$orig_body = '' ;
2017-04-08 19:30:35 +02:00
}
2012-07-07 01:09:23 +02:00
2012-07-08 00:20:24 +02:00
$img_start = strpos ( $orig_body , '[img' );
$img_st_close = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), ']' ) : false );
$img_end = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), '[/img]' ) : false );
}
2012-07-07 01:09:23 +02:00
2017-04-08 19:30:35 +02:00
if (( $textlen + strlen ( $orig_body )) > $maxlen ) {
2016-10-22 12:14:41 +02:00
if ( $textlen < $maxlen ) {
2012-07-08 00:20:24 +02:00
logger ( 'limit_body_size: the limit happens after the end of the last image' , LOGGER_DEBUG );
$new_body = $new_body . substr ( $orig_body , 0 , $maxlen - $textlen );
}
2016-10-22 12:14:41 +02:00
} else {
2012-07-08 00:20:24 +02:00
logger ( 'limit_body_size: the text size with embedded images extracted did not violate the limit' , LOGGER_DEBUG );
$new_body = $new_body . $orig_body ;
2012-07-07 01:09:23 +02:00
}
2012-07-08 00:20:24 +02:00
return $new_body ;
2017-04-08 19:30:35 +02:00
} else {
2012-07-07 01:09:23 +02:00
return $body ;
2017-04-08 19:30:35 +02:00
}
2017-12-12 05:52:33 +01:00
}
2010-11-04 00:48:21 +01:00
2018-01-21 00:52:54 +01:00
/// @TODO move to ???
2014-10-20 08:03:47 +02:00
function add_page_info_data ( $data ) {
2018-01-17 19:42:40 +01:00
Addon :: callHooks ( 'page_info_data' , $data );
2014-01-05 16:10:02 +01:00
2014-04-04 10:52:53 +02:00
// It maybe is a rich content, but if it does have everything that a link has,
// then treat it that way
2017-06-08 04:00:59 +02:00
if (( $data [ " type " ] == " rich " ) && is_string ( $data [ " title " ]) &&
is_string ( $data [ " text " ]) && ( sizeof ( $data [ " images " ]) > 0 )) {
2014-04-04 10:52:53 +02:00
$data [ " type " ] = " link " ;
2016-11-13 20:09:47 +01:00
}
2014-01-05 16:10:02 +01:00
2017-06-08 04:00:59 +02:00
if ((( $data [ " type " ] != " link " ) && ( $data [ " type " ] != " video " ) && ( $data [ " type " ] != " photo " )) || ( $data [ " title " ] == $data [ " url " ])) {
2016-11-13 09:50:01 +01:00
return " " ;
2016-11-12 21:23:00 +01:00
}
2014-01-05 16:10:02 +01:00
2017-06-08 04:00:59 +02:00
if ( $no_photos && ( $data [ " type " ] == " photo " )) {
2016-11-13 20:09:47 +01:00
return " " ;
}
2014-01-05 16:10:02 +01:00
2016-04-17 20:43:41 +02:00
// Escape some bad characters
2018-01-15 14:05:12 +01:00
$data [ " url " ] = str_replace ([ " [ " , " ] " ], [ " [ " , " ] " ], htmlentities ( $data [ " url " ], ENT_QUOTES , 'UTF-8' , false ));
$data [ " title " ] = str_replace ([ " [ " , " ] " ], [ " [ " , " ] " ], htmlentities ( $data [ " title " ], ENT_QUOTES , 'UTF-8' , false ));
2016-04-17 20:43:41 +02:00
$text = " [attachment type=' " . $data [ " type " ] . " ' " ;
2016-11-12 21:23:00 +01:00
if ( $data [ " text " ] == " " ) {
$data [ " text " ] = $data [ " title " ];
}
if ( $data [ " text " ] == " " ) {
$data [ " text " ] = $data [ " url " ];
}
2016-11-13 20:09:47 +01:00
if ( $data [ " url " ] != " " ) {
2016-04-17 20:43:41 +02:00
$text .= " url=' " . $data [ " url " ] . " ' " ;
2016-11-13 20:09:47 +01:00
}
if ( $data [ " title " ] != " " ) {
2016-04-17 20:43:41 +02:00
$text .= " title=' " . $data [ " title " ] . " ' " ;
2016-11-13 20:09:47 +01:00
}
2016-04-17 20:43:41 +02:00
if ( sizeof ( $data [ " images " ]) > 0 ) {
2018-01-15 14:05:12 +01:00
$preview = str_replace ([ " [ " , " ] " ], [ " [ " , " ] " ], htmlentities ( $data [ " images " ][ 0 ][ " src " ], ENT_QUOTES , 'UTF-8' , false ));
2016-04-17 20:43:41 +02:00
// if the preview picture is larger than 500 pixels then show it in a larger mode
// But only, if the picture isn't higher than large (To prevent huge posts)
2017-11-25 11:07:49 +01:00
if ( ! Config :: get ( 'system' , 'always_show_preview' ) && ( $data [ " images " ][ 0 ][ " width " ] >= 500 )
&& ( $data [ " images " ][ 0 ][ " width " ] >= $data [ " images " ][ 0 ][ " height " ])) {
2016-04-17 20:43:41 +02:00
$text .= " image=' " . $preview . " ' " ;
2016-11-13 20:09:47 +01:00
} else {
2016-04-17 20:43:41 +02:00
$text .= " preview=' " . $preview . " ' " ;
2016-11-13 20:09:47 +01:00
}
2014-06-15 23:33:25 +02:00
}
2016-11-13 20:09:47 +01:00
2016-04-17 20:43:41 +02:00
$text .= " ] " . $data [ " text " ] . " [/attachment] " ;
2014-04-04 10:52:53 +02:00
2014-10-03 12:18:33 +02:00
$hashtags = " " ;
2017-06-08 04:00:59 +02:00
if ( isset ( $data [ " keywords " ]) && count ( $data [ " keywords " ])) {
2014-10-03 13:02:15 +02:00
$hashtags = " \n " ;
foreach ( $data [ " keywords " ] AS $keyword ) {
2018-01-21 00:52:54 +01:00
/// @TODO make a positive list of allowed characters
2018-01-15 14:05:12 +01:00
$hashtag = str_replace ([ " " , " + " , " / " , " . " , " # " , " ' " , " ’ " , " ` " , " ( " , " ) " , " „ " , " “ " ],
[ " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " ], $keyword );
2017-08-26 09:32:10 +02:00
$hashtags .= " #[url= " . System :: baseUrl () . " /search?tag= " . rawurlencode ( $hashtag ) . " ] " . $hashtag . " [/url] " ;
2014-10-03 13:02:15 +02:00
}
}
2014-10-03 12:18:33 +02:00
2016-04-17 20:43:41 +02:00
return " \n " . $text . $hashtags ;
2014-04-04 10:52:53 +02:00
}
2018-01-21 00:52:54 +01:00
/// @TODO move to ???
2015-01-20 22:54:25 +01:00
function query_page_info ( $url , $no_photos = false , $photo = " " , $keywords = false , $keyword_blacklist = " " ) {
2014-10-20 08:03:47 +02:00
2016-11-24 01:11:22 +01:00
$data = ParseUrl :: getSiteinfoCached ( $url , true );
2014-10-20 08:03:47 +02:00
2017-04-08 19:30:35 +02:00
if ( $photo != " " ) {
2014-12-17 21:57:38 +01:00
$data [ " images " ][ 0 ][ " src " ] = $photo ;
2017-04-08 19:30:35 +02:00
}
2014-12-17 21:57:38 +01:00
2017-04-14 16:59:51 +02:00
logger ( 'fetch page info for ' . $url . ' ' . print_r ( $data , true ), LOGGER_DEBUG );
2014-10-20 08:03:47 +02:00
2017-06-08 04:00:59 +02:00
if ( ! $keywords && isset ( $data [ " keywords " ])) {
2014-10-20 08:03:47 +02:00
unset ( $data [ " keywords " ]);
2017-04-08 19:30:35 +02:00
}
2014-10-20 08:03:47 +02:00
2017-06-08 04:00:59 +02:00
if (( $keyword_blacklist != " " ) && isset ( $data [ " keywords " ])) {
2017-04-08 19:30:35 +02:00
$list = explode ( " , " , $keyword_blacklist );
2014-10-30 00:24:23 +01:00
foreach ( $list AS $keyword ) {
$keyword = trim ( $keyword );
$index = array_search ( $keyword , $data [ " keywords " ]);
2017-04-08 19:30:35 +02:00
if ( $index !== false ) {
2014-10-30 00:24:23 +01:00
unset ( $data [ " keywords " ][ $index ]);
2017-04-08 19:30:35 +02:00
}
2014-10-30 00:24:23 +01:00
}
}
2017-04-14 16:59:51 +02:00
return $data ;
2015-01-20 22:54:25 +01:00
}
2018-01-21 00:52:54 +01:00
/// @TODO move to ???
2015-01-20 22:54:25 +01:00
function add_page_keywords ( $url , $no_photos = false , $photo = " " , $keywords = false , $keyword_blacklist = " " ) {
$data = query_page_info ( $url , $no_photos , $photo , $keywords , $keyword_blacklist );
$tags = " " ;
2017-06-08 04:00:59 +02:00
if ( isset ( $data [ " keywords " ]) && count ( $data [ " keywords " ])) {
2015-01-20 22:54:25 +01:00
foreach ( $data [ " keywords " ] AS $keyword ) {
2018-01-15 14:05:12 +01:00
$hashtag = str_replace ([ " " , " + " , " / " , " . " , " # " , " ' " ],
[ " " , " " , " " , " " , " " , " " ], $keyword );
2015-01-20 22:54:25 +01:00
2017-04-08 19:30:35 +02:00
if ( $tags != " " ) {
$tags .= " , " ;
}
2015-01-20 22:54:25 +01:00
2017-08-26 09:32:10 +02:00
$tags .= " #[url= " . System :: baseUrl () . " /search?tag= " . rawurlencode ( $hashtag ) . " ] " . $hashtag . " [/url] " ;
2015-01-20 22:54:25 +01:00
}
}
2017-04-14 16:59:51 +02:00
return $tags ;
2015-01-20 22:54:25 +01:00
}
2018-01-21 00:52:54 +01:00
/// @TODO move to ???
2015-01-20 22:54:25 +01:00
function add_page_info ( $url , $no_photos = false , $photo = " " , $keywords = false , $keyword_blacklist = " " ) {
$data = query_page_info ( $url , $no_photos , $photo , $keywords , $keyword_blacklist );
2014-10-20 08:03:47 +02:00
$text = add_page_info_data ( $data );
2017-04-14 16:59:51 +02:00
return $text ;
2014-10-20 08:03:47 +02:00
}
2018-01-21 00:52:54 +01:00
/// @TODO move to ???
2014-04-04 10:52:53 +02:00
function add_page_info_to_body ( $body , $texturl = false , $no_photos = false ) {
2017-04-14 16:59:51 +02:00
logger ( 'add_page_info_to_body: fetch page info for body ' . $body , LOGGER_DEBUG );
2014-04-04 10:52:53 +02:00
2014-06-15 23:33:25 +02:00
$URLSearchString = " ^ \ [ \ ] " ;
2014-04-04 10:52:53 +02:00
2016-12-12 07:46:02 +01:00
// Fix for Mastodon where the mentions are in a different format
$body = preg_replace ( " / \ [url \ =([ $URLSearchString ]*) \ ]([#!@])(.*?) \ [ \ /url \ ]/ism " ,
2017-04-14 16:59:51 +02:00
'$2[url=$1]$3[/url]' , $body );
2016-12-12 07:46:02 +01:00
2014-06-15 23:33:25 +02:00
// Adding these spaces is a quick hack due to my problems with regular expressions :)
2017-04-14 16:59:51 +02:00
preg_match ( " /[^!#@] \ [url \ ]([ $URLSearchString ]*) \ [ \ /url \ ]/ism " , " " . $body , $matches );
2014-04-04 10:52:53 +02:00
2017-04-14 16:59:51 +02:00
if ( ! $matches ) {
preg_match ( " /[^!#@] \ [url \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /url \ ]/ism " , " " . $body , $matches );
}
2014-04-04 10:52:53 +02:00
// Convert urls without bbcode elements
2017-06-08 04:00:59 +02:00
if ( ! $matches && $texturl ) {
2014-04-04 10:52:53 +02:00
preg_match ( " /([^ \ ] \ =' " . '"' . " ]|^)(https? \ : \ / \ /[a-zA-Z0-9 \ : \ / \ - \ ? \ & \ ; \ . \ = \ _ \ ~ \ # \ % \$ \ ! \ + \ ,]+)/ism " , " " . $body , $matches );
2014-01-05 16:10:02 +01:00
2014-04-04 10:52:53 +02:00
// Yeah, a hack. I really hate regular expressions :)
2017-04-14 16:59:51 +02:00
if ( $matches ) {
2014-06-15 23:33:25 +02:00
$matches [ 1 ] = $matches [ 2 ];
2017-04-14 16:59:51 +02:00
}
2014-01-05 16:10:02 +01:00
}
2017-04-14 16:59:51 +02:00
if ( $matches ) {
2014-07-27 16:10:09 +02:00
$footer = add_page_info ( $matches [ 1 ], $no_photos );
2017-04-14 16:59:51 +02:00
}
2014-07-27 16:10:09 +02:00
// Remove the link from the body if the link is attached at the end of the post
2017-06-08 04:00:59 +02:00
if ( isset ( $footer ) && ( trim ( $footer ) != " " ) && ( strpos ( $footer , $matches [ 1 ]))) {
2014-07-27 16:10:09 +02:00
$removedlink = trim ( str_replace ( $matches [ 1 ], " " , $body ));
2017-06-08 04:00:59 +02:00
if (( $removedlink == " " ) || strstr ( $body , $removedlink )) {
2014-07-27 16:10:09 +02:00
$body = $removedlink ;
2017-04-14 16:59:51 +02:00
}
2014-07-27 16:10:09 +02:00
2018-01-15 14:05:12 +01:00
$url = str_replace ([ '/' , '.' ], [ '\/' , '\.' ], $matches [ 1 ]);
2017-04-14 16:59:51 +02:00
$removedlink = preg_replace ( " / \ [url \ = " . $url . " \ ](.*?) \ [ \ /url \ ]/ism " , '' , $body );
2017-06-08 04:00:59 +02:00
if (( $removedlink == " " ) || strstr ( $body , $removedlink )) {
2014-07-27 16:10:09 +02:00
$body = $removedlink ;
2017-04-14 16:59:51 +02:00
}
2014-07-27 16:10:09 +02:00
}
// Add the page information to the bottom
2017-06-08 04:00:59 +02:00
if ( isset ( $footer ) && ( trim ( $footer ) != " " )) {
2014-07-27 16:10:09 +02:00
$body .= $footer ;
2017-04-14 16:59:51 +02:00
}
2014-01-05 16:10:02 +01:00
2014-06-15 23:33:25 +02:00
return $body ;
2014-01-05 16:10:02 +01:00
}
2017-04-14 16:59:51 +02:00
/// @TODO add type-hint array
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2018-01-02 14:32:53 +01:00
function item_store ( $arr , $force_parent = false , $notify = false , $dontcache = false )
{
2016-11-14 07:55:17 +01:00
$a = get_app ();
2014-09-01 14:40:29 +02:00
// If it is a posting where users should get notifications, then define it as wall posting
if ( $notify ) {
$arr [ 'wall' ] = 1 ;
$arr [ 'type' ] = 'wall' ;
2014-09-01 15:28:31 +02:00
$arr [ 'origin' ] = 1 ;
2014-09-01 14:40:29 +02:00
$arr [ 'network' ] = NETWORK_DFRN ;
2017-04-29 07:44:13 +02:00
$arr [ 'protocol' ] = PROTOCOL_DFRN ;
2016-11-14 07:55:17 +01:00
// We have to avoid duplicates. So we create the GUID in form of a hash of the plink or uri.
2018-01-21 01:18:31 +01:00
// In difference to the call to "Item::guidFromUri" several lines below we add the hash of our own host.
2016-11-14 07:55:17 +01:00
// This is done because our host is the original creator of the post.
2017-04-08 10:12:14 +02:00
if ( ! isset ( $arr [ 'guid' ])) {
if ( isset ( $arr [ 'plink' ])) {
2018-01-21 01:18:31 +01:00
$arr [ 'guid' ] = Item :: guidFromUri ( $arr [ 'plink' ], $a -> get_hostname ());
2017-04-08 10:12:14 +02:00
} elseif ( isset ( $arr [ 'uri' ])) {
2018-01-21 01:18:31 +01:00
$arr [ 'guid' ] = Item :: guidFromUri ( $arr [ 'uri' ], $a -> get_hostname ());
2017-04-08 10:12:14 +02:00
}
2016-11-14 07:55:17 +01:00
}
2018-01-02 14:32:53 +01:00
} else {
$arr [ 'network' ] = trim ( defaults ( $arr , 'network' , NETWORK_PHANTOM ));
2014-09-01 14:40:29 +02:00
}
2017-05-12 18:09:25 +02:00
if ( $notify ) {
$guid_prefix = " " ;
2017-06-08 04:00:59 +02:00
} elseif (( trim ( $arr [ 'guid' ]) == " " ) && ( trim ( $arr [ 'plink' ]) != " " )) {
2018-01-21 01:18:31 +01:00
$arr [ 'guid' ] = Item :: guidFromUri ( $arr [ 'plink' ]);
2017-06-08 04:00:59 +02:00
} elseif (( trim ( $arr [ 'guid' ]) == " " ) && ( trim ( $arr [ 'uri' ]) != " " )) {
2018-01-21 01:18:31 +01:00
$arr [ 'guid' ] = Item :: guidFromUri ( $arr [ 'uri' ]);
2017-05-12 18:09:25 +02:00
} else {
$parsed = parse_url ( $arr [ " author-link " ]);
$guid_prefix = hash ( " crc32 " , $parsed [ " host " ]);
}
$arr [ 'guid' ] = (( x ( $arr , 'guid' )) ? notags ( trim ( $arr [ 'guid' ])) : get_guid ( 32 , $guid_prefix ));
$arr [ 'uri' ] = (( x ( $arr , 'uri' )) ? notags ( trim ( $arr [ 'uri' ])) : item_new_uri ( $a -> get_hostname (), $uid , $arr [ 'guid' ]));
2017-04-28 18:35:53 +02:00
// Store conversation data
2018-01-21 00:52:54 +01:00
$arr = Conversation :: insert ( $arr );
2017-04-28 18:35:53 +02:00
2017-04-14 16:59:51 +02:00
/*
* If a Diaspora signature structure was passed in , pull it out of the
* item array and set it aside for later storage .
*/
2011-08-29 04:22:27 +02:00
$dsprsig = null ;
2017-04-14 16:59:51 +02:00
if ( x ( $arr , 'dsprsig' )) {
2016-12-01 14:50:26 +01:00
$encoded_signature = $arr [ 'dsprsig' ];
2011-08-29 04:22:27 +02:00
$dsprsig = json_decode ( base64_decode ( $arr [ 'dsprsig' ]));
unset ( $arr [ 'dsprsig' ]);
}
2015-05-26 23:33:38 +02:00
// Converting the plink
2018-01-21 00:52:54 +01:00
/// @TODO Check if this is really still needed
2018-01-02 14:32:53 +01:00
if ( $arr [ 'network' ] == NETWORK_OSTATUS ) {
2017-04-14 16:59:51 +02:00
if ( isset ( $arr [ 'plink' ])) {
2017-11-16 05:09:11 +01:00
$arr [ 'plink' ] = OStatus :: convertHref ( $arr [ 'plink' ]);
2017-04-14 16:59:51 +02:00
} elseif ( isset ( $arr [ 'uri' ])) {
2017-11-16 05:09:11 +01:00
$arr [ 'plink' ] = OStatus :: convertHref ( $arr [ 'uri' ]);
2017-04-14 16:59:51 +02:00
}
2015-05-26 23:33:38 +02:00
}
2017-04-14 16:59:51 +02:00
if ( x ( $arr , 'gravity' )) {
2010-09-10 09:42:53 +02:00
$arr [ 'gravity' ] = intval ( $arr [ 'gravity' ]);
2017-04-14 16:59:51 +02:00
} elseif ( $arr [ 'parent-uri' ] === $arr [ 'uri' ]) {
2010-09-10 07:02:28 +02:00
$arr [ 'gravity' ] = 0 ;
2017-04-14 16:59:51 +02:00
} elseif ( activity_match ( $arr [ 'verb' ], ACTIVITY_POST )) {
2010-09-10 07:02:28 +02:00
$arr [ 'gravity' ] = 6 ;
2017-04-14 16:59:51 +02:00
} else {
2010-11-10 05:38:24 +01:00
$arr [ 'gravity' ] = 6 ; // extensible catchall
2017-04-14 16:59:51 +02:00
}
2010-09-10 07:02:28 +02:00
2017-04-14 16:59:51 +02:00
if ( ! x ( $arr , 'type' )) {
2010-11-10 05:38:24 +01:00
$arr [ 'type' ] = 'remote' ;
2017-04-14 16:59:51 +02:00
}
2011-02-02 03:20:25 +01:00
2014-05-12 15:33:20 +02:00
$uid = intval ( $arr [ 'uid' ]);
2017-07-23 07:51:55 +02:00
// check for create date and expire time
$expire_interval = Config :: get ( 'system' , 'dbclean-expire-days' , 0 );
2018-01-10 14:36:02 +01:00
$user = dba :: selectFirst ( 'user' , [ 'expire' ], [ 'uid' => $uid ]);
2018-01-10 04:20:33 +01:00
if ( DBM :: is_result ( $user ) && ( $user [ 'expire' ] > 0 ) && (( $user [ 'expire' ] < $expire_interval ) || ( $expire_interval == 0 ))) {
$expire_interval = $user [ 'expire' ];
2017-07-23 07:51:55 +02:00
}
2017-07-23 21:59:29 +02:00
if (( $expire_interval > 0 ) && ! empty ( $arr [ 'created' ])) {
$expire_date = time () - ( $expire_interval * 86400 );
$created_date = strtotime ( $arr [ 'created' ]);
2017-07-23 07:51:55 +02:00
if ( $created_date < $expire_date ) {
2017-07-23 21:59:29 +02:00
logger ( 'item-store: item created (' . date ( 'c' , $created_date ) . ') before expiration time (' . date ( 'c' , $expire_date ) . '). ignored. ' . print_r ( $arr , true ), LOGGER_DEBUG );
2017-07-23 07:51:55 +02:00
return 0 ;
2014-05-12 15:33:20 +02:00
}
}
2017-04-14 16:59:51 +02:00
/*
* Do we already have this item ?
* We have to check several networks since Friendica posts could be repeated
* via OStatus ( maybe Diasporsa as well )
*/
2018-01-15 14:05:12 +01:00
if ( in_array ( $arr [ 'network' ], [ NETWORK_DIASPORA , NETWORK_DFRN , NETWORK_OSTATUS , " " ])) {
2015-11-30 23:13:56 +01:00
$r = q ( " SELECT `id`, `network` FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `network` IN ('%s', '%s', '%s') LIMIT 1 " ,
dbesc ( trim ( $arr [ 'uri' ])),
intval ( $uid ),
dbesc ( NETWORK_DIASPORA ),
dbesc ( NETWORK_DFRN ),
dbesc ( NETWORK_OSTATUS )
);
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2015-11-30 23:13:56 +01:00
// We only log the entries with a different user id than 0. Otherwise we would have too many false positives
2017-04-14 16:59:51 +02:00
if ( $uid != 0 ) {
2015-11-30 23:13:56 +01:00
logger ( " Item with uri " . $arr [ 'uri' ] . " already existed for user " . $uid . " with id " . $r [ 0 ][ " id " ] . " target network " . $r [ 0 ][ " network " ] . " - new network: " . $arr [ 'network' ]);
2017-04-14 16:59:51 +02:00
}
return $r [ 0 ][ " id " ];
2015-11-30 23:13:56 +01:00
}
}
2017-04-14 16:59:51 +02:00
/// @TODO old-lost code?
2018-01-17 20:22:38 +01:00
// Shouldn't happen but we want to make absolutely sure it doesn't leak from an addon.
2014-05-18 18:59:10 +02:00
// Deactivated, since the bbcode parser can handle with it - and it destroys posts with some smileys that contain "<"
2016-10-22 12:14:41 +02:00
//if ((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false))
2014-05-18 18:59:10 +02:00
// $arr['body'] = strip_tags($arr['body']);
2011-02-02 03:20:25 +01:00
2018-01-21 00:52:54 +01:00
Item :: addLanguageInPostopts ( $arr );
2012-07-12 07:45:14 +02:00
2017-04-14 16:59:51 +02:00
$arr [ 'wall' ] = (( x ( $arr , 'wall' )) ? intval ( $arr [ 'wall' ]) : 0 );
$arr [ 'extid' ] = (( x ( $arr , 'extid' )) ? notags ( trim ( $arr [ 'extid' ])) : '' );
$arr [ 'author-name' ] = (( x ( $arr , 'author-name' )) ? trim ( $arr [ 'author-name' ]) : '' );
$arr [ 'author-link' ] = (( x ( $arr , 'author-link' )) ? notags ( trim ( $arr [ 'author-link' ])) : '' );
$arr [ 'author-avatar' ] = (( x ( $arr , 'author-avatar' )) ? notags ( trim ( $arr [ 'author-avatar' ])) : '' );
$arr [ 'owner-name' ] = (( x ( $arr , 'owner-name' )) ? trim ( $arr [ 'owner-name' ]) : '' );
$arr [ 'owner-link' ] = (( x ( $arr , 'owner-link' )) ? notags ( trim ( $arr [ 'owner-link' ])) : '' );
$arr [ 'owner-avatar' ] = (( x ( $arr , 'owner-avatar' )) ? notags ( trim ( $arr [ 'owner-avatar' ])) : '' );
2017-08-03 07:42:44 +02:00
$arr [ 'received' ] = (( x ( $arr , 'received' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'received' ]) : datetime_convert ());
$arr [ 'created' ] = (( x ( $arr , 'created' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'created' ]) : $arr [ 'received' ]);
$arr [ 'edited' ] = (( x ( $arr , 'edited' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'edited' ]) : $arr [ 'created' ]);
$arr [ 'changed' ] = (( x ( $arr , 'changed' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'changed' ]) : $arr [ 'created' ]);
$arr [ 'commented' ] = (( x ( $arr , 'commented' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'commented' ]) : $arr [ 'created' ]);
2017-04-14 16:59:51 +02:00
$arr [ 'title' ] = (( x ( $arr , 'title' )) ? trim ( $arr [ 'title' ]) : '' );
$arr [ 'location' ] = (( x ( $arr , 'location' )) ? trim ( $arr [ 'location' ]) : '' );
$arr [ 'coord' ] = (( x ( $arr , 'coord' )) ? notags ( trim ( $arr [ 'coord' ])) : '' );
$arr [ 'visible' ] = (( x ( $arr , 'visible' ) !== false ) ? intval ( $arr [ 'visible' ]) : 1 );
2010-11-10 05:38:24 +01:00
$arr [ 'deleted' ] = 0 ;
2017-04-14 16:59:51 +02:00
$arr [ 'parent-uri' ] = (( x ( $arr , 'parent-uri' )) ? notags ( trim ( $arr [ 'parent-uri' ])) : $arr [ 'uri' ]);
$arr [ 'verb' ] = (( x ( $arr , 'verb' )) ? notags ( trim ( $arr [ 'verb' ])) : '' );
$arr [ 'object-type' ] = (( x ( $arr , 'object-type' )) ? notags ( trim ( $arr [ 'object-type' ])) : '' );
$arr [ 'object' ] = (( x ( $arr , 'object' )) ? trim ( $arr [ 'object' ]) : '' );
$arr [ 'target-type' ] = (( x ( $arr , 'target-type' )) ? notags ( trim ( $arr [ 'target-type' ])) : '' );
$arr [ 'target' ] = (( x ( $arr , 'target' )) ? trim ( $arr [ 'target' ]) : '' );
$arr [ 'plink' ] = (( x ( $arr , 'plink' )) ? notags ( trim ( $arr [ 'plink' ])) : '' );
$arr [ 'allow_cid' ] = (( x ( $arr , 'allow_cid' )) ? trim ( $arr [ 'allow_cid' ]) : '' );
$arr [ 'allow_gid' ] = (( x ( $arr , 'allow_gid' )) ? trim ( $arr [ 'allow_gid' ]) : '' );
$arr [ 'deny_cid' ] = (( x ( $arr , 'deny_cid' )) ? trim ( $arr [ 'deny_cid' ]) : '' );
$arr [ 'deny_gid' ] = (( x ( $arr , 'deny_gid' )) ? trim ( $arr [ 'deny_gid' ]) : '' );
$arr [ 'private' ] = (( x ( $arr , 'private' )) ? intval ( $arr [ 'private' ]) : 0 );
$arr [ 'bookmark' ] = (( x ( $arr , 'bookmark' )) ? intval ( $arr [ 'bookmark' ]) : 0 );
$arr [ 'body' ] = (( x ( $arr , 'body' )) ? trim ( $arr [ 'body' ]) : '' );
$arr [ 'tag' ] = (( x ( $arr , 'tag' )) ? notags ( trim ( $arr [ 'tag' ])) : '' );
$arr [ 'attach' ] = (( x ( $arr , 'attach' )) ? notags ( trim ( $arr [ 'attach' ])) : '' );
$arr [ 'app' ] = (( x ( $arr , 'app' )) ? notags ( trim ( $arr [ 'app' ])) : '' );
$arr [ 'origin' ] = (( x ( $arr , 'origin' )) ? intval ( $arr [ 'origin' ]) : 0 );
$arr [ 'postopts' ] = (( x ( $arr , 'postopts' )) ? trim ( $arr [ 'postopts' ]) : '' );
$arr [ 'resource-id' ] = (( x ( $arr , 'resource-id' )) ? trim ( $arr [ 'resource-id' ]) : '' );
$arr [ 'event-id' ] = (( x ( $arr , 'event-id' )) ? intval ( $arr [ 'event-id' ]) : 0 );
$arr [ 'inform' ] = (( x ( $arr , 'inform' )) ? trim ( $arr [ 'inform' ]) : '' );
$arr [ 'file' ] = (( x ( $arr , 'file' )) ? trim ( $arr [ 'file' ]) : '' );
2010-11-12 05:32:20 +01:00
2017-07-19 07:51:39 +02:00
// When there is no content then we don't post it
if ( $arr [ 'body' ] . $arr [ 'title' ] == '' ) {
return 0 ;
}
2016-06-13 22:21:33 +02:00
// Items cannot be stored before they happen ...
2017-04-14 16:59:51 +02:00
if ( $arr [ 'created' ] > datetime_convert ()) {
2016-06-13 22:21:33 +02:00
$arr [ 'created' ] = datetime_convert ();
2017-04-14 16:59:51 +02:00
}
2016-06-13 22:21:33 +02:00
// We haven't invented time travel by now.
2017-04-14 16:59:51 +02:00
if ( $arr [ 'edited' ] > datetime_convert ()) {
2016-06-13 22:21:33 +02:00
$arr [ 'edited' ] = datetime_convert ();
2017-04-14 16:59:51 +02:00
}
2016-02-09 06:42:00 +01:00
2017-06-08 04:00:59 +02:00
if (( $arr [ 'author-link' ] == " " ) && ( $arr [ 'owner-link' ] == " " )) {
2017-08-26 12:01:50 +02:00
logger ( " Both author-link and owner-link are empty. Called by: " . System :: callstack (), LOGGER_DEBUG );
2017-04-14 16:59:51 +02:00
}
2016-02-09 06:42:00 +01:00
2014-07-22 00:36:20 +02:00
if ( $arr [ 'plink' ] == " " ) {
2017-08-26 09:32:10 +02:00
$arr [ 'plink' ] = System :: baseUrl () . '/display/' . urlencode ( $arr [ 'guid' ]);
2014-07-22 00:36:20 +02:00
}
2018-01-02 14:32:53 +01:00
if ( $arr [ 'network' ] == NETWORK_PHANTOM ) {
2015-10-08 00:25:55 +02:00
$r = q ( " SELECT `network` FROM `contact` WHERE `network` IN ('%s', '%s', '%s') AND `nurl` = '%s' AND `uid` = %d LIMIT 1 " ,
dbesc ( NETWORK_DFRN ), dbesc ( NETWORK_DIASPORA ), dbesc ( NETWORK_OSTATUS ),
dbesc ( normalise_link ( $arr [ 'author-link' ])),
2013-11-02 10:49:44 +01:00
intval ( $arr [ 'uid' ])
);
2018-01-02 14:32:53 +01:00
if ( ! DBM :: is_result ( $r )) {
2015-10-08 00:25:55 +02:00
$r = q ( " SELECT `network` FROM `gcontact` WHERE `network` IN ('%s', '%s', '%s') AND `nurl` = '%s' LIMIT 1 " ,
dbesc ( NETWORK_DFRN ), dbesc ( NETWORK_DIASPORA ), dbesc ( NETWORK_OSTATUS ),
dbesc ( normalise_link ( $arr [ 'author-link' ]))
);
2018-01-02 14:32:53 +01:00
}
2015-10-08 00:25:55 +02:00
2017-11-08 04:57:46 +01:00
if ( ! DBM :: is_result ( $r )) {
2015-10-08 00:25:55 +02:00
$r = q ( " SELECT `network` FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1 " ,
intval ( $arr [ 'contact-id' ]),
intval ( $arr [ 'uid' ])
);
2017-04-14 16:59:51 +02:00
}
2015-10-08 00:25:55 +02:00
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2013-11-02 10:49:44 +01:00
$arr [ 'network' ] = $r [ 0 ][ " network " ];
2017-04-14 16:59:51 +02:00
}
2013-11-02 10:49:44 +01:00
// Fallback to friendica (why is it empty in some cases?)
2017-04-14 16:59:51 +02:00
if ( $arr [ 'network' ] == " " ) {
2013-11-02 10:49:44 +01:00
$arr [ 'network' ] = NETWORK_DFRN ;
2017-04-14 16:59:51 +02:00
}
2013-11-02 10:49:44 +01:00
2017-04-14 16:59:51 +02:00
logger ( " item_store: Set network to " . $arr [ " network " ] . " for " . $arr [ " uri " ], LOGGER_DEBUG );
2013-11-02 10:49:44 +01:00
}
2012-08-05 13:30:51 +02:00
2016-01-23 12:39:37 +01:00
// The contact-id should be set before "item_store" was called - but there seems to be some issues
if ( $arr [ " contact-id " ] == 0 ) {
2017-04-14 16:59:51 +02:00
/*
* First we are looking for a suitable contact that matches with the author of the post
* This is done only for comments ( See below explanation at " gcontact-id " )
*/
if ( $arr [ 'parent-uri' ] != $arr [ 'uri' ]) {
2017-11-19 23:03:39 +01:00
$arr [ " contact-id " ] = Contact :: getIdForURL ( $arr [ 'author-link' ], $uid );
2017-04-14 16:59:51 +02:00
}
2016-01-23 12:39:37 +01:00
// If not present then maybe the owner was found
2017-04-14 16:59:51 +02:00
if ( $arr [ " contact-id " ] == 0 ) {
2017-11-19 23:03:39 +01:00
$arr [ " contact-id " ] = Contact :: getIdForURL ( $arr [ 'owner-link' ], $uid );
2017-04-14 16:59:51 +02:00
}
2016-01-23 12:39:37 +01:00
// Still missing? Then use the "self" contact of the current user
if ( $arr [ " contact-id " ] == 0 ) {
$r = q ( " SELECT `id` FROM `contact` WHERE `self` AND `uid` = %d " , intval ( $uid ));
2017-04-14 16:59:51 +02:00
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2016-01-23 12:39:37 +01:00
$arr [ " contact-id " ] = $r [ 0 ][ " id " ];
2017-04-14 16:59:51 +02:00
}
2016-01-23 12:39:37 +01:00
}
2017-04-14 16:59:51 +02:00
2016-01-28 18:06:17 +01:00
logger ( " Contact-id was missing for post " . $arr [ " guid " ] . " from user id " . $uid . " - now set to " . $arr [ " contact-id " ], LOGGER_DEBUG );
2016-01-23 12:39:37 +01:00
}
2018-01-02 14:32:53 +01:00
if ( ! x ( $arr , " gcontact-id " )) {
2017-04-14 16:59:51 +02:00
/*
* The gcontact should mostly behave like the contact . But is is supposed to be global for the system .
* This means that wall posts , repeated posts , etc . should have the gcontact id of the owner .
* On comments the author is the better choice .
*/
if ( $arr [ 'parent-uri' ] === $arr [ 'uri' ]) {
2018-01-15 14:05:12 +01:00
$arr [ " gcontact-id " ] = GContact :: getId ([ " url " => $arr [ 'owner-link' ], " network " => $arr [ 'network' ],
" photo " => $arr [ 'owner-avatar' ], " name " => $arr [ 'owner-name' ]]);
2017-04-14 16:59:51 +02:00
} else {
2018-01-15 14:05:12 +01:00
$arr [ " gcontact-id " ] = GContact :: getId ([ " url " => $arr [ 'author-link' ], " network " => $arr [ 'network' ],
" photo " => $arr [ 'author-avatar' ], " name " => $arr [ 'author-name' ]]);
2017-04-14 16:59:51 +02:00
}
2016-01-28 18:06:17 +01:00
}
2016-01-05 15:34:27 +01:00
2017-04-14 16:59:51 +02:00
if ( $arr [ " author-id " ] == 0 ) {
2017-11-19 23:03:39 +01:00
$arr [ " author-id " ] = Contact :: getIdForURL ( $arr [ " author-link " ], 0 );
2017-04-14 16:59:51 +02:00
}
2016-06-15 21:20:55 +02:00
2017-11-19 23:03:39 +01:00
if ( Contact :: isBlocked ( $arr [ " author-id " ])) {
2017-10-07 11:52:43 +02:00
logger ( 'Contact ' . $arr [ " author-id " ] . ' is blocked, item ' . $arr [ " uri " ] . ' will not be stored' );
return 0 ;
}
2017-04-14 16:59:51 +02:00
if ( $arr [ " owner-id " ] == 0 ) {
2017-11-19 23:03:39 +01:00
$arr [ " owner-id " ] = Contact :: getIdForURL ( $arr [ " owner-link " ], 0 );
2017-04-14 16:59:51 +02:00
}
2016-06-15 21:20:55 +02:00
2017-11-19 23:03:39 +01:00
if ( Contact :: isBlocked ( $arr [ " owner-id " ])) {
2017-10-07 11:52:43 +02:00
logger ( 'Contact ' . $arr [ " owner-id " ] . ' is blocked, item ' . $arr [ " uri " ] . ' will not be stored' );
return 0 ;
}
2015-05-10 20:43:41 +02:00
if ( $arr [ 'guid' ] != " " ) {
// Checking if there is already an item with the same guid
logger ( 'checking for an item for user ' . $arr [ 'uid' ] . ' on network ' . $arr [ 'network' ] . ' with the guid ' . $arr [ 'guid' ], LOGGER_DEBUG );
$r = q ( " SELECT `guid` FROM `item` WHERE `guid` = '%s' AND `network` = '%s' AND `uid` = '%d' LIMIT 1 " ,
dbesc ( $arr [ 'guid' ]), dbesc ( $arr [ 'network' ]), intval ( $arr [ 'uid' ]));
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2015-05-10 20:43:41 +02:00
logger ( 'found item with guid ' . $arr [ 'guid' ] . ' for user ' . $arr [ 'uid' ] . ' on network ' . $arr [ 'network' ], LOGGER_DEBUG );
return 0 ;
}
}
2015-03-01 17:33:55 +01:00
// Check for hashtags in the body and repair or add hashtag links
item_body_set_hashtags ( $arr );
2012-08-05 13:30:51 +02:00
$arr [ 'thr-parent' ] = $arr [ 'parent-uri' ];
2017-04-26 23:16:25 +02:00
2016-10-22 12:14:41 +02:00
if ( $arr [ 'parent-uri' ] === $arr [ 'uri' ]) {
2010-11-12 05:32:20 +01:00
$parent_id = 0 ;
2012-02-28 13:56:16 +01:00
$parent_deleted = 0 ;
2010-11-12 05:32:20 +01:00
$allow_cid = $arr [ 'allow_cid' ];
$allow_gid = $arr [ 'allow_gid' ];
$deny_cid = $arr [ 'deny_cid' ];
$deny_gid = $arr [ 'deny_gid' ];
2014-08-31 23:52:25 +02:00
$notify_type = 'wall-new' ;
2016-10-22 12:14:41 +02:00
} else {
2010-11-12 05:32:20 +01:00
2013-01-27 23:25:04 +01:00
// find the parent and snarf the item id and ACLs
2011-03-08 23:40:33 +01:00
// and anything else we need to inherit
2010-11-12 05:32:20 +01:00
2011-10-12 11:21:18 +02:00
$r = q ( " SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d ORDER BY `id` ASC LIMIT 1 " ,
2010-11-12 05:32:20 +01:00
dbesc ( $arr [ 'parent-uri' ]),
intval ( $arr [ 'uid' ])
);
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2010-12-05 08:16:16 +01:00
// is the new message multi-level threaded?
// even though we don't support it now, preserve the info
// and re-attach to the conversation parent.
2016-10-22 12:14:41 +02:00
if ( $r [ 0 ][ 'uri' ] != $r [ 0 ][ 'parent-uri' ]) {
2010-12-05 08:16:16 +01:00
$arr [ 'parent-uri' ] = $r [ 0 ][ 'parent-uri' ];
2014-03-09 09:19:14 +01:00
$z = q ( " SELECT * FROM `item` WHERE `uri` = '%s' AND `parent-uri` = '%s' AND `uid` = %d
2011-10-12 11:21:18 +02:00
ORDER BY `id` ASC LIMIT 1 " ,
2011-08-09 04:10:36 +02:00
dbesc ( $r [ 0 ][ 'parent-uri' ]),
dbesc ( $r [ 0 ][ 'parent-uri' ]),
intval ( $arr [ 'uid' ])
);
2017-04-14 16:59:51 +02:00
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $z )) {
2011-08-09 04:10:36 +02:00
$r = $z ;
2017-04-14 16:59:51 +02:00
}
2010-12-05 08:16:16 +01:00
}
2011-02-04 13:25:53 +01:00
$parent_id = $r [ 0 ][ 'id' ];
$parent_deleted = $r [ 0 ][ 'deleted' ];
$allow_cid = $r [ 0 ][ 'allow_cid' ];
$allow_gid = $r [ 0 ][ 'allow_gid' ];
$deny_cid = $r [ 0 ][ 'deny_cid' ];
$deny_gid = $r [ 0 ][ 'deny_gid' ];
2011-03-08 23:40:33 +01:00
$arr [ 'wall' ] = $r [ 0 ][ 'wall' ];
2014-08-31 23:52:25 +02:00
$notify_type = 'comment-new' ;
2012-06-11 14:28:08 +02:00
2017-04-14 16:59:51 +02:00
/*
* If the parent is private , force privacy for the entire conversation
* This differs from the above settings as it subtly allows comments from
* email correspondents to be private even if the overall thread is not .
*/
if ( $r [ 0 ][ 'private' ]) {
2012-06-29 02:43:29 +02:00
$arr [ 'private' ] = $r [ 0 ][ 'private' ];
2017-04-14 16:59:51 +02:00
}
2012-06-11 14:28:08 +02:00
2017-04-14 16:59:51 +02:00
/*
* Edge case . We host a public forum that was originally posted to privately .
* The original author commented , but as this is a comment , the permissions
* weren ' t fixed up so it will still show the comment as private unless we fix it here .
*/
2017-10-31 20:33:23 +01:00
if (( intval ( $r [ 0 ][ 'forum_mode' ]) == 1 ) && $r [ 0 ][ 'private' ]) {
2012-06-19 02:19:56 +02:00
$arr [ 'private' ] = 0 ;
2017-04-14 16:59:51 +02:00
}
2014-03-09 09:19:14 +01:00
// If its a post from myself then tag the thread as "mention"
logger ( " item_store: Checking if parent " . $parent_id . " has to be tagged as mention for user " . $arr [ 'uid' ], LOGGER_DEBUG );
2016-10-07 08:05:43 +02:00
$u = q ( " SELECT `nickname` FROM `user` WHERE `uid` = %d " , intval ( $arr [ 'uid' ]));
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $u )) {
2017-08-26 09:32:10 +02:00
$self = normalise_link ( System :: baseUrl () . '/profile/' . $u [ 0 ][ 'nickname' ]);
2014-03-09 09:19:14 +01:00
logger ( " item_store: 'myself' is " . $self . " for parent " . $parent_id . " checking against " . $arr [ 'author-link' ] . " and " . $arr [ 'owner-link' ], LOGGER_DEBUG );
2017-06-08 04:00:59 +02:00
if (( normalise_link ( $arr [ 'author-link' ]) == $self ) || ( normalise_link ( $arr [ 'owner-link' ]) == $self )) {
2018-01-15 14:05:12 +01:00
dba :: update ( 'thread' , [ 'mention' => true ], [ 'iid' => $parent_id ]);
2014-03-09 09:19:14 +01:00
logger ( " item_store: tagged thread " . $parent_id . " as mention for user " . $self , LOGGER_DEBUG );
}
}
2016-10-07 08:05:43 +02:00
} else {
2017-04-14 16:59:51 +02:00
/*
* Allow one to see reply tweets from status . net even when
* we don 't have or can' t see the original post .
*/
2016-10-22 12:14:41 +02:00
if ( $force_parent ) {
2011-02-04 02:40:04 +01:00
logger ( 'item_store: $force_parent=true, reply converted to top-level post.' );
$parent_id = 0 ;
$arr [ 'parent-uri' ] = $arr [ 'uri' ];
2011-05-04 11:20:44 +02:00
$arr [ 'gravity' ] = 0 ;
2016-10-22 12:14:41 +02:00
} else {
2015-06-07 23:18:02 +02:00
logger ( 'item_store: item parent ' . $arr [ 'parent-uri' ] . ' for ' . $arr [ 'uid' ] . ' was not found - ignoring item' );
2011-02-04 02:40:04 +01:00
return 0 ;
}
2013-01-11 01:20:16 +01:00
2012-02-27 23:08:00 +01:00
$parent_deleted = 0 ;
2010-11-12 05:32:20 +01:00
}
}
2010-07-19 05:49:10 +02:00
2015-11-30 23:13:56 +01:00
$r = q ( " SELECT `id` FROM `item` WHERE `uri` = '%s' AND `network` IN ('%s', '%s') AND `uid` = %d LIMIT 1 " ,
2011-10-03 15:04:17 +02:00
dbesc ( $arr [ 'uri' ]),
2015-05-27 08:16:05 +02:00
dbesc ( $arr [ 'network' ]),
2015-11-30 23:13:56 +01:00
dbesc ( NETWORK_DFRN ),
2011-10-12 11:21:18 +02:00
intval ( $arr [ 'uid' ])
2011-10-03 15:04:17 +02:00
);
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2016-10-17 20:38:51 +02:00
logger ( 'duplicated item with the same uri found. ' . print_r ( $arr , true ));
2011-10-03 15:04:17 +02:00
return 0 ;
2015-05-27 08:16:05 +02:00
}
2016-10-17 20:38:51 +02:00
// On Friendica and Diaspora the GUID is unique
2018-01-15 14:05:12 +01:00
if ( in_array ( $arr [ 'network' ], [ NETWORK_DFRN , NETWORK_DIASPORA ])) {
2016-10-17 20:38:51 +02:00
$r = q ( " SELECT `id` FROM `item` WHERE `guid` = '%s' AND `uid` = %d LIMIT 1 " ,
dbesc ( $arr [ 'guid' ]),
intval ( $arr [ 'uid' ])
);
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2016-10-17 20:38:51 +02:00
logger ( 'duplicated item with the same guid found. ' . print_r ( $arr , true ));
return 0 ;
}
} else {
// Check for an existing post with the same content. There seems to be a problem with OStatus.
$r = q ( " SELECT `id` FROM `item` WHERE `body` = '%s' AND `network` = '%s' AND `created` = '%s' AND `contact-id` = %d AND `uid` = %d LIMIT 1 " ,
dbesc ( $arr [ 'body' ]),
dbesc ( $arr [ 'network' ]),
dbesc ( $arr [ 'created' ]),
intval ( $arr [ 'contact-id' ]),
intval ( $arr [ 'uid' ])
);
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2016-10-17 20:38:51 +02:00
logger ( 'duplicated item with the same body found. ' . print_r ( $arr , true ));
return 0 ;
}
2011-10-03 15:04:17 +02:00
}
2011-08-08 02:29:26 +02:00
2015-03-09 00:45:53 +01:00
// Is this item available in the global items (with uid=0)?
if ( $arr [ " uid " ] == 0 ) {
$arr [ " global " ] = true ;
2016-10-29 22:17:33 +02:00
// Set the global flag on all items if this was a global item entry
2018-01-15 14:05:12 +01:00
dba :: update ( 'item' , [ 'global' => true ], [ 'uri' => $arr [ " uri " ]]);
2016-10-22 12:14:41 +02:00
} else {
2016-04-03 16:36:05 +02:00
$isglobal = q ( " SELECT `global` FROM `item` WHERE `uid` = 0 AND `uri` = '%s' " , dbesc ( $arr [ " uri " ]));
2015-03-09 00:45:53 +01:00
2017-11-08 04:57:46 +01:00
$arr [ " global " ] = ( DBM :: is_result ( $isglobal ) && count ( $isglobal ) > 0 );
2015-03-09 00:45:53 +01:00
}
2016-10-07 08:05:43 +02:00
// ACL settings
2017-04-14 16:59:51 +02:00
if ( strlen ( $allow_cid ) || strlen ( $allow_gid ) || strlen ( $deny_cid ) || strlen ( $deny_gid )) {
2016-10-07 08:05:43 +02:00
$private = 1 ;
2017-04-14 16:59:51 +02:00
} else {
2016-10-07 08:05:43 +02:00
$private = $arr [ 'private' ];
2017-04-14 16:59:51 +02:00
}
2016-10-07 08:05:43 +02:00
$arr [ " allow_cid " ] = $allow_cid ;
$arr [ " allow_gid " ] = $allow_gid ;
$arr [ " deny_cid " ] = $deny_cid ;
$arr [ " deny_gid " ] = $deny_gid ;
$arr [ " private " ] = $private ;
$arr [ " deleted " ] = $parent_deleted ;
2015-03-07 21:24:39 +01:00
// Fill the cache field
put_item_in_cache ( $arr );
2017-04-14 16:59:51 +02:00
if ( $notify ) {
2018-01-17 19:42:40 +01:00
Addon :: callHooks ( 'post_local' , $arr );
2017-04-14 16:59:51 +02:00
} else {
2018-01-17 19:42:40 +01:00
Addon :: callHooks ( 'post_remote' , $arr );
2017-04-14 16:59:51 +02:00
}
2010-12-22 23:16:22 +01:00
2017-09-06 08:02:26 +02:00
// This array field is used to trigger some automatic reactions
// It is mainly used in the "post_local" hook.
unset ( $arr [ 'api_source' ]);
2017-04-14 16:59:51 +02:00
if ( x ( $arr , 'cancel' )) {
2018-01-17 20:22:38 +01:00
logger ( 'item_store: post cancelled by addon.' );
2012-01-31 05:49:54 +01:00
return 0 ;
}
2017-04-14 16:59:51 +02:00
/*
* Check for already added items .
* There is a timing issue here that sometimes creates double postings .
* An unique index would help - but the limitations of MySQL ( maximum size of index values ) prevent this .
*/
2016-10-29 22:17:33 +02:00
if ( $arr [ " uid " ] == 0 ) {
2017-09-15 23:00:39 +02:00
$r = q ( " SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = 0 LIMIT 1 " , dbesc ( trim ( $arr [ 'uri' ])));
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2016-10-29 22:17:33 +02:00
logger ( 'Global item already stored. URI: ' . $arr [ 'uri' ] . ' on network ' . $arr [ 'network' ], LOGGER_DEBUG );
return 0 ;
}
}
2010-11-04 03:47:07 +01:00
logger ( 'item_store: ' . print_r ( $arr , true ), LOGGER_DATA );
2017-05-11 22:13:45 +02:00
dba :: transaction ();
2017-08-09 23:12:41 +02:00
$r = dba :: insert ( 'item' , $arr );
2010-07-19 05:49:10 +02:00
2016-10-29 22:17:33 +02:00
// When the item was successfully stored we fetch the ID of the item.
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2017-08-12 15:54:29 +02:00
$current_post = dba :: lastInsertId ();
2016-10-29 22:17:33 +02:00
} else {
// This can happen - for example - if there are locking timeouts.
2017-05-11 22:13:45 +02:00
dba :: rollback ();
2016-12-01 14:50:26 +01:00
// Store the data into a spool file so that we can try again later.
// At first we restore the Diaspora signature that we removed above.
2016-12-01 23:52:35 +01:00
if ( isset ( $encoded_signature )) {
2016-12-01 14:50:26 +01:00
$arr [ 'dsprsig' ] = $encoded_signature ;
2016-12-01 23:52:35 +01:00
}
2016-12-01 14:50:26 +01:00
// Now we store the data in the spool directory
2017-02-19 09:23:21 +01:00
// We use "microtime" to keep the arrival order and "mt_rand" to avoid duplicates
$file = 'item-' . round ( microtime ( true ) * 10000 ) . '-' . mt_rand () . '.msg' ;
2017-02-19 11:13:40 +01:00
$spoolpath = get_spoolpath ();
if ( $spoolpath != " " ) {
$spool = $spoolpath . '/' . $file ;
file_put_contents ( $spool , json_encode ( $arr ));
logger ( " Item wasn't stored - Item was spooled into file " . $file , LOGGER_DEBUG );
}
2016-10-29 22:17:33 +02:00
return 0 ;
}
if ( $current_post == 0 ) {
// This is one of these error messages that never should occur.
logger ( " couldn't find created item - we better quit now. " );
2017-05-11 22:13:45 +02:00
dba :: rollback ();
2016-10-29 22:17:33 +02:00
return 0 ;
}
// How much entries have we created?
// We wouldn't need this query when we could use an unique index - but MySQL has length problems with them.
$r = q ( " SELECT COUNT(*) AS `entries` FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `network` = '%s' " ,
2015-01-25 00:19:59 +01:00
dbesc ( $arr [ 'uri' ]),
2015-10-10 14:26:07 +02:00
intval ( $arr [ 'uid' ]),
dbesc ( $arr [ 'network' ])
2010-07-19 05:49:10 +02:00
);
2011-05-30 07:50:36 +02:00
2017-11-08 04:57:46 +01:00
if ( ! DBM :: is_result ( $r )) {
2016-10-29 22:17:33 +02:00
// This shouldn't happen, since COUNT always works when the database connection is there.
logger ( " We couldn't count the stored entries. Very strange ... " );
2017-05-11 22:13:45 +02:00
dba :: rollback ();
2015-11-30 23:13:56 +01:00
return 0 ;
2016-10-29 22:17:33 +02:00
}
2015-06-02 22:07:39 +02:00
2016-10-29 22:17:33 +02:00
if ( $r [ 0 ][ " entries " ] > 1 ) {
// There are duplicates. We delete our just created entry.
2017-04-14 16:59:51 +02:00
logger ( 'Duplicated post occurred. uri = ' . $arr [ 'uri' ] . ' uid = ' . $arr [ 'uid' ]);
2014-01-05 16:10:02 +01:00
2016-10-29 22:17:33 +02:00
// Yes, we could do a rollback here - but we are having many users with MyISAM.
2018-01-15 14:05:12 +01:00
dba :: delete ( 'item' , [ 'id' => $current_post ]);
2017-05-11 22:13:45 +02:00
dba :: commit ();
2016-10-29 22:17:33 +02:00
return 0 ;
} elseif ( $r [ 0 ][ " entries " ] == 0 ) {
// This really should never happen since we quit earlier if there were problems.
logger ( " Something is terribly wrong. We haven't found our created entry. " );
2017-05-11 22:13:45 +02:00
dba :: rollback ();
2010-09-09 05:14:17 +02:00
return 0 ;
}
2010-07-19 05:49:10 +02:00
2016-10-29 22:17:33 +02:00
logger ( 'item_store: created item ' . $current_post );
2018-01-21 00:52:54 +01:00
Item :: updateContact ( $arr );
2016-10-29 22:17:33 +02:00
2017-04-14 16:59:51 +02:00
if ( ! $parent_id || ( $arr [ 'parent-uri' ] === $arr [ 'uri' ])) {
2010-11-12 05:32:20 +01:00
$parent_id = $current_post ;
2017-04-14 16:59:51 +02:00
}
2011-02-04 22:37:04 +01:00
2016-10-07 08:05:43 +02:00
// Set parent id
2018-01-15 14:05:12 +01:00
dba :: update ( 'item' , [ 'parent' => $parent_id ], [ 'id' => $current_post ]);
2010-07-19 05:49:10 +02:00
2014-06-15 23:33:25 +02:00
$arr [ 'id' ] = $current_post ;
$arr [ 'parent' ] = $parent_id ;
2012-06-12 07:09:50 +02:00
2011-09-19 04:04:11 +02:00
// update the commented timestamp on the parent
2015-02-22 17:34:04 +01:00
// Only update "commented" if it is really a comment
2017-11-07 03:22:52 +01:00
if (( $arr [ 'verb' ] == ACTIVITY_POST ) || ! Config :: get ( " system " , " like_no_comment " )) {
2018-01-15 14:05:12 +01:00
dba :: update ( 'item' , [ 'commented' => datetime_convert (), 'changed' => datetime_convert ()], [ 'id' => $parent_id ]);
2017-04-14 16:59:51 +02:00
} else {
2018-01-15 14:05:12 +01:00
dba :: update ( 'item' , [ 'changed' => datetime_convert ()], [ 'id' => $parent_id ]);
2017-04-14 16:59:51 +02:00
}
2011-09-16 15:49:24 +02:00
2016-10-22 12:14:41 +02:00
if ( $dsprsig ) {
2016-01-20 16:00:43 +01:00
2017-04-14 16:59:51 +02:00
/*
* Friendica servers lower than 3.4 . 3 - 2 had double encoded the signature ...
* We can check for this condition when we decode and encode the stuff again .
*/
2016-01-20 16:00:43 +01:00
if ( base64_encode ( base64_decode ( base64_decode ( $dsprsig -> signature ))) == base64_decode ( $dsprsig -> signature )) {
$dsprsig -> signature = base64_decode ( $dsprsig -> signature );
logger ( " Repaired double encoded signature from handle " . $dsprsig -> signer , LOGGER_DEBUG );
}
2018-01-15 14:05:12 +01:00
dba :: insert ( 'sign' , [ 'iid' => $current_post , 'signed_text' => $dsprsig -> signed_text ,
'signature' => $dsprsig -> signature , 'signer' => $dsprsig -> signer ]);
2011-08-29 04:22:27 +02:00
}
2017-04-08 19:30:35 +02:00
$deleted = tag_deliver ( $arr [ 'uid' ], $current_post );
2013-04-19 15:55:07 +02:00
2017-04-14 16:59:51 +02:00
/*
* current post can be deleted if is for a community page and no mention are
* in it .
*/
2017-06-08 04:00:59 +02:00
if ( ! $deleted && ! $dontcache ) {
2014-01-05 16:10:02 +01:00
2016-12-19 14:42:20 +01:00
$r = q ( 'SELECT * FROM `item` WHERE `id` = %d' , intval ( $current_post ));
2017-11-08 04:57:46 +01:00
if (( DBM :: is_result ( $r )) && ( count ( $r ) == 1 )) {
2016-12-30 21:48:09 +01:00
if ( $notify ) {
2018-01-17 19:42:40 +01:00
Addon :: callHooks ( 'post_local_end' , $r [ 0 ]);
2016-12-30 21:48:09 +01:00
} else {
2018-01-17 19:42:40 +01:00
Addon :: callHooks ( 'post_remote_end' , $r [ 0 ]);
2016-12-30 21:48:09 +01:00
}
} else {
2014-03-16 17:12:56 +01:00
logger ( 'item_store: new item not found in DB, id ' . $current_post );
2016-12-30 21:48:09 +01:00
}
2013-04-19 15:55:07 +02:00
}
2014-03-16 17:12:56 +01:00
2016-10-29 22:17:33 +02:00
if ( $arr [ 'parent-uri' ] === $arr [ 'uri' ]) {
add_thread ( $current_post );
} else {
update_thread ( $parent_id );
}
2017-05-11 22:13:45 +02:00
dba :: commit ();
2016-10-29 22:17:33 +02:00
2017-04-14 16:59:51 +02:00
/*
* Due to deadlock issues with the " term " table we are doing these steps after the commit .
* This is not perfect - but a workable solution until we found the reason for the problem .
*/
2015-02-09 23:04:18 +01:00
create_tags_from_item ( $current_post );
2018-01-10 18:05:20 +01:00
Term :: createFromItem ( $current_post );
2014-03-16 17:12:56 +01:00
2016-10-29 22:17:33 +02:00
if ( $arr [ 'parent-uri' ] === $arr [ 'uri' ]) {
2018-01-16 23:23:19 +01:00
Item :: addShadow ( $current_post );
2016-10-21 20:25:21 +02:00
} else {
2018-01-16 23:23:19 +01:00
Item :: addShadowPost ( $current_post );
2015-03-21 20:23:47 +01:00
}
2015-02-09 21:52:08 +01:00
2018-01-07 12:08:36 +01:00
check_user_notification ( $current_post );
2016-01-28 22:58:05 +01:00
2016-12-30 21:48:09 +01:00
if ( $notify ) {
2018-01-15 14:05:12 +01:00
Worker :: add ([ 'priority' => PRIORITY_HIGH , 'dont_fork' => true ], " Notifier " , $notify_type , $current_post );
2016-12-30 21:48:09 +01:00
}
2014-08-31 23:52:25 +02:00
2010-07-19 05:49:10 +02:00
return $current_post ;
}
2014-07-22 00:36:20 +02:00
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2015-03-01 17:33:55 +01:00
function item_body_set_hashtags ( & $item ) {
$tags = get_tags ( $item [ " body " ]);
// No hashtags?
2017-04-14 16:59:51 +02:00
if ( ! count ( $tags )) {
return false ;
}
2015-03-01 17:33:55 +01:00
// This sorting is important when there are hashtags that are part of other hashtags
// Otherwise there could be problems with hashtags like #test and #test2
rsort ( $tags );
$URLSearchString = " ^ \ [ \ ] " ;
2017-08-19 11:22:50 +02:00
// All hashtags should point to the home server if "local_tags" is activated
if ( Config :: get ( 'system' , 'local_tags' )) {
2017-08-19 00:12:40 +02:00
$item [ " body " ] = preg_replace ( " /# \ [url \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /url \ ]/ism " ,
2017-08-26 09:32:10 +02:00
" #[url= " . System :: baseUrl () . " /search?tag= $ 2] $ 2[/url] " , $item [ " body " ]);
2015-03-01 17:33:55 +01:00
2017-08-19 00:12:40 +02:00
$item [ " tag " ] = preg_replace ( " /# \ [url \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /url \ ]/ism " ,
2017-08-26 09:32:10 +02:00
" #[url= " . System :: baseUrl () . " /search?tag= $ 2] $ 2[/url] " , $item [ " tag " ]);
2017-08-19 00:12:40 +02:00
}
2015-03-01 17:33:55 +01:00
// mask hashtags inside of url, bookmarks and attachments to avoid urls in urls
$item [ " body " ] = preg_replace_callback ( " / \ [url \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /url \ ]/ism " ,
2017-04-08 19:30:35 +02:00
function ( $match ) {
2017-04-14 16:59:51 +02:00
return ( " [url= " . str_replace ( " # " , " # " , $match [ 1 ]) . " ] " . str_replace ( " # " , " # " , $match [ 2 ]) . " [/url] " );
2017-04-08 19:30:35 +02:00
}, $item [ " body " ]);
2015-03-01 17:33:55 +01:00
$item [ " body " ] = preg_replace_callback ( " / \ [bookmark \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /bookmark \ ]/ism " ,
2017-04-08 19:30:35 +02:00
function ( $match ) {
2017-04-14 16:59:51 +02:00
return ( " [bookmark= " . str_replace ( " # " , " # " , $match [ 1 ]) . " ] " . str_replace ( " # " , " # " , $match [ 2 ]) . " [/bookmark] " );
2017-04-08 19:30:35 +02:00
}, $item [ " body " ]);
2015-03-01 17:33:55 +01:00
$item [ " body " ] = preg_replace_callback ( " / \ [attachment (.*) \ ](.*?) \ [ \ /attachment \ ]/ism " ,
2017-04-08 19:30:35 +02:00
function ( $match ) {
2017-04-14 16:59:51 +02:00
return ( " [attachment " . str_replace ( " # " , " # " , $match [ 1 ]) . " ] " . $match [ 2 ] . " [/attachment] " );
2017-04-08 19:30:35 +02:00
}, $item [ " body " ]);
2015-03-01 17:33:55 +01:00
// Repair recursive urls
$item [ " body " ] = preg_replace ( " /# \ [url \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /url \ ]/ism " ,
" # $ 2 " , $item [ " body " ]);
2017-04-14 16:59:51 +02:00
foreach ( $tags as $tag ) {
2017-04-14 17:03:59 +02:00
if (( strpos ( $tag , '#' ) !== 0 ) || ( strpos ( $tag , '[url=' ))) {
2015-03-01 17:33:55 +01:00
continue ;
2017-04-14 16:59:51 +02:00
}
2015-03-01 17:33:55 +01:00
$basetag = str_replace ( '_' , ' ' , substr ( $tag , 1 ));
2015-03-01 20:40:38 +01:00
2017-08-26 09:32:10 +02:00
$newtag = '#[url=' . System :: baseUrl () . '/search?tag=' . rawurlencode ( $basetag ) . ']' . $basetag . '[/url]' ;
2015-03-01 20:40:38 +01:00
$item [ " body " ] = str_replace ( $tag , $newtag , $item [ " body " ]);
2017-04-14 16:59:51 +02:00
if ( ! stristr ( $item [ " tag " ], " /search?tag= " . $basetag . " ] " . $basetag . " [/url] " )) {
if ( strlen ( $item [ " tag " ])) {
2015-03-01 20:40:38 +01:00
$item [ " tag " ] = ',' . $item [ " tag " ];
2017-04-14 16:59:51 +02:00
}
2015-03-01 20:40:38 +01:00
$item [ " tag " ] = $newtag . $item [ " tag " ];
}
2015-03-01 17:33:55 +01:00
}
// Convert back the masked hashtags
$item [ " body " ] = str_replace ( " # " , " # " , $item [ " body " ]);
}
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2014-07-22 00:36:20 +02:00
function get_item_guid ( $id ) {
$r = q ( " SELECT `guid` FROM `item` WHERE `id` = %d LIMIT 1 " , intval ( $id ));
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2017-04-14 16:59:51 +02:00
return $r [ 0 ][ " guid " ];
} else {
/// @TODO This else-block can be elimited again
return " " ;
}
2014-07-22 00:36:20 +02:00
}
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2014-07-26 15:01:01 +02:00
function get_item_id ( $guid , $uid = 0 ) {
$nick = " " ;
$id = 0 ;
2017-04-14 16:59:51 +02:00
if ( $uid == 0 ) {
2014-07-26 15:01:01 +02:00
$uid == local_user ();
2017-04-14 16:59:51 +02:00
}
2014-07-26 15:01:01 +02:00
// Does the given user have this item?
if ( $uid ) {
$r = q ( " SELECT `item`.`id`, `user`.`nickname` FROM `item` INNER JOIN `user` ON `user`.`uid` = `item`.`uid`
2017-06-09 03:03:44 +02:00
WHERE `item` . `visible` = 1 AND `item` . `deleted` = 0 AND `item` . `moderated` = 0
2014-07-26 15:01:01 +02:00
AND `item` . `guid` = '%s' AND `item` . `uid` = % d " , dbesc( $guid ), intval( $uid ));
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2014-07-26 15:01:01 +02:00
$id = $r [ 0 ][ " id " ];
$nick = $r [ 0 ][ " nickname " ];
}
}
// Or is it anywhere on the server?
if ( $nick == " " ) {
$r = q ( " SELECT `item`.`id`, `user`.`nickname` FROM `item` INNER JOIN `user` ON `user`.`uid` = `item`.`uid`
2017-06-09 03:03:44 +02:00
WHERE `item` . `visible` = 1 AND `item` . `deleted` = 0 AND `item` . `moderated` = 0
2014-07-26 15:01:01 +02:00
AND `item` . `allow_cid` = '' AND `item` . `allow_gid` = ''
AND `item` . `deny_cid` = '' AND `item` . `deny_gid` = ''
AND `item` . `private` = 0 AND `item` . `wall` = 1
AND `item` . `guid` = '%s' " , dbesc( $guid ));
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2014-07-26 15:01:01 +02:00
$id = $r [ 0 ][ " id " ];
$nick = $r [ 0 ][ " nickname " ];
}
}
2018-01-15 14:05:12 +01:00
return [ " nick " => $nick , " id " => $id ];
2014-07-26 15:01:01 +02:00
}
2014-03-16 17:12:56 +01:00
// return - test
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2017-04-08 19:30:35 +02:00
function get_item_contact ( $item , $contacts ) {
2017-04-14 16:59:51 +02:00
if ( ! count ( $contacts ) || ( ! is_array ( $item ))) {
2010-09-27 01:30:21 +02:00
return false ;
2017-04-14 16:59:51 +02:00
}
foreach ( $contacts as $contact ) {
2016-10-22 12:14:41 +02:00
if ( $contact [ 'id' ] == $item [ 'contact-id' ]) {
2010-09-27 01:30:21 +02:00
return $contact ;
}
}
return false ;
}
2013-04-19 15:55:07 +02:00
/**
* look for mention tags and setup a second delivery chain for forum / community posts if appropriate
* @ param int $uid
* @ param int $item_id
* @ return bool true if item was deleted , else false
*/
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2018-01-04 03:12:19 +01:00
function tag_deliver ( $uid , $item_id )
{
2012-02-10 06:18:50 +01:00
$mention = false ;
2011-11-16 05:30:34 +01:00
2017-04-08 19:30:35 +02:00
$u = q ( " SELECT * FROM `user` WHERE `uid` = %d LIMIT 1 " ,
2012-02-10 06:18:50 +01:00
intval ( $uid )
2011-11-16 05:30:34 +01:00
);
2017-11-08 04:57:46 +01:00
if ( ! DBM :: is_result ( $u )) {
2011-11-16 05:30:34 +01:00
return ;
2016-12-20 15:37:27 +01:00
}
2011-11-16 05:30:34 +01:00
2012-02-10 06:18:50 +01:00
$community_page = (( $u [ 0 ][ 'page-flags' ] == PAGE_COMMUNITY ) ? true : false );
2012-05-18 04:35:24 +02:00
$prvgroup = (( $u [ 0 ][ 'page-flags' ] == PAGE_PRVGROUP ) ? true : false );
2016-12-20 15:37:27 +01:00
$i = q ( " SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1 " ,
2011-11-16 05:30:34 +01:00
intval ( $item_id ),
intval ( $uid )
);
2017-11-08 04:57:46 +01:00
if ( ! DBM :: is_result ( $i )) {
2011-11-16 05:30:34 +01:00
return ;
2016-12-20 15:37:27 +01:00
}
2011-11-16 05:30:34 +01:00
$item = $i [ 0 ];
2017-08-26 09:32:10 +02:00
$link = normalise_link ( System :: baseUrl () . '/profile/' . $u [ 0 ][ 'nickname' ]);
2011-11-16 05:30:34 +01:00
2017-04-14 16:59:51 +02:00
/*
* Diaspora uses their own hardwired link URL in @- tags
* instead of the one we supply with webfinger
*/
2017-08-26 09:32:10 +02:00
$dlink = normalise_link ( System :: baseUrl () . '/u/' . $u [ 0 ][ 'nickname' ]);
2012-01-04 22:50:12 +01:00
2017-04-14 17:38:11 +02:00
$cnt = preg_match_all ( '/[\@\!]\[url\=(.*?)\](.*?)\[\/url\]/ism' , $item [ 'body' ], $matches , PREG_SET_ORDER );
2016-10-22 12:14:41 +02:00
if ( $cnt ) {
2017-04-14 16:59:51 +02:00
foreach ( $matches as $mtch ) {
2017-04-08 19:30:35 +02:00
if ( link_compare ( $link , $mtch [ 1 ]) || link_compare ( $dlink , $mtch [ 1 ])) {
2012-02-10 06:18:50 +01:00
$mention = true ;
logger ( 'tag_deliver: mention found: ' . $mtch [ 2 ]);
2011-11-16 05:30:34 +01:00
}
}
}
2017-04-08 19:30:35 +02:00
if ( ! $mention ) {
if (( $community_page || $prvgroup ) &&
( ! $item [ 'wall' ]) && ( ! $item [ 'origin' ]) && ( $item [ 'id' ] == $item [ 'parent' ])) {
2013-04-19 15:55:07 +02:00
// mmh.. no mention.. community page or private group... no wall.. no origin.. top-post (not a comment)
// delete it!
logger ( " tag_deliver: no-mention top-level post to communuty or private group. delete. " );
2018-01-15 14:05:12 +01:00
dba :: delete ( 'item' , [ 'id' => $item_id ]);
2013-04-19 15:55:07 +02:00
return true ;
}
2011-11-16 05:30:34 +01:00
return ;
2013-04-19 15:55:07 +02:00
}
2013-11-02 10:49:44 +01:00
2018-01-15 14:05:12 +01:00
$arr = [ 'item' => $item , 'user' => $u [ 0 ], 'contact' => $r [ 0 ]];
2012-09-27 03:24:19 +02:00
2018-01-17 19:42:40 +01:00
Addon :: callHooks ( 'tagged' , $arr );
2012-09-27 03:24:19 +02:00
2017-04-14 16:59:51 +02:00
if (( ! $community_page ) && ( ! $prvgroup )) {
2012-05-18 07:44:52 +02:00
return ;
2017-04-14 16:59:51 +02:00
}
2012-05-18 04:35:24 +02:00
2017-04-14 16:59:51 +02:00
/*
* tgroup delivery - setup a second delivery chain
* prevent delivery looping - only proceed
* if the message originated elsewhere and is a top - level post
*/
2017-04-08 19:30:35 +02:00
if (( $item [ 'wall' ]) || ( $item [ 'origin' ]) || ( $item [ 'id' ] != $item [ 'parent' ])) {
2012-02-10 09:08:23 +01:00
return ;
2017-04-08 19:30:35 +02:00
}
2011-11-16 05:30:34 +01:00
2012-02-10 09:08:23 +01:00
// now change this copy of the post to a forum head message and deliver to all the tgroup members
2017-04-14 16:59:51 +02:00
$c = q ( " SELECT `name`, `url`, `thumb` FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1 " ,
2012-02-17 03:29:09 +01:00
intval ( $u [ 0 ][ 'uid' ])
);
2017-11-08 04:57:46 +01:00
if ( ! DBM :: is_result ( $c )) {
2012-02-17 03:29:09 +01:00
return ;
2016-12-22 16:58:50 +01:00
}
2012-02-17 03:29:09 +01:00
2012-05-07 08:06:21 +02:00
// also reset all the privacy bits to the forum default permissions
$private = ( $u [ 0 ][ 'allow_cid' ] || $u [ 0 ][ 'allow_gid' ] || $u [ 0 ][ 'deny_cid' ] || $u [ 0 ][ 'deny_gid' ]) ? 1 : 0 ;
2012-05-18 07:44:52 +02:00
$forum_mode = (( $prvgroup ) ? 2 : 1 );
2016-12-22 16:58:50 +01:00
q ( " UPDATE `item` SET `wall` = 1, `origin` = 1, `forum_mode` = %d, `owner-name` = '%s', `owner-link` = '%s', `owner-avatar` = '%s',
`private` = % d , `allow_cid` = '%s' , `allow_gid` = '%s' , `deny_cid` = '%s' , `deny_gid` = '%s' WHERE `id` = % d " ,
2012-05-18 07:44:52 +02:00
intval ( $forum_mode ),
2012-02-17 03:29:09 +01:00
dbesc ( $c [ 0 ][ 'name' ]),
dbesc ( $c [ 0 ][ 'url' ]),
dbesc ( $c [ 0 ][ 'thumb' ]),
2012-05-07 08:06:21 +02:00
intval ( $private ),
dbesc ( $u [ 0 ][ 'allow_cid' ]),
dbesc ( $u [ 0 ][ 'allow_gid' ]),
dbesc ( $u [ 0 ][ 'deny_cid' ]),
dbesc ( $u [ 0 ][ 'deny_gid' ]),
2012-02-10 09:08:23 +01:00
intval ( $item_id )
);
2014-03-09 09:19:14 +01:00
update_thread ( $item_id );
2012-02-10 09:08:23 +01:00
2018-01-15 14:05:12 +01:00
Worker :: add ([ 'priority' => PRIORITY_HIGH , 'dont_fork' => true ], 'Notifier' , 'tgroup' , $item_id );
2012-02-10 09:08:23 +01:00
2011-11-16 05:30:34 +01:00
}
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Protocol/DFRN.php
2017-04-08 19:30:35 +02:00
function tgroup_check ( $uid , $item ) {
2012-09-13 03:53:20 +02:00
$mention = false ;
// check that the message originated elsewhere and is a top-level post
2017-04-08 19:30:35 +02:00
if (( $item [ 'wall' ]) || ( $item [ 'origin' ]) || ( $item [ 'uri' ] != $item [ 'parent-uri' ])) {
2012-09-13 03:53:20 +02:00
return false ;
2017-04-08 19:30:35 +02:00
}
2012-09-13 03:53:20 +02:00
2016-12-20 15:37:27 +01:00
/// @TODO Encapsulate this or find it encapsulated and replace all occurrances
$u = q ( " SELECT * FROM `user` WHERE `uid` = %d LIMIT 1 " ,
2012-09-13 03:53:20 +02:00
intval ( $uid )
);
2017-11-08 04:57:46 +01:00
if ( ! DBM :: is_result ( $u )) {
2012-09-13 03:53:20 +02:00
return false ;
2016-12-20 15:37:27 +01:00
}
2012-09-13 03:53:20 +02:00
$community_page = (( $u [ 0 ][ 'page-flags' ] == PAGE_COMMUNITY ) ? true : false );
$prvgroup = (( $u [ 0 ][ 'page-flags' ] == PAGE_PRVGROUP ) ? true : false );
2017-08-26 09:32:10 +02:00
$link = normalise_link ( System :: baseUrl () . '/profile/' . $u [ 0 ][ 'nickname' ]);
2012-09-13 03:53:20 +02:00
2017-04-14 16:59:51 +02:00
/*
* Diaspora uses their own hardwired link URL in @- tags
* instead of the one we supply with webfinger
*/
2017-08-26 09:32:10 +02:00
$dlink = normalise_link ( System :: baseUrl () . '/u/' . $u [ 0 ][ 'nickname' ]);
2012-09-13 03:53:20 +02:00
2017-04-14 17:38:11 +02:00
$cnt = preg_match_all ( '/[\@\!]\[url\=(.*?)\](.*?)\[\/url\]/ism' , $item [ 'body' ], $matches , PREG_SET_ORDER );
2016-10-22 12:14:41 +02:00
if ( $cnt ) {
2016-12-22 16:58:50 +01:00
foreach ( $matches as $mtch ) {
2017-04-08 19:30:35 +02:00
if ( link_compare ( $link , $mtch [ 1 ]) || link_compare ( $dlink , $mtch [ 1 ])) {
2012-09-13 03:53:20 +02:00
$mention = true ;
logger ( 'tgroup_check: mention found: ' . $mtch [ 2 ]);
}
}
}
2016-12-22 16:58:50 +01:00
if ( ! $mention ) {
2012-09-13 03:53:20 +02:00
return false ;
2016-12-22 16:58:50 +01:00
}
2012-09-13 03:53:20 +02:00
2017-04-14 16:59:51 +02:00
/// @TODO Combine both return statements into one
2016-12-22 16:58:50 +01:00
return (( $community_page ) || ( $prvgroup ));
2010-09-27 01:30:21 +02:00
}
2010-10-01 04:41:22 +02:00
2017-04-14 16:59:51 +02:00
/**
* This function returns true if $update has an edited timestamp newer
* than $existing , i . e . $update contains new data which should override
* what ' s already there . If there is no timestamp yet , the update is
* assumed to be newer . If the update has no timestamp , the existing
* item is assumed to be up - to - date . If the timestamps are equal it
* assumes the update has been seen before and should be ignored .
*
2018-01-21 00:52:54 +01:00
* @ TODO fix type - hints ( both array )
2017-04-14 16:59:51 +02:00
*/
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Protocol/DFRN.php
2017-08-10 06:31:46 +02:00
function edited_timestamp_is_newer ( $existing , $update ) {
2017-04-14 16:59:51 +02:00
if ( ! x ( $existing , 'edited' ) || ! $existing [ 'edited' ]) {
2016-12-22 16:58:50 +01:00
return true ;
}
2017-04-14 16:59:51 +02:00
if ( ! x ( $update , 'edited' ) || ! $update [ 'edited' ]) {
2016-12-22 16:58:50 +01:00
return false ;
}
$existing_edited = datetime_convert ( 'UTC' , 'UTC' , $existing [ 'edited' ]);
$update_edited = datetime_convert ( 'UTC' , 'UTC' , $update [ 'edited' ]);
return ( strcmp ( $existing_edited , $update_edited ) < 0 );
2013-03-20 02:00:12 +01:00
}
2011-02-08 06:16:39 +01:00
/**
2010-10-22 06:48:22 +02:00
*
* consume_feed - process atom feed and update anything / everything we might need to update
*
2011-02-08 06:16:39 +01:00
* $xml = the ( atom ) feed to consume - RSS isn ' t as fully supported but may work for simple feeds .
*
2010-10-22 06:48:22 +02:00
* $importer = the contact_record ( joined to user_record ) of the local user who owns this relationship .
* It is this person ' s stuff that is going to be updated .
* $contact = the person who is sending us stuff . If not set , we MAY be processing a " follow " activity
2014-05-12 19:02:03 +02:00
* from an external network and MAY create an appropriate contact record . Otherwise , we MUST
2010-10-22 06:48:22 +02:00
* have a contact record .
2014-05-12 19:02:03 +02:00
* $hub = should we find a hub declation in the feed , pass it back to our calling process , who might ( or
2010-10-22 06:48:22 +02:00
* might not ) try and subscribe to it .
2011-10-04 13:38:58 +02:00
* $datedir sorts in reverse order
2014-05-12 19:02:03 +02:00
* $pass - by default ( $pass = 0 ) we cannot guarantee that a parent item has been
2011-10-04 13:38:58 +02:00
* imported prior to its children being seen in the stream unless we are certain
* of how the feed is arranged / ordered .
* With $pass = 1 , we only pull parent items out of the stream .
* With $pass = 2 , we only pull children ( comments / likes ) .
2010-10-22 06:48:22 +02:00
*
2011-10-04 13:38:58 +02:00
* So running this twice , first with pass 1 and then with pass 2 will do the right
* thing regardless of feed ordering . This won ' t be adequate in a fully - threaded
* model where comments can have sub - threads . That would require some massive sorting
* to get all the feed items into a mostly linear ordering , and might still require
2014-03-16 17:12:56 +01:00
* recursion .
2017-04-14 16:59:51 +02:00
*
2018-01-21 00:52:54 +01:00
* @ TODO find proper type - hints
2010-10-22 06:48:22 +02:00
*/
2018-01-21 00:52:54 +01:00
/// @TODO move to ???
2017-04-14 16:59:51 +02:00
function consume_feed ( $xml , $importer , & $contact , & $hub , $datedir = 0 , $pass = 0 ) {
2015-06-07 23:18:02 +02:00
if ( $contact [ 'network' ] === NETWORK_OSTATUS ) {
if ( $pass < 2 ) {
2015-12-03 14:38:04 +01:00
// Test - remove before flight
//$tempfile = tempnam(get_temppath(), "ostatus2");
//file_put_contents($tempfile, $xml);
2015-06-07 23:18:02 +02:00
logger ( " Consume OStatus messages " , LOGGER_DEBUG );
2017-11-16 05:09:11 +01:00
OStatus :: import ( $xml , $importer , $contact , $hub );
2015-06-07 23:18:02 +02:00
}
return ;
}
2010-10-01 04:41:22 +02:00
2015-09-27 14:02:05 +02:00
if ( $contact [ 'network' ] === NETWORK_FEED ) {
if ( $pass < 2 ) {
logger ( " Consume feeds " , LOGGER_DEBUG );
2017-12-13 08:02:52 +01:00
Feed :: import ( $xml , $importer , $contact , $hub );
2015-09-27 14:02:05 +02:00
}
return ;
}
2016-02-04 23:52:06 +01:00
2016-02-03 23:04:52 +01:00
if ( $contact [ 'network' ] === NETWORK_DFRN ) {
logger ( " Consume DFRN messages " , LOGGER_DEBUG );
2017-04-14 16:59:51 +02:00
$r = q ( " SELECT `contact`.*, `contact`.`uid` AS `importer_uid`,
2016-04-17 20:43:41 +02:00
`contact` . `pubkey` AS `cpubkey` ,
`contact` . `prvkey` AS `cprvkey` ,
`contact` . `thumb` AS `thumb` ,
`contact` . `url` as `url` ,
`contact` . `name` as `senderName` ,
`user` .*
FROM `contact`
LEFT JOIN `user` ON `contact` . `uid` = `user` . `uid`
WHERE `contact` . `id` = % d AND `user` . `uid` = % d " ,
dbesc ( $contact [ " id " ]), dbesc ( $importer [ " uid " ])
);
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2016-02-04 23:52:06 +01:00
logger ( " Now import the DFRN feed " );
2017-11-08 04:57:46 +01:00
DFRN :: import ( $xml , $r [ 0 ], true );
2016-02-03 23:04:52 +01:00
return ;
}
}
2016-02-05 21:25:20 +01:00
}
2016-02-04 23:52:06 +01:00
2017-04-14 16:59:51 +02:00
/// @TODO type-hint is array
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2016-02-05 21:25:20 +01:00
function item_is_remote_self ( $contact , & $datarray ) {
$a = get_app ();
2013-01-11 01:20:16 +01:00
2017-04-14 16:59:51 +02:00
if ( ! $contact [ 'remote_self' ]) {
2016-02-05 21:25:20 +01:00
return false ;
2017-04-14 16:59:51 +02:00
}
2011-01-14 00:45:42 +01:00
2016-02-05 21:25:20 +01:00
// Prevent the forwarding of posts that are forwarded
2017-04-14 16:59:51 +02:00
if ( $datarray [ " extid " ] == NETWORK_DFRN ) {
2016-02-05 21:25:20 +01:00
return false ;
2017-04-14 16:59:51 +02:00
}
2011-01-14 00:45:42 +01:00
2016-02-05 21:25:20 +01:00
// Prevent to forward already forwarded posts
2017-04-14 16:59:51 +02:00
if ( $datarray [ " app " ] == $a -> get_hostname ()) {
2016-02-05 21:25:20 +01:00
return false ;
2017-04-14 16:59:51 +02:00
}
2013-01-11 01:20:16 +01:00
2016-02-05 21:25:20 +01:00
// Only forward posts
2017-04-14 16:59:51 +02:00
if ( $datarray [ " verb " ] != ACTIVITY_POST ) {
2016-02-05 21:25:20 +01:00
return false ;
2017-04-14 16:59:51 +02:00
}
2011-01-14 00:45:42 +01:00
2017-06-08 04:00:59 +02:00
if (( $contact [ 'network' ] != NETWORK_FEED ) && $datarray [ 'private' ]) {
2016-02-05 21:25:20 +01:00
return false ;
2017-04-14 16:59:51 +02:00
}
2011-01-14 00:45:42 +01:00
2016-02-05 21:25:20 +01:00
$datarray2 = $datarray ;
logger ( 'remote-self start - Contact ' . $contact [ 'url' ] . ' - ' . $contact [ 'remote_self' ] . ' Item ' . print_r ( $datarray , true ), LOGGER_DEBUG );
if ( $contact [ 'remote_self' ] == 2 ) {
$r = q ( " SELECT `id`,`url`,`name`,`thumb` FROM `contact` WHERE `uid` = %d AND `self` " ,
intval ( $contact [ 'uid' ]));
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2016-02-05 21:25:20 +01:00
$datarray [ 'contact-id' ] = $r [ 0 ][ " id " ];
2011-01-14 00:45:42 +01:00
2016-02-05 21:25:20 +01:00
$datarray [ 'owner-name' ] = $r [ 0 ][ " name " ];
$datarray [ 'owner-link' ] = $r [ 0 ][ " url " ];
$datarray [ 'owner-avatar' ] = $r [ 0 ][ " thumb " ];
2011-01-14 00:45:42 +01:00
2016-02-05 21:25:20 +01:00
$datarray [ 'author-name' ] = $datarray [ 'owner-name' ];
$datarray [ 'author-link' ] = $datarray [ 'owner-link' ];
$datarray [ 'author-avatar' ] = $datarray [ 'owner-avatar' ];
2017-08-03 07:42:44 +02:00
unset ( $datarray [ 'created' ]);
unset ( $datarray [ 'edited' ]);
2011-01-14 00:45:42 +01:00
}
2011-10-24 13:17:46 +02:00
2016-02-05 21:25:20 +01:00
if ( $contact [ 'network' ] != NETWORK_FEED ) {
$datarray [ " guid " ] = get_guid ( 32 );
unset ( $datarray [ " plink " ]);
2017-04-08 19:30:35 +02:00
$datarray [ " uri " ] = item_new_uri ( $a -> get_hostname (), $contact [ 'uid' ], $datarray [ " guid " ]);
2016-02-05 21:25:20 +01:00
$datarray [ " parent-uri " ] = $datarray [ " uri " ];
$datarray [ " extid " ] = $contact [ 'network' ];
$urlpart = parse_url ( $datarray2 [ 'author-link' ]);
$datarray [ " app " ] = $urlpart [ " host " ];
2017-04-14 16:59:51 +02:00
} else {
2016-02-05 21:25:20 +01:00
$datarray [ 'private' ] = 0 ;
2017-04-14 16:59:51 +02:00
}
2011-02-08 13:25:27 +01:00
}
2016-02-05 21:25:20 +01:00
if ( $contact [ 'network' ] != NETWORK_FEED ) {
// Store the original post
$r = item_store ( $datarray2 , false , false );
logger ( 'remote-self post original item - Contact ' . $contact [ 'url' ] . ' return ' . $r . ' Item ' . print_r ( $datarray2 , true ), LOGGER_DEBUG );
2017-04-14 16:59:51 +02:00
} else {
2016-02-05 21:25:20 +01:00
$datarray [ " app " ] = " Feed " ;
2017-04-14 16:59:51 +02:00
}
2014-10-29 01:05:09 +01:00
2017-09-08 09:08:06 +02:00
// Trigger automatic reactions for addons
$datarray [ 'api_source' ] = true ;
// We have to tell the hooks who we are - this really should be improved
$_SESSION [ " authenticated " ] = true ;
$_SESSION [ " uid " ] = $contact [ 'uid' ];
2014-10-29 01:05:09 +01:00
return true ;
}
2017-04-14 16:59:51 +02:00
/// @TODO find proper type-hints
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2017-03-31 20:41:32 +02:00
function new_follower ( $importer , $contact , $datarray , $item , $sharing = false ) {
2010-10-25 05:39:24 +02:00
$url = notags ( trim ( $datarray [ 'author-link' ]));
$name = notags ( trim ( $datarray [ 'author-name' ]));
$photo = notags ( trim ( $datarray [ 'author-avatar' ]));
2015-07-13 23:50:33 +02:00
if ( is_object ( $item )) {
$rawtag = $item -> get_item_tags ( NAMESPACE_ACTIVITY , 'actor' );
2017-03-31 20:41:32 +02:00
if ( $rawtag && $rawtag [ 0 ][ 'child' ][ NAMESPACE_POCO ][ 'preferredUsername' ][ 0 ][ 'data' ]) {
2015-07-13 23:50:33 +02:00
$nick = $rawtag [ 0 ][ 'child' ][ NAMESPACE_POCO ][ 'preferredUsername' ][ 0 ][ 'data' ];
2017-03-31 20:41:32 +02:00
}
} else {
2015-07-13 23:50:33 +02:00
$nick = $item ;
2017-03-31 20:41:32 +02:00
}
2010-10-25 05:39:24 +02:00
2016-10-22 12:14:41 +02:00
if ( is_array ( $contact )) {
if (( $contact [ 'network' ] == NETWORK_OSTATUS && $contact [ 'rel' ] == CONTACT_IS_SHARING )
2011-10-03 01:18:01 +02:00
|| ( $sharing && $contact [ 'rel' ] == CONTACT_IS_FOLLOWER )) {
2018-01-15 14:05:12 +01:00
dba :: update ( 'contact' , [ 'rel' => CONTACT_IS_FRIEND , 'writable' => true ],
[ 'id' => $contact [ 'id' ], 'uid' => $importer [ 'uid' ]]);
2010-10-25 05:39:24 +02:00
}
// send email notification to owner?
2015-11-28 01:03:26 +01:00
} else {
2011-07-02 02:39:16 +02:00
// create contact record
2018-01-04 03:12:19 +01:00
q ( " INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `name`, `nick`, `photo`, `network`, `rel`,
2015-11-28 01:03:26 +01:00
`blocked` , `readonly` , `pending` , `writable` )
VALUES ( % d , '%s' , '%s' , '%s' , '%s' , '%s' , '%s' , '%s' , % d , 0 , 0 , 1 , 1 ) " ,
2010-10-25 05:39:24 +02:00
intval ( $importer [ 'uid' ]),
dbesc ( datetime_convert ()),
dbesc ( $url ),
2011-11-02 00:08:07 +01:00
dbesc ( normalise_link ( $url )),
2010-10-25 05:39:24 +02:00
dbesc ( $name ),
dbesc ( $nick ),
dbesc ( $photo ),
2017-12-02 22:57:39 +01:00
dbesc ( NETWORK_OSTATUS ),
intval ( CONTACT_IS_FOLLOWER )
2010-10-25 05:39:24 +02:00
);
2018-01-04 03:12:19 +01:00
2016-04-13 22:21:23 +02:00
$r = q ( " SELECT `id`, `network` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `pending` = 1 LIMIT 1 " ,
2010-10-25 05:39:24 +02:00
intval ( $importer [ 'uid' ]),
2011-10-03 01:18:01 +02:00
dbesc ( $url )
2010-10-25 05:39:24 +02:00
);
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2016-06-25 13:56:55 +02:00
$contact_record = $r [ 0 ];
2017-11-29 23:29:11 +01:00
Contact :: updateAvatar ( $photo , $importer [ " uid " ], $contact_record [ " id " ], true );
2010-10-25 05:39:24 +02:00
}
2014-09-06 18:15:18 +02:00
2017-04-14 16:59:51 +02:00
/// @TODO Encapsulate this into a function/method
2010-11-06 22:40:19 +01:00
$r = q ( " SELECT * FROM `user` WHERE `uid` = %d LIMIT 1 " ,
intval ( $importer [ 'uid' ])
);
2018-01-15 14:05:12 +01:00
if ( DBM :: is_result ( $r ) && ! in_array ( $r [ 0 ][ 'page-flags' ], [ PAGE_SOAPBOX , PAGE_FREELOVE , PAGE_COMMUNITY ])) {
2015-11-28 01:03:26 +01:00
// create notification
$hash = random_string ();
2016-10-22 12:14:41 +02:00
if ( is_array ( $contact_record )) {
2018-01-15 14:05:12 +01:00
dba :: insert ( 'intro' , [ 'uid' => $importer [ 'uid' ], 'contact-id' => $contact_record [ 'id' ],
2017-08-10 00:04:00 +02:00
'blocked' => false , 'knowyou' => false ,
2018-01-15 14:05:12 +01:00
'hash' => $hash , 'datetime' => datetime_convert ()]);
2015-11-28 01:03:26 +01:00
}
2012-05-18 07:44:52 +02:00
2017-12-09 19:45:17 +01:00
Group :: addMember ( User :: getDefaultGroup ( $importer [ 'uid' ], $contact_record [ " network " ]), $contact_record [ 'id' ]);
2012-05-18 07:44:52 +02:00
2016-10-22 12:14:41 +02:00
if (( $r [ 0 ][ 'notify-flags' ] & NOTIFY_INTRO ) &&
2018-01-15 14:05:12 +01:00
in_array ( $r [ 0 ][ 'page-flags' ], [ PAGE_NORMAL ])) {
2014-09-06 18:15:18 +02:00
2018-01-15 14:05:12 +01:00
notification ([
2014-09-06 18:15:18 +02:00
'type' => NOTIFY_INTRO ,
'notify_flags' => $r [ 0 ][ 'notify-flags' ],
'language' => $r [ 0 ][ 'language' ],
'to_name' => $r [ 0 ][ 'username' ],
'to_email' => $r [ 0 ][ 'email' ],
'uid' => $r [ 0 ][ 'uid' ],
2017-08-26 09:32:10 +02:00
'link' => System :: baseUrl () . '/notifications/intro' ,
2018-01-21 19:33:59 +01:00
'source_name' => (( strlen ( stripslashes ( $contact_record [ 'name' ]))) ? stripslashes ( $contact_record [ 'name' ]) : L10n :: t ( '[Name Withheld]' )),
2014-09-06 18:15:18 +02:00
'source_link' => $contact_record [ 'url' ],
'source_photo' => $contact_record [ 'photo' ],
'verb' => ( $sharing ? ACTIVITY_FRIEND : ACTIVITY_FOLLOW ),
'otype' => 'intro'
2018-01-15 14:05:12 +01:00
]);
2014-09-06 18:15:18 +02:00
2010-11-06 22:40:19 +01:00
}
2018-01-15 14:05:12 +01:00
} elseif ( DBM :: is_result ( $r ) && in_array ( $r [ 0 ][ 'page-flags' ], [ PAGE_SOAPBOX , PAGE_FREELOVE , PAGE_COMMUNITY ])) {
2018-01-04 03:12:19 +01:00
q ( " UPDATE `contact` SET `pending` = 0 WHERE `uid` = %d AND `url` = '%s' AND `pending` LIMIT 1 " ,
2015-11-28 01:03:26 +01:00
intval ( $importer [ 'uid' ]),
dbesc ( $url )
);
2010-11-06 22:40:19 +01:00
}
2015-11-28 01:03:26 +01:00
2010-10-25 05:39:24 +02:00
}
2010-10-22 06:48:22 +02:00
}
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2018-01-15 14:05:12 +01:00
function lose_follower ( $importer , $contact , array $datarray = [], $item = " " ) {
2010-10-22 06:48:22 +02:00
2016-10-22 12:14:41 +02:00
if (( $contact [ 'rel' ] == CONTACT_IS_FRIEND ) || ( $contact [ 'rel' ] == CONTACT_IS_SHARING )) {
2018-01-15 14:05:12 +01:00
dba :: update ( 'contact' , [ 'rel' => CONTACT_IS_SHARING ], [ 'id' => $contact [ 'id' ]]);
2016-10-22 12:14:41 +02:00
} else {
2017-11-19 23:03:39 +01:00
Contact :: remove ( $contact [ 'id' ]);
2010-10-25 05:39:24 +02:00
}
2010-10-22 06:48:22 +02:00
}
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2018-01-15 14:05:12 +01:00
function lose_sharer ( $importer , $contact , array $datarray = [], $item = " " ) {
2011-10-03 01:18:01 +02:00
2016-10-22 12:14:41 +02:00
if (( $contact [ 'rel' ] == CONTACT_IS_FRIEND ) || ( $contact [ 'rel' ] == CONTACT_IS_FOLLOWER )) {
2018-01-15 14:05:12 +01:00
dba :: update ( 'contact' , [ 'rel' => CONTACT_IS_FOLLOWER ], [ 'id' => $contact [ 'id' ]]);
2016-10-22 12:14:41 +02:00
} else {
2017-11-19 23:03:39 +01:00
Contact :: remove ( $contact [ 'id' ]);
2011-10-03 01:18:01 +02:00
}
}
2018-01-21 00:52:54 +01:00
/// @TODO move to ???
2017-03-31 20:41:32 +02:00
function subscribe_to_hub ( $url , $importer , $contact , $hubmode = 'subscribe' ) {
2010-10-01 06:38:45 +02:00
2012-06-07 08:10:32 +02:00
$a = get_app ();
2016-10-22 12:14:41 +02:00
if ( is_array ( $importer )) {
2010-10-01 06:38:45 +02:00
$r = q ( " SELECT `nickname` FROM `user` WHERE `uid` = %d LIMIT 1 " ,
intval ( $importer [ 'uid' ])
);
}
2011-09-22 13:11:39 +02:00
2017-04-14 16:59:51 +02:00
/*
* Diaspora has different message - ids in feeds than they do
* through the direct Diaspora protocol . If we try and use
* the feed , we 'll get duplicates. So don' t .
*/
2017-11-08 04:57:46 +01:00
if (( ! DBM :: is_result ( $r )) || $contact [ 'network' ] === NETWORK_DIASPORA ) {
2010-10-01 06:38:45 +02:00
return ;
2017-04-14 16:59:51 +02:00
}
2010-10-01 06:38:45 +02:00
2017-11-07 03:22:52 +01:00
$push_url = Config :: get ( 'system' , 'url' ) . '/pubsub/' . $r [ 0 ][ 'nickname' ] . '/' . $contact [ 'id' ];
2010-10-01 06:38:45 +02:00
2010-10-15 13:20:42 +02:00
// Use a single verify token, even if multiple hubs
$verify_token = (( strlen ( $contact [ 'hub-verify' ])) ? $contact [ 'hub-verify' ] : random_string ());
2010-10-01 06:38:45 +02:00
2011-09-22 13:11:39 +02:00
$params = 'hub.mode=' . $hubmode . '&hub.callback=' . urlencode ( $push_url ) . '&hub.topic=' . urlencode ( $contact [ 'poll' ]) . '&hub.verify=async&hub.verify_token=' . $verify_token ;
2010-10-01 06:38:45 +02:00
2011-10-05 03:53:56 +02:00
logger ( 'subscribe_to_hub: ' . $hubmode . ' ' . $contact [ 'name' ] . ' to hub ' . $url . ' endpoint: ' . $push_url . ' with verifier ' . $verify_token );
2010-11-05 04:47:44 +01:00
2017-06-08 04:00:59 +02:00
if ( ! strlen ( $contact [ 'hub-verify' ]) || ( $contact [ 'hub-verify' ] != $verify_token )) {
2018-01-15 14:05:12 +01:00
dba :: update ( 'contact' , [ 'hub-verify' => $verify_token ], [ 'id' => $contact [ 'id' ]]);
2010-10-15 13:20:42 +02:00
}
2010-10-01 06:38:45 +02:00
2017-04-08 19:30:35 +02:00
post_url ( $url , $params );
2012-06-07 08:10:32 +02:00
logger ( 'subscribe_to_hub: returns: ' . $a -> get_curl_code (), LOGGER_DEBUG );
2013-01-11 01:20:16 +01:00
2010-10-01 06:38:45 +02:00
return ;
2010-11-02 01:56:36 +01:00
}
2018-01-04 03:12:19 +01:00
/**
*
* @ param string $s
* @ param int $uid
* @ param array $item
* @ param int $cid
* @ return string
*/
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2018-01-04 03:12:19 +01:00
function fix_private_photos ( $s , $uid , $item = null , $cid = 0 )
{
if ( Config :: get ( 'system' , 'disable_embedded' )) {
2013-03-03 17:44:41 +01:00
return $s ;
2017-04-14 16:59:51 +02:00
}
2013-03-03 17:44:41 +01:00
logger ( 'fix_private_photos: check for photos' , LOGGER_DEBUG );
2018-01-04 03:12:19 +01:00
$site = substr ( System :: baseUrl (), strpos ( System :: baseUrl (), '://' ));
2011-05-01 02:24:37 +02:00
2012-07-08 00:20:24 +02:00
$orig_body = $s ;
$new_body = '' ;
$img_start = strpos ( $orig_body , '[img' );
$img_st_close = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), ']' ) : false );
2012-07-08 02:47:13 +02:00
$img_len = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start + $img_st_close + 1 ), '[/img]' ) : false );
2012-07-08 00:20:24 +02:00
2018-01-04 03:12:19 +01:00
while (( $img_st_close !== false ) && ( $img_len !== false )) {
2012-07-08 00:20:24 +02:00
$img_st_close ++ ; // make it point to AFTER the closing bracket
$image = substr ( $orig_body , $img_start + $img_st_close , $img_len );
2012-05-28 06:01:58 +02:00
logger ( 'fix_private_photos: found photo ' . $image , LOGGER_DEBUG );
2012-07-08 00:20:24 +02:00
2018-01-04 03:12:19 +01:00
if ( stristr ( $image , $site . '/photo/' )) {
2012-07-08 00:20:24 +02:00
// Only embed locally hosted photos
2012-05-28 06:01:58 +02:00
$replace = false ;
2011-05-01 02:24:37 +02:00
$i = basename ( $image );
2018-01-15 14:05:12 +01:00
$i = str_replace ([ '.jpg' , '.png' , '.gif' ], [ '' , '' , '' ], $i );
2017-04-14 16:59:51 +02:00
$x = strpos ( $i , '-' );
2012-07-08 00:20:24 +02:00
2016-10-22 12:14:41 +02:00
if ( $x ) {
2017-04-14 17:38:11 +02:00
$res = substr ( $i , $x + 1 );
$i = substr ( $i , 0 , $x );
2011-05-01 02:24:37 +02:00
$r = q ( " SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `scale` = %d AND `uid` = %d " ,
dbesc ( $i ),
intval ( $res ),
intval ( $uid )
2017-04-14 16:59:51 +02:00
);
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2017-04-14 16:59:51 +02:00
/*
* Check to see if we should replace this photo link with an embedded image
* 1. No need to do so if the photo is public
* 2. If there 's a contact-id provided, see if they' re in the access list
* for the photo . If so , embed it .
* 3. Otherwise , if we have an item , see if the item permissions match the photo
* permissions , regardless of order but first check to see if they ' re an exact
* match to save some processing overhead .
*/
2016-10-22 12:14:41 +02:00
if ( has_permissions ( $r [ 0 ])) {
if ( $cid ) {
2012-05-28 06:01:58 +02:00
$recips = enumerate_permissions ( $r [ 0 ]);
2016-10-22 12:14:41 +02:00
if ( in_array ( $cid , $recips )) {
2014-05-12 19:02:03 +02:00
$replace = true ;
2012-05-28 06:01:58 +02:00
}
2016-10-22 12:14:41 +02:00
} elseif ( $item ) {
2017-04-14 16:59:51 +02:00
if ( compare_permissions ( $item , $r [ 0 ])) {
2012-05-28 06:01:58 +02:00
$replace = true ;
2017-04-14 16:59:51 +02:00
}
2012-05-28 06:01:58 +02:00
}
}
2016-10-22 12:14:41 +02:00
if ( $replace ) {
2012-07-08 00:20:24 +02:00
$data = $r [ 0 ][ 'data' ];
$type = $r [ 0 ][ 'type' ];
// If a custom width and height were specified, apply before embedding
2016-10-22 12:14:41 +02:00
if ( preg_match ( " / \ [img \ =([0-9]*)x([0-9]*) \ ]/is " , substr ( $orig_body , $img_start , $img_st_close ), $match )) {
2012-07-08 00:20:24 +02:00
logger ( 'fix_private_photos: scaling photo' , LOGGER_DEBUG );
$width = intval ( $match [ 1 ]);
$height = intval ( $match [ 2 ]);
2017-12-07 14:56:11 +01:00
$Image = new Image ( $data , $type );
if ( $Image -> isValid ()) {
$Image -> scaleDown ( max ( $width , $height ));
$data = $Image -> asString ();
$type = $Image -> getType ();
2012-07-08 00:20:24 +02:00
}
}
2012-05-29 01:51:52 +02:00
logger ( 'fix_private_photos: replacing photo' , LOGGER_DEBUG );
2012-07-08 00:20:24 +02:00
$image = 'data:' . $type . ';base64,' . base64_encode ( $data );
logger ( 'fix_private_photos: replaced: ' . $image , LOGGER_DATA );
2012-05-28 06:01:58 +02:00
}
2011-05-01 02:24:37 +02:00
}
}
2014-05-12 19:02:03 +02:00
}
2012-07-08 00:20:24 +02:00
$new_body = $new_body . substr ( $orig_body , 0 , $img_start + $img_st_close ) . $image . '[/img]' ;
$orig_body = substr ( $orig_body , $img_start + $img_st_close + $img_len + strlen ( '[/img]' ));
2017-04-08 19:30:35 +02:00
if ( $orig_body === false ) {
2012-07-08 00:20:24 +02:00
$orig_body = '' ;
2017-04-08 19:30:35 +02:00
}
2012-07-08 00:20:24 +02:00
$img_start = strpos ( $orig_body , '[img' );
$img_st_close = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), ']' ) : false );
2012-07-08 02:47:13 +02:00
$img_len = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start + $img_st_close + 1 ), '[/img]' ) : false );
2011-05-01 02:24:37 +02:00
}
2012-07-08 00:20:24 +02:00
2012-07-08 02:47:13 +02:00
$new_body = $new_body . $orig_body ;
2012-07-08 00:20:24 +02:00
2017-04-14 16:59:51 +02:00
return $new_body ;
2011-05-01 02:24:37 +02:00
}
2017-04-14 16:59:51 +02:00
/// @TODO type-hint is array
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2012-05-28 06:01:58 +02:00
function has_permissions ( $obj ) {
2017-04-14 16:59:51 +02:00
return (
(
x ( $obj , 'allow_cid' )
) || (
x ( $obj , 'allow_gid' )
) || (
x ( $obj , 'deny_cid' )
) || (
x ( $obj , 'deny_gid' )
)
);
2012-05-28 06:01:58 +02:00
}
2017-04-14 16:59:51 +02:00
/// @TODO type-hint is array
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2017-04-08 19:30:35 +02:00
function compare_permissions ( $obj1 , $obj2 ) {
2014-05-12 19:02:03 +02:00
// first part is easy. Check that these are exactly the same.
2016-10-22 12:14:41 +02:00
if (( $obj1 [ 'allow_cid' ] == $obj2 [ 'allow_cid' ])
2012-05-28 06:01:58 +02:00
&& ( $obj1 [ 'allow_gid' ] == $obj2 [ 'allow_gid' ])
&& ( $obj1 [ 'deny_cid' ] == $obj2 [ 'deny_cid' ])
2017-04-14 16:59:51 +02:00
&& ( $obj1 [ 'deny_gid' ] == $obj2 [ 'deny_gid' ])) {
2012-05-28 06:01:58 +02:00
return true ;
2017-04-14 16:59:51 +02:00
}
2012-05-28 06:01:58 +02:00
// This is harder. Parse all the permissions and compare the resulting set.
$recipients1 = enumerate_permissions ( $obj1 );
$recipients2 = enumerate_permissions ( $obj2 );
sort ( $recipients1 );
sort ( $recipients2 );
2017-04-14 16:59:51 +02:00
/// @TODO Comparison of arrays, maybe use array_diff_assoc() here?
return ( $recipients1 == $recipients2 );
2012-05-28 06:01:58 +02:00
}
// returns an array of contact-ids that are allowed to see this object
2017-04-14 16:59:51 +02:00
/// @TODO type-hint is array
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2012-05-28 06:01:58 +02:00
function enumerate_permissions ( $obj ) {
$allow_people = expand_acl ( $obj [ 'allow_cid' ]);
2017-12-09 19:45:17 +01:00
$allow_groups = Group :: expand ( expand_acl ( $obj [ 'allow_gid' ]));
2012-05-28 06:01:58 +02:00
$deny_people = expand_acl ( $obj [ 'deny_cid' ]);
2017-12-09 19:45:17 +01:00
$deny_groups = Group :: expand ( expand_acl ( $obj [ 'deny_gid' ]));
2017-04-08 19:30:35 +02:00
$recipients = array_unique ( array_merge ( $allow_people , $allow_groups ));
$deny = array_unique ( array_merge ( $deny_people , $deny_groups ));
$recipients = array_diff ( $recipients , $deny );
2012-05-28 06:01:58 +02:00
return $recipients ;
}
2011-05-01 02:24:37 +02:00
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2011-04-06 02:41:02 +02:00
function item_getfeedtags ( $item ) {
2018-01-15 14:05:12 +01:00
$ret = [];
2011-04-06 02:41:02 +02:00
$matches = false ;
2017-04-08 19:30:35 +02:00
$cnt = preg_match_all ( '|\#\[url\=(.*?)\](.*?)\[\/url\]|' , $item [ 'tag' ], $matches );
2016-10-22 12:14:41 +02:00
if ( $cnt ) {
2017-04-14 16:59:51 +02:00
for ( $x = 0 ; $x < $cnt ; $x ++ ) {
if ( $matches [ 1 ][ $x ]) {
2018-01-15 14:05:12 +01:00
$ret [ $matches [ 2 ][ $x ]] = [ '#' , $matches [ 1 ][ $x ], $matches [ 2 ][ $x ]];
2017-04-14 16:59:51 +02:00
}
2011-04-06 02:41:02 +02:00
}
}
2014-05-12 19:02:03 +02:00
$matches = false ;
2017-04-08 19:30:35 +02:00
$cnt = preg_match_all ( '|\@\[url\=(.*?)\](.*?)\[\/url\]|' , $item [ 'tag' ], $matches );
2016-10-22 12:14:41 +02:00
if ( $cnt ) {
2017-04-14 16:59:51 +02:00
for ( $x = 0 ; $x < $cnt ; $x ++ ) {
if ( $matches [ 1 ][ $x ]) {
2018-01-15 14:05:12 +01:00
$ret [] = [ '@' , $matches [ 1 ][ $x ], $matches [ 2 ][ $x ]];
2017-04-14 16:59:51 +02:00
}
2011-04-06 02:41:02 +02:00
}
2014-05-12 19:02:03 +02:00
}
2011-04-06 02:41:02 +02:00
return $ret ;
}
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2014-06-02 23:41:33 +02:00
function item_expire ( $uid , $days , $network = " " , $force = false ) {
2011-03-16 01:31:49 +01:00
2018-01-18 00:22:01 +01:00
if ( ! $uid || ( $days < 1 )) {
2011-03-16 01:31:49 +01:00
return ;
2017-04-14 16:59:51 +02:00
}
2011-03-16 01:31:49 +01:00
2017-04-14 16:59:51 +02:00
/*
* $expire_network_only = save your own wall posts
* and just expire conversations started by others
*/
2017-11-07 03:22:52 +01:00
$expire_network_only = PConfig :: get ( $uid , 'expire' , 'network_only' );
2018-01-18 00:22:01 +01:00
$sql_extra = ( intval ( $expire_network_only ) ? " AND wall = 0 " : " " );
2012-05-29 08:24:10 +02:00
2014-06-02 23:41:33 +02:00
if ( $network != " " ) {
$sql_extra .= sprintf ( " AND network = '%s' " , dbesc ( $network ));
2017-04-14 16:59:51 +02:00
/*
* There is an index " uid_network_received " but not " uid_network_created "
* This avoids the creation of another index just for one purpose .
* And it doesn ' t really matter wether to look at " received " or " created "
*/
2014-06-02 23:41:33 +02:00
$range = " AND `received` < UTC_TIMESTAMP() - INTERVAL %d DAY " ;
2017-04-14 16:59:51 +02:00
} else {
2014-06-02 23:41:33 +02:00
$range = " AND `created` < UTC_TIMESTAMP() - INTERVAL %d DAY " ;
2017-04-14 16:59:51 +02:00
}
2014-06-02 23:41:33 +02:00
2016-08-03 15:59:25 +02:00
$r = q ( " SELECT `file`, `resource-id`, `starred`, `type`, `id` FROM `item`
2014-06-02 23:41:33 +02:00
WHERE `uid` = % d $range
2014-05-12 19:02:03 +02:00
AND `id` = `parent`
2012-05-29 08:24:10 +02:00
$sql_extra
2011-03-16 01:31:49 +01:00
AND `deleted` = 0 " ,
intval ( $uid ),
intval ( $days )
);
2018-01-18 00:22:01 +01:00
if ( ! DBM :: is_result ( $r )) {
2011-03-16 01:31:49 +01:00
return ;
2017-04-14 16:59:51 +02:00
}
2011-11-17 15:53:59 +01:00
2017-11-07 23:15:59 +01:00
$expire_items = PConfig :: get ( $uid , 'expire' , 'items' , 1 );
2013-01-11 01:20:16 +01:00
2014-06-02 23:41:33 +02:00
// Forcing expiring of items - but not notes and marked items
2017-04-14 16:59:51 +02:00
if ( $force ) {
2014-06-02 23:41:33 +02:00
$expire_items = true ;
2017-04-14 16:59:51 +02:00
}
2014-06-02 23:41:33 +02:00
2017-11-07 23:15:59 +01:00
$expire_notes = PConfig :: get ( $uid , 'expire' , 'notes' , 1 );
$expire_starred = PConfig :: get ( $uid , 'expire' , 'starred' , 1 );
$expire_photos = PConfig :: get ( $uid , 'expire' , 'photos' , 0 );
2013-01-11 01:20:16 +01:00
2017-07-04 07:31:42 +02:00
logger ( 'User ' . $uid . ': expire: # items=' . count ( $r ) . " ; expire items: $expire_items , expire notes: $expire_notes , expire starred: $expire_starred , expire photos: $expire_photos " );
2011-03-16 01:31:49 +01:00
2017-04-14 16:59:51 +02:00
foreach ( $r as $item ) {
2011-03-16 01:31:49 +01:00
2012-03-27 09:54:34 +02:00
// don't expire filed items
2017-04-14 16:59:51 +02:00
if ( strpos ( $item [ 'file' ], '[' ) !== false ) {
2012-03-27 09:54:34 +02:00
continue ;
2017-04-14 16:59:51 +02:00
}
2012-03-27 09:54:34 +02:00
2011-03-16 01:31:49 +01:00
// Only expire posts, not photos and photo comments
2017-04-14 16:59:51 +02:00
if ( $expire_photos == 0 && strlen ( $item [ 'resource-id' ])) {
2011-11-17 15:53:59 +01:00
continue ;
2017-04-14 16:59:51 +02:00
} elseif ( $expire_starred == 0 && intval ( $item [ 'starred' ])) {
2011-11-22 04:01:05 +01:00
continue ;
2017-04-14 16:59:51 +02:00
} elseif ( $expire_notes == 0 && $item [ 'type' ] == 'note' ) {
2011-03-16 01:31:49 +01:00
continue ;
2017-04-14 16:59:51 +02:00
} elseif ( $expire_items == 0 && $item [ 'type' ] != 'note' ) {
2011-11-17 15:53:59 +01:00
continue ;
2017-04-14 16:59:51 +02:00
}
2011-11-17 15:53:59 +01:00
2018-01-18 00:22:01 +01:00
Item :: delete ( $item [ 'id' ], PRIORITY_LOW );
2011-03-16 01:31:49 +01:00
}
2011-06-11 05:39:46 +02:00
}
2017-04-14 16:59:51 +02:00
/// @TODO type-hint is array
2018-01-21 00:52:54 +01:00
/// @TODO move to ...
2011-06-16 05:43:39 +02:00
function drop_items ( $items ) {
$uid = 0 ;
2018-01-18 00:22:01 +01:00
if ( ! local_user () && ! remote_user ()) {
2012-01-25 03:59:55 +01:00
return ;
2017-04-14 16:59:51 +02:00
}
2012-01-25 03:59:55 +01:00
2016-10-22 12:14:41 +02:00
if ( count ( $items )) {
2017-04-14 16:59:51 +02:00
foreach ( $items as $item ) {
2018-01-18 00:22:01 +01:00
$owner = Item :: delete ( $item );
2016-10-22 12:14:41 +02:00
if ( $owner && ! $uid )
2011-06-16 05:43:39 +02:00
$uid = $owner ;
}
}
}
2018-01-21 00:52:54 +01:00
/// @TODO move to ...
2018-01-18 00:22:01 +01:00
function drop_item ( $id ) {
2011-06-16 05:43:39 +02:00
$a = get_app ();
// locate item to be deleted
$r = q ( " SELECT * FROM `item` WHERE `id` = %d LIMIT 1 " ,
intval ( $id )
);
2018-01-18 00:22:01 +01:00
if ( ! DBM :: is_result ( $r )) {
2018-01-21 19:33:59 +01:00
notice ( L10n :: t ( 'Item not found.' ) . EOL );
2017-08-26 09:32:10 +02:00
goaway ( System :: baseUrl () . '/' . $_SESSION [ 'return_url' ]);
2011-06-16 05:43:39 +02:00
}
$item = $r [ 0 ];
2017-06-21 05:49:05 +02:00
if ( $item [ 'deleted' ]) {
return 0 ;
}
2016-11-14 18:49:51 +01:00
$contact_id = 0 ;
2012-09-05 07:50:28 +02:00
2011-06-16 05:43:39 +02:00
// check if logged in user is either the author or owner of this item
2016-10-22 12:14:41 +02:00
if ( is_array ( $_SESSION [ 'remote' ])) {
2017-04-14 16:59:51 +02:00
foreach ( $_SESSION [ 'remote' ] as $visitor ) {
2016-10-22 12:14:41 +02:00
if ( $visitor [ 'uid' ] == $item [ 'uid' ] && $visitor [ 'cid' ] == $item [ 'contact-id' ]) {
2016-11-14 18:49:51 +01:00
$contact_id = $visitor [ 'cid' ];
2012-09-05 07:50:28 +02:00
break ;
}
}
}
2018-01-18 00:22:01 +01:00
if (( local_user () == $item [ 'uid' ]) || $contact_id ) {
2011-06-16 05:43:39 +02:00
2013-01-26 20:52:21 +01:00
// Check if we should do HTML-based delete confirmation
2016-10-22 12:14:41 +02:00
if ( $_REQUEST [ 'confirm' ]) {
2013-01-26 20:52:21 +01:00
// <form> can't take arguments in its "action" parameter
// so add any arguments as hidden inputs
$query = explode_querystring ( $a -> query_string );
2018-01-15 14:05:12 +01:00
$inputs = [];
2017-04-14 16:59:51 +02:00
foreach ( $query [ 'args' ] as $arg ) {
2016-10-22 12:14:41 +02:00
if ( strpos ( $arg , 'confirm=' ) === false ) {
2013-01-26 20:52:21 +01:00
$arg_parts = explode ( '=' , $arg );
2018-01-15 14:05:12 +01:00
$inputs [] = [ 'name' => $arg_parts [ 0 ], 'value' => $arg_parts [ 1 ]];
2013-01-26 20:52:21 +01:00
}
}
2018-01-15 14:05:12 +01:00
return replace_macros ( get_markup_template ( 'confirm.tpl' ), [
2013-01-26 20:52:21 +01:00
'$method' => 'get' ,
2018-01-21 19:33:59 +01:00
'$message' => L10n :: t ( 'Do you really want to delete this item?' ),
2013-01-26 20:52:21 +01:00
'$extra_inputs' => $inputs ,
2018-01-21 19:33:59 +01:00
'$confirm' => L10n :: t ( 'Yes' ),
2013-01-26 20:52:21 +01:00
'$confirm_url' => $query [ 'base' ],
'$confirm_name' => 'confirmed' ,
2018-01-21 19:33:59 +01:00
'$cancel' => L10n :: t ( 'Cancel' ),
2018-01-15 14:05:12 +01:00
]);
2013-01-26 20:52:21 +01:00
}
// Now check how the user responded to the confirmation query
2016-10-22 12:14:41 +02:00
if ( $_REQUEST [ 'canceled' ]) {
2017-08-26 09:32:10 +02:00
goaway ( System :: baseUrl () . '/' . $_SESSION [ 'return_url' ]);
2013-01-26 20:52:21 +01:00
}
2011-06-16 05:43:39 +02:00
// delete the item
2018-01-18 00:22:01 +01:00
Item :: delete ( $item [ 'id' ]);
2011-06-16 05:43:39 +02:00
2017-08-26 09:32:10 +02:00
goaway ( System :: baseUrl () . '/' . $_SESSION [ 'return_url' ]);
2011-06-16 05:43:39 +02:00
//NOTREACHED
2016-10-22 12:14:41 +02:00
} else {
2018-01-21 19:33:59 +01:00
notice ( L10n :: t ( 'Permission denied.' ) . EOL );
2017-08-26 09:32:10 +02:00
goaway ( System :: baseUrl () . '/' . $_SESSION [ 'return_url' ]);
2011-06-16 05:43:39 +02:00
//NOTREACHED
}
2011-10-23 09:24:37 +02:00
}
2012-06-13 05:46:30 +02:00
2018-01-21 00:52:54 +01:00
/// @TODO: This query seems to be really slow
/// @TODO move to src/Model/Item.php
2017-04-08 19:30:35 +02:00
function first_post_date ( $uid , $wall = false ) {
$r = q ( " SELECT `id`, `created` FROM `item`
WHERE `uid` = % d AND `wall` = % d AND `deleted` = 0 AND `visible` = 1 AND `moderated` = 0
AND `id` = `parent`
ORDER BY `created` ASC LIMIT 1 " ,
2012-06-13 05:46:30 +02:00
intval ( $uid ),
intval ( $wall ? 1 : 0 )
);
2017-11-08 04:57:46 +01:00
if ( DBM :: is_result ( $r )) {
2017-04-14 16:59:51 +02:00
// logger('first_post_date: ' . $r[0]['id'] . ' ' . $r[0]['created'], LOGGER_DATA);
2017-04-08 19:30:35 +02:00
return substr ( datetime_convert ( '' , date_default_timezone_get (), $r [ 0 ][ 'created' ]), 0 , 10 );
2012-06-13 06:34:28 +02:00
}
2012-06-13 05:46:30 +02:00
return false ;
}
2018-01-21 00:52:54 +01:00
/* arrange the list in years */
/// @TODO move to src/Model/Item.php
2015-05-19 01:03:08 +02:00
function list_post_dates ( $uid , $wall ) {
2017-04-14 16:59:51 +02:00
$dnow = datetime_convert ( '' , date_default_timezone_get (), 'now' , 'Y-m-d' );
2015-06-02 18:59:46 +02:00
$dthen = first_post_date ( $uid , $wall );
2017-04-08 19:30:35 +02:00
if ( ! $dthen ) {
2018-01-15 14:05:12 +01:00
return [];
2017-04-08 19:30:35 +02:00
}
2015-06-02 18:59:46 +02:00
2015-05-19 01:03:08 +02:00
// Set the start and end date to the beginning of the month
2017-04-14 16:59:51 +02:00
$dnow = substr ( $dnow , 0 , 8 ) . '01' ;
$dthen = substr ( $dthen , 0 , 8 ) . '01' ;
2015-06-02 18:59:46 +02:00
2018-01-15 14:05:12 +01:00
$ret = [];
2015-06-02 18:59:46 +02:00
2017-04-08 19:30:35 +02:00
/*
* Starting with the current month , get the first and last days of every
* month down to and including the month of the first post
*/
while ( substr ( $dnow , 0 , 7 ) >= substr ( $dthen , 0 , 7 )) {
2017-04-14 16:59:51 +02:00
$dyear = intval ( substr ( $dnow , 0 , 4 ));
$dstart = substr ( $dnow , 0 , 8 ) . '01' ;
$dend = substr ( $dnow , 0 , 8 ) . get_dim ( intval ( $dnow ), intval ( substr ( $dnow , 5 )));
$start_month = datetime_convert ( '' , '' , $dstart , 'Y-m-d' );
$end_month = datetime_convert ( '' , '' , $dend , 'Y-m-d' );
$str = day_translate ( datetime_convert ( '' , '' , $dnow , 'F' ));
2017-04-08 19:30:35 +02:00
if ( ! $ret [ $dyear ]) {
2018-01-15 14:05:12 +01:00
$ret [ $dyear ] = [];
2017-04-08 19:30:35 +02:00
}
2018-01-15 14:05:12 +01:00
$ret [ $dyear ][] = [ $str , $end_month , $start_month ];
2017-04-08 19:30:35 +02:00
$dnow = datetime_convert ( '' , '' , $dnow . ' -1 month' , 'Y-m-d' );
2015-05-19 01:03:08 +02:00
}
return $ret ;
}
2018-01-21 00:52:54 +01:00
/// @TODO move to src/Model/Item.php
2017-04-08 19:30:35 +02:00
function posted_date_widget ( $url , $uid , $wall ) {
2012-06-13 05:46:30 +02:00
$o = '' ;
2012-06-14 01:17:45 +02:00
2017-12-04 15:01:27 +01:00
if ( ! Feature :: isEnabled ( $uid , 'archives' )) {
2012-11-22 17:14:22 +01:00
return $o ;
2017-04-08 19:30:35 +02:00
}
2012-11-22 17:14:22 +01:00
2012-06-14 01:17:45 +02:00
// For former Facebook folks that left because of "timeline"
2017-04-14 16:59:51 +02:00
/*
* @ TODO old - lost code ?
2017-11-07 03:22:52 +01:00
if ( $wall && intval ( PConfig :: get ( $uid , 'system' , 'no_wall_archive_widget' )))
2017-04-14 16:59:51 +02:00
return $o ;
*/
2015-06-02 18:59:46 +02:00
2017-11-07 03:22:52 +01:00
$visible_years = PConfig :: get ( $uid , 'system' , 'archive_visible_years' );
2017-04-08 19:30:35 +02:00
if ( ! $visible_years ) {
2015-06-02 18:59:46 +02:00
$visible_years = 5 ;
2017-04-08 19:30:35 +02:00
}
2015-06-02 18:59:46 +02:00
2017-04-08 19:30:35 +02:00
$ret = list_post_dates ( $uid , $wall );
2015-06-02 18:59:46 +02:00
2017-11-08 04:57:46 +01:00
if ( ! DBM :: is_result ( $ret )) {
2012-06-13 05:46:30 +02:00
return $o ;
2017-04-08 19:30:35 +02:00
}
2012-06-13 05:46:30 +02:00
2017-04-14 16:59:51 +02:00
$cutoff_year = intval ( datetime_convert ( '' , date_default_timezone_get (), 'now' , 'Y' )) - $visible_years ;
2017-04-08 19:30:35 +02:00
$cutoff = (( array_key_exists ( $cutoff_year , $ret )) ? true : false );
2015-06-02 18:59:46 +02:00
2018-01-15 14:05:12 +01:00
$o = replace_macros ( get_markup_template ( 'posted_date_widget.tpl' ),[
2018-01-21 19:33:59 +01:00
'$title' => L10n :: t ( 'Archives' ),
2015-05-19 01:03:08 +02:00
'$size' => $visible_years ,
'$cutoff_year' => $cutoff_year ,
'$cutoff' => $cutoff ,
2012-06-13 05:46:30 +02:00
'$url' => $url ,
2015-05-19 01:03:08 +02:00
'$dates' => $ret ,
2018-01-21 19:33:59 +01:00
'$showmore' => L10n :: t ( 'show more' )
2015-05-19 01:03:08 +02:00
2018-01-15 14:05:12 +01:00
]);
2012-06-13 05:46:30 +02:00
return $o ;
2012-06-29 21:40:54 +02:00
}