]> git.mxchange.org Git - friendica.git/blobdiff - include/items.php
Merge remote-tracking branch 'upstream/develop' into 1504-unified-follow
[friendica.git] / include / items.php
index d6ca2008544bcb1f4eabacf4689f304363ece821..3832b80b318f30f51a0f8b716d87c752f65ac855 100644 (file)
@@ -12,6 +12,7 @@ require_once('include/email.php');
 require_once('include/ostatus_conversation.php');
 require_once('include/threads.php');
 require_once('include/socgraph.php');
+require_once('mod/share.php');
 
 function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) {
 
@@ -838,10 +839,7 @@ function get_atom_elements($feed, $item, $contact = array()) {
                        logger('get_atom_elements: fixing sender of repeated message.');
 
                        if (!intval(get_config('system','wall-to-wall_share'))) {
-                               $prefix = "[share author='".str_replace("'", "'",$name).
-                                               "' profile='".$uri.
-                                               "' avatar='".$avatar.
-                                               "' link='".$orig_uri."']";
+                               $prefix = share_header($name, $uri, $avatar, "", "", $orig_uri);
 
                                $res["body"] = $prefix.html2bbcode($message)."[/share]";
                        } else {
@@ -1183,9 +1181,9 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
        $arr['owner-avatar']  = ((x($arr,'owner-avatar'))  ? notags(trim($arr['owner-avatar']))  : '');
        $arr['created']       = ((x($arr,'created') !== false) ? datetime_convert('UTC','UTC',$arr['created']) : datetime_convert());
        $arr['edited']        = ((x($arr,'edited')  !== false) ? datetime_convert('UTC','UTC',$arr['edited'])  : datetime_convert());
-       $arr['commented']     = datetime_convert();
-       $arr['received']      = datetime_convert();
-       $arr['changed']       = datetime_convert();
+       $arr['commented']     = ((x($arr,'commented')  !== false) ? datetime_convert('UTC','UTC',$arr['commented'])  : datetime_convert());
+       $arr['received']      = ((x($arr,'received')  !== false) ? datetime_convert('UTC','UTC',$arr['received'])  : datetime_convert());
+       $arr['changed']       = ((x($arr,'changed')  !== false) ? datetime_convert('UTC','UTC',$arr['changed'])  : datetime_convert());
        $arr['title']         = ((x($arr,'title'))         ? notags(trim($arr['title']))         : '');
        $arr['location']      = ((x($arr,'location'))      ? notags(trim($arr['location']))      : '');
        $arr['coord']         = ((x($arr,'coord'))         ? notags(trim($arr['coord']))         : '');
@@ -1210,8 +1208,8 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
        $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['guid']          = ((x($arr,'guid'))          ? notags(trim($arr['guid']))          : get_guid(30));
        $arr['network']       = ((x($arr,'network'))       ? trim($arr['network'])               : '');
+       $arr['guid']          = ((x($arr,'guid'))          ? notags(trim($arr['guid']))          : get_guid(32, $arr['network']));
        $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 );
@@ -1239,6 +1237,9 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
                logger("item_store: Set network to ".$arr["network"]." for ".$arr["uri"], LOGGER_DEBUG);
        }
 
+       // Check for hashtags in the body and repair or add hashtag links
+       item_body_set_hashtags($arr);
+
        $arr['thr-parent'] = $arr['parent-uri'];
        if($arr['parent-uri'] === $arr['uri']) {
                $parent_id = 0;
@@ -1343,6 +1344,20 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
                return 0;
        }
 
+       // Is this item available in the global items (with uid=0)?
+       if ($arr["uid"] == 0) {
+               $arr["global"] = true;
+
+               q("UPDATE `item` SET `global` = 1 WHERE `guid` = '%s'", dbesc($arr["guid"]));
+       }  else {
+               $isglobal = q("SELECT `global` FROM `item` WHERE `uid` = 0 AND `guid` = '%s'", dbesc($arr["guid"]));
+
+               $arr["global"] = (count($isglobal) > 0);
+       }
+
+       // Fill the cache field
+       put_item_in_cache($arr);
+
        call_hooks('post_remote',$arr);
 
        if(x($arr,'cancel')) {
@@ -1376,16 +1391,6 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
                $current_post = $r[0]['id'];
                logger('item_store: created item ' . $current_post);
 
-               // Add every contact to the global contact table
-               // Contacts from the statusnet connector are also added since you could add them in OStatus as well.
-               if (!$arr['private'] AND in_array($arr["network"],
-                       array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, NETWORK_STATUSNET, ""))) {
-                       poco_check($arr["author-link"], $arr["author-name"], $arr["network"], $arr["author-avatar"], "", "", "", "", "", $arr["received"], $arr["contact-id"], $arr["uid"]);
-
-                       // Maybe its a body with a shared item? Then extract a global contact from it.
-                       poco_contact_from_body($arr["body"], $arr["received"], $arr["contact-id"], $arr["uid"]);
-               }
-
                // Set "success_update" to the date of the last time we heard from this contact
                // This can be used to filter for inactive contacts and poco.
                // Only do this for public postings to avoid privacy problems, since poco data is public.
@@ -1444,12 +1449,18 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
        $arr['deleted'] = $parent_deleted;
 
        // update the commented timestamp on the parent
-
-       q("UPDATE `item` set `commented` = '%s', `changed` = '%s' WHERE `id` = %d",
-               dbesc(datetime_convert()),
-               dbesc(datetime_convert()),
-               intval($parent_id)
-       );
+       // Only update "commented" if it is really a comment
+       if (($arr['verb'] == ACTIVITY_POST) OR !get_config("system", "like_no_comment"))
+               q("UPDATE `item` SET `commented` = '%s', `changed` = '%s' WHERE `id` = %d",
+                       dbesc(datetime_convert()),
+                       dbesc(datetime_convert()),
+                       intval($parent_id)
+               );
+       else
+               q("UPDATE `item` SET `changed` = '%s' WHERE `id` = %d",
+                       dbesc(datetime_convert()),
+                       intval($parent_id)
+               );
 
        if($dsprsig) {
                q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
@@ -1475,21 +1486,20 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
 
        $deleted = tag_deliver($arr['uid'],$current_post);
 
-       // current post can be deleted if is for a communuty page and no mention are
+       // current post can be deleted if is for a community page and no mention are
        // in it.
        if (!$deleted AND !$dontcache) {
 
-               // Store the fresh generated item into the cache
-               put_item_in_cache($arr);
-
                $r = q('SELECT * FROM `item` WHERE id = %d', intval($current_post));
                if (count($r) == 1) {
                        call_hooks('post_remote_end', $r[0]);
-               } else {
+               } else
                        logger('item_store: new item not found in DB, id ' . $current_post);
-               }
        }
 
+       // Add every contact of the post to the global contact table
+       poco_store($arr);
+
        create_tags_from_item($current_post);
        create_files_from_item($current_post);
 
@@ -1549,8 +1559,10 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
                        ));
                        logger('item_store: Notification sent for contact '.$arr['contact-id'].' and post '.$current_post, LOGGER_DEBUG);
                }
