X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=classes%2FNotice.php;h=44a6aeb986914b4ab6c6c8ccc8987d2a67443329;hb=14afe2d26874ed30a0ccef5e0acda2c5171afcde;hp=cc7de63c206951df8a490927821778f366c80f52;hpb=ed964ea980be63999860aaa5f39274768eca5d59;p=quix0rs-gnu-social.git diff --git a/classes/Notice.php b/classes/Notice.php index cc7de63c20..44a6aeb986 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -34,22 +34,23 @@ class Notice extends Memcached_DataObject ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ - public $__table = 'notice'; // table name - public $id; // int(4) primary_key not_null - public $profile_id; // int(4) not_null + public $__table = 'notice'; // table name + public $id; // int(4) primary_key not_null + public $profile_id; // int(4) not_null public $uri; // varchar(255) unique_key public $content; // varchar(140) - public $rendered; // text() + public $rendered; // text() public $url; // varchar(255) - public $created; // datetime() not_null - public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP - public $reply_to; // int(4) - public $is_local; // tinyint(1) - public $source; // varchar(32) + public $created; // datetime() not_null + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP + public $reply_to; // int(4) + public $is_local; // tinyint(1) + public $source; // varchar(32) /* Static get */ - function staticGet($k,$v=null) - { return Memcached_DataObject::staticGet('Notice',$k,$v); } + function staticGet($k,$v=NULL) { + return Memcached_DataObject::staticGet('Notice',$k,$v); + } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE @@ -94,27 +95,34 @@ class Notice extends Memcached_DataObject /* Add them to the database */ foreach(array_unique($match[1]) as $hashtag) { /* elide characters we don't want in the tag */ - $hashtag = common_canonical_tag($hashtag); - - $tag = DB_DataObject::factory('Notice_tag'); - $tag->notice_id = $this->id; - $tag->tag = $hashtag; - $tag->created = $this->created; - $id = $tag->insert(); - if (!$id) { - $last_error = PEAR::getStaticProperty('DB_DataObject','lastError'); - common_log(LOG_ERR, 'DB error inserting hashtag: ' . $last_error->message); - common_server_error(sprintf(_('DB error inserting hashtag: %s'), $last_error->message)); - return; - } + $this->saveTag($hashtag); } return true; } + function saveTag($hashtag) + { + $hashtag = common_canonical_tag($hashtag); + + $tag = new Notice_tag(); + $tag->notice_id = $this->id; + $tag->tag = $hashtag; + $tag->created = $this->created; + $id = $tag->insert(); + + if (!$id) { + throw new ServerException(sprintf(_('DB error inserting hashtag: %s'), + $last_error->message)); + return; + } + } + static function saveNew($profile_id, $content, $source=null, $is_local=1, $reply_to=null, $uri=null) { $profile = Profile::staticGet($profile_id); + $final = common_shorten_links($content); + if (!$profile) { common_log(LOG_ERR, 'Problem saving notice. Unknown user.'); return _('Problem saving notice. Unknown user.'); @@ -125,7 +133,12 @@ class Notice extends Memcached_DataObject return _('Too many notices too fast; take a breather and post again in a few minutes.'); } - $banned = common_config('profile', 'banned'); + if (common_config('site', 'dupelimit') > 0 && !Notice::checkDupes($profile_id, $final)) { + common_log(LOG_WARNING, 'Dupe posting by profile #' . $profile_id . '; throttled.'); + return _('Too many duplicate messages too quickly; take a breather and post again in a few minutes.'); + } + + $banned = common_config('profile', 'banned'); if ( in_array($profile_id, $banned) || in_array($profile->nickname, $banned)) { common_log(LOG_WARNING, "Attempted post from banned user: $profile->nickname (user id = $profile_id)."); @@ -149,39 +162,44 @@ class Notice extends Memcached_DataObject $notice->query('BEGIN'); - $notice->reply_to = $reply_to; - $notice->created = common_sql_now(); - $notice->content = common_shorten_links($content); - $notice->rendered = common_render_content($notice->content, $notice); - $notice->source = $source; - $notice->uri = $uri; - - $id = $notice->insert(); + $notice->reply_to = $reply_to; + $notice->created = common_sql_now(); + $notice->content = $final; + $notice->rendered = common_render_content($final, $notice); + $notice->source = $source; + $notice->uri = $uri; - if (!$id) { - common_log_db_error($notice, 'INSERT', __FILE__); - return _('Problem saving notice.'); - } + if (Event::handle('StartNoticeSave', array(&$notice))) { - # Update the URI after the notice is in the database - if (!$uri) { - $orig = clone($notice); - $notice->uri = common_notice_uri($notice); + $id = $notice->insert(); - if (!$notice->update($orig)) { - common_log_db_error($notice, 'UPDATE', __FILE__); + if (!$id) { + common_log_db_error($notice, 'INSERT', __FILE__); return _('Problem saving notice.'); } - } - # XXX: do we need to change this for remote users? + # Update the URI after the notice is in the database + if (!$uri) { + $orig = clone($notice); + $notice->uri = common_notice_uri($notice); + + if (!$notice->update($orig)) { + common_log_db_error($notice, 'UPDATE', __FILE__); + return _('Problem saving notice.'); + } + } + + # XXX: do we need to change this for remote users? + + $notice->saveReplies(); + $notice->saveTags(); + $notice->saveGroups(); - $notice->saveReplies(); - $notice->saveTags(); - $notice->saveGroups(); + $notice->addToInboxes(); + $notice->query('COMMIT'); - $notice->addToInboxes(); - $notice->query('COMMIT'); + Event::handle('EndNoticeSave', array($notice)); + } # Clear the cache for subscribed users, so they'll update at next request # XXX: someone clever could prepend instead of clearing the cache @@ -193,6 +211,36 @@ class Notice extends Memcached_DataObject return $notice; } + static function checkDupes($profile_id, $content) { + $profile = Profile::staticGet($profile_id); + if (!$profile) { + return false; + } + $notice = $profile->getNotices(0, NOTICE_CACHE_WINDOW); + if ($notice) { + $last = 0; + while ($notice->fetch()) { + if (time() - strtotime($notice->created) >= common_config('site', 'dupelimit')) { + return true; + } else if ($notice->content == $content) { + return false; + } + } + } + # If we get here, oldest item in cache window is not + # old enough for dupe limit; do direct check against DB + $notice = new Notice(); + $notice->profile_id = $profile_id; + $notice->content = $content; + if (common_config('db','type') == 'pgsql') + $notice->whereAdd('extract(epoch from now() - created) < ' . common_config('site', 'dupelimit')); + else + $notice->whereAdd('now() - created < ' . common_config('site', 'dupelimit')); + + $cnt = $notice->count(); + return ($cnt == 0); + } + static function checkEditThrottle($profile_id) { $profile = Profile::staticGet($profile_id); if (!$profile) { @@ -574,7 +622,7 @@ class Notice extends Memcached_DataObject $inbox = new Notice_inbox(); $UT = common_config('db','type')=='pgsql'?'"user"':'user'; $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created) ' . - "SELECT $UT.id, " . $this->id . ', "' . $this->created . '" ' . + "SELECT $UT.id, " . $this->id . ", '" . $this->created . "' " . "FROM $UT JOIN subscription ON $UT.id = subscription.subscriber " . 'WHERE subscription.subscribed = ' . $this->profile_id . ' ' . 'AND NOT EXISTS (SELECT user_id, notice_id ' . @@ -616,6 +664,15 @@ class Notice extends Memcached_DataObject continue; } + // we automatically add a tag for every group name, too + + $tag = Notice_tag::pkeyGet(array('tag' => common_canonical_tag($nickname), + 'notice_id' => $this->id)); + + if (is_null($tag)) { + $this->saveTag($nickname); + } + if ($profile->isMember($group)) { $gi = new Group_inbox(); @@ -635,7 +692,7 @@ class Notice extends Memcached_DataObject $inbox = new Notice_inbox(); $UT = common_config('db','type')=='pgsql'?'"user"':'user'; $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' . - "SELECT $UT.id, " . $this->id . ', "' . $this->created . '", 2 ' . + "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', 2 " . "FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " . 'WHERE group_member.group_id = ' . $group->id . ' ' . 'AND NOT EXISTS (SELECT user_id, notice_id ' . @@ -727,10 +784,113 @@ class Notice extends Memcached_DataObject if (!$id) { common_log_db_error($reply, 'INSERT', __FILE__); return; + } else { + $replied[$recipient->id] = 1; } } } } } + + foreach (array_keys($replied) as $recipient) { + $user = User::staticGet('id', $recipient); + if ($user) { + mail_notify_attn($user, $this); + } + } + } + + function asAtomEntry($namespace=false, $source=false) + { + $profile = $this->getProfile(); + + $xs = new XMLStringer(true); + + if ($namespace) { + $attrs = array('xmlns' => 'http://www.w3.org/2005/Atom', + 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0'); + } else { + $attrs = array(); + } + + $xs->elementStart('entry', $attrs); + + if ($source) { + $xs->elementStart('source'); + $xs->element('title', null, $profile->nickname . " - " . common_config('site', 'name')); + $xs->element('link', array('href' => $profile->profileurl)); + $user = User::staticGet('id', $profile->id); + if (!empty($user)) { + $atom_feed = common_local_url('api', + array('apiaction' => 'statuses', + 'method' => 'user_timeline', + 'argument' => $profile->nickname.'.atom')); + $xs->element('link', array('rel' => 'self', + 'type' => 'application/atom+xml', + 'href' => $profile->profileurl)); + $xs->element('link', array('rel' => 'license', + 'href' => common_config('license', 'url'))); + } + + $xs->element('icon', null, $profile->avatarUrl(AVATAR_PROFILE_SIZE)); + } + + $xs->elementStart('author'); + $xs->element('name', null, $profile->nickname); + $xs->element('uri', null, $profile->profileurl); + $xs->elementEnd('author'); + + if ($source) { + $xs->elementEnd('source'); + } + + $xs->element('title', null, $this->content); + $xs->element('summary', null, $this->content); + + $xs->element('link', array('rel' => 'alternate', + 'href' => $this->bestUrl())); + + $xs->element('id', null, $this->uri); + + $xs->element('published', null, common_date_w3dtf($this->created)); + $xs->element('updated', null, common_date_w3dtf($this->modified)); + + if ($this->reply_to) { + $reply_notice = Notice::staticGet('id', $this->reply_to); + if (!empty($reply_notice)) { + $xs->element('link', array('rel' => 'related', + 'href' => $reply_notice->bestUrl())); + $xs->element('thr:in-reply-to', + array('ref' => $reply_notice->uri, + 'href' => $reply_notice->bestUrl())); + } + } + + $xs->element('content', array('type' => 'html'), $this->rendered); + + $tag = new Notice_tag(); + $tag->notice_id = $this->id; + if ($tag->find()) { + while ($tag->fetch()) { + $xs->element('category', array('term' => $tag->tag)); + } + } + $tag->free(); + + $xs->elementEnd('entry'); + + return $xs->getString(); + } + + function bestUrl() + { + if (!empty($this->url)) { + return $this->url; + } else if (!empty($this->uri) && preg_match('/^https?:/', $this->uri)) { + return $this->uri; + } else { + return common_local_url('shownotice', + array('notice' => $this->id)); + } } }