-       } else
+       } else {
                update_thread($parent_id);
+               add_shadow_entry($arr);
+       }
 
        if ($notify)
                proc_run('php', "include/notifier.php", $notify_type, $current_post);
@@ -1558,6 +1570,73 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
        return $current_post;
 }
 
+function item_body_set_hashtags(&$item) {
+
+       $tags = get_tags($item["body"]);
+
+       // No hashtags?
+       if(!count($tags))
+               return(false);
+
+       // 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);
+
+       $a = get_app();
+
+       $URLSearchString = "^\[\]";
+
+       // All hashtags should point to the home server
+       //$item["body"] = preg_replace("/#\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
+       //              "#[url=".$a->get_baseurl()."/search?tag=$2]$2[/url]", $item["body"]);
+
+       //$item["tag"] = preg_replace("/#\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
+       //              "#[url=".$a->get_baseurl()."/search?tag=$2]$2[/url]", $item["tag"]);
+
+       // mask hashtags inside of url, bookmarks and attachments to avoid urls in urls
+       $item["body"] = preg_replace_callback("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
+               function ($match){
+                       return("[url=".$match[1]."]".str_replace("#", "#", $match[2])."[/url]");
+               },$item["body"]);
+
+       $item["body"] = preg_replace_callback("/\[bookmark\=([$URLSearchString]*)\](.*?)\[\/bookmark\]/ism",
+               function ($match){
+                       return("[bookmark=".$match[1]."]".str_replace("#", "#", $match[2])."[/bookmark]");
+               },$item["body"]);
+
+       $item["body"] = preg_replace_callback("/\[attachment (.*)\](.*?)\[\/attachment\]/ism",
+               function ($match){
+                       return("[attachment ".str_replace("#", "#", $match[1])."]".$match[2]."[/attachment]");
+               },$item["body"]);
+
+       // Repair recursive urls
+       $item["body"] = preg_replace("/#\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
+                       "#$2", $item["body"]);
+
+       foreach($tags as $tag) {
+               if(strpos($tag,'#') !== 0)
+                       continue;
+
+               if(strpos($tag,'[url='))
+                       continue;
+
+               $basetag = str_replace('_',' ',substr($tag,1));
+
+               $newtag = '#[url='.$a->get_baseurl().'/search?tag='.rawurlencode($basetag).']'.$basetag.'[/url]';
+
+               $item["body"] = str_replace($tag, $newtag, $item["body"]);
+
+               if(!stristr($item["tag"],"/search?tag=".$basetag."]".$basetag."[/url]")) {
+                       if(strlen($item["tag"]))
+                               $item["tag"] = ','.$item["tag"];
+                       $item["tag"] = $newtag.$item["tag"];
+               }
+       }
+
+       // Convert back the masked hashtags
+       $item["body"] = str_replace("#", "#", $item["body"]);
+}
+
 function get_item_guid($id) {
        $r = q("SELECT `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($id));
        if (count($r))
@@ -2083,6 +2162,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
        $photo_timestamp = '';
        $photo_url = '';
        $birthday = '';
+       $contact_updated = '';
 
        $hubs = $feed->get_links('hub');
        logger('consume_feed: hubs: ' . print_r($hubs,true), LOGGER_DATA);
@@ -2118,6 +2198,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
 
        if((is_array($contact)) && ($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $contact['avatar-date'])) {
                logger('consume_feed: Updating photo for '.$contact['name'].' from '.$photo_url.' uid: '.$contact['uid']);
+
+               $contact_updated = $photo_timestamp;
+
                require_once("include/Photo.php");
                $photo_failure = false;
                $have_photo = false;
@@ -2175,6 +2258,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
        }
 
        if((is_array($contact)) && ($name_updated) && (strlen($new_name)) && ($name_updated > $contact['name-date'])) {
+               if ($name_updated > $contact_updated)
+                       $contact_updated = $name_updated;
+
                $r = q("select * from contact where uid = %d and id = %d limit 1",
                        intval($contact['uid']),
                        intval($contact['id'])
@@ -2199,6 +2285,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
                }
        }
 
+       if ($contact_updated AND $new_name AND $photo_url)
+               poco_check($contact['url'], $new_name, NETWORK_DFRN, $photo_url, "", "", "", "", "", $contact_updated, 2, $contact['id'], $contact['uid']);
+
        if(strlen($birthday)) {
                if(substr($birthday,0,4) != $contact['bdyear']) {
                        logger('consume_feed: updating birthday: ' . $birthday);
@@ -2245,7 +2334,6 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
 
                        $contact['bdyear'] = substr($birthday,0,4);
                }
-
        }
 
        $community_page = 0;
@@ -2811,6 +2899,7 @@ function local_delivery($importer,$data) {
        $new_name = '';
        $photo_timestamp = '';
        $photo_url = '';
+       $contact_updated = '';
 
 
        $rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'owner');
@@ -2839,6 +2928,9 @@ function local_delivery($importer,$data) {
        }
 
        if(($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $importer['avatar-date'])) {
+
+               $contact_updated = $photo_timestamp;
+
                logger('local_delivery: Updating photo for ' . $importer['name']);
                require_once("include/Photo.php");
                $photo_failure = false;
@@ -2897,6 +2989,9 @@ function local_delivery($importer,$data) {
        }
 
        if(($name_updated) && (strlen($new_name)) && ($name_updated > $importer['name-date'])) {
+               if ($name_updated > $contact_updated)
+                       $contact_updated = $name_updated;
+
                $r = q("select * from contact where uid = %d and id = %d limit 1",
                        intval($importer['importer_uid']),
                        intval($importer['id'])
@@ -2921,7 +3016,8 @@ function local_delivery($importer,$data) {
                }
        }
 
-
+       if ($contact_updated AND $new_name AND $photo_url)
+               poco_check($importer['url'], $new_name, NETWORK_DFRN, $photo_url, "", "", "", "", "", $contact_updated, 2, $importer['id'], $importer['importer_uid']);
 
        // Currently unsupported - needs a lot of work
        $reloc = $feed->get_feed_tags( NAMESPACE_DFRN, 'relocate' );