First cut at hastags support.

darcs-hash:20080720055702-533db-193ed842b0d0a952bef71a3c5287213ada0ef15c.gz
This commit is contained in:
Mike Cochrane 2008-07-20 01:57:02 -04:00
parent e4f1d6f504
commit 5d84485001
9 changed files with 139 additions and 21 deletions

View File

@ -71,7 +71,8 @@ class NewnoticeAction extends Action {
return; return;
} }
common_save_replies($notice); common_save_replies($notice);
$notice->saveTags();
common_broadcast_notice($notice); common_broadcast_notice($notice);
$returnto = $this->trimmed('returnto'); $returnto = $this->trimmed('returnto');

View File

@ -89,7 +89,8 @@ class PostnoticeAction extends Action {
common_server_error(_('Error inserting notice'), 500); common_server_error(_('Error inserting notice'), 500);
return false; return false;
} }
common_save_replies($notice); common_save_replies($notice);
$notice->saveTags();
common_broadcast_notice($notice, true); common_broadcast_notice($notice, true);
} }
return true; return true;

View File

@ -51,4 +51,28 @@ class Notice extends DB_DataObject
function getProfile() { function getProfile() {
return Profile::staticGet($this->profile_id); return Profile::staticGet($this->profile_id);
} }
function saveTags() {
/* extract all #hastags */
$count = preg_match_all('/(?:^|\s)#([a-z0-9]{1,64})/', strtolower($this->content), $match);
if (!$count) {
return true;
}
/* Add them to the database */
foreach(array_unique($match[1]) as $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_ERROR, 'DB error inserting hashtag: ' . $last_error->message);
common_server_error(sprintf(_('DB error inserting hashtag: %s'), $last_error->message));
return;
}
}
return true;
}
} }

22
classes/Notice_tag.php Normal file
View File

@ -0,0 +1,22 @@
<?php
/**
* Table Definition for notice_tag
*/
require_once 'DB/DataObject.php';
class Notice_tag extends DB_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
public $__table = 'notice_tag'; // table name
public $tag; // varchar(64) primary_key not_null
public $notice_id; // int(4) primary_key not_null
public $created; // datetime() not_null
/* Static get */
function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('Notice_tag',$k,$v); }
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
}

View File

@ -123,7 +123,7 @@ create table reply (
profile_id integer not null comment 'profile replied to' references profile (id), profile_id integer not null comment 'profile replied to' references profile (id),
modified timestamp not null comment 'date this record was modified', modified timestamp not null comment 'date this record was modified',
replied_id integer comment 'notice replied to (not used, see notice.reply_to)', replied_id integer comment 'notice replied to (not used, see notice.reply_to)',
constraint primary key (notice_id, profile_id), constraint primary key (notice_id, profile_id),
index reply_notice_id_idx (notice_id), index reply_notice_id_idx (notice_id),
index reply_profile_id_idx (profile_id), index reply_profile_id_idx (profile_id),
@ -226,3 +226,12 @@ create table queue_item (
) ENGINE=MyISAM; ) ENGINE=MyISAM;
/* Hash tags */
create table notice_tag (
tag varchar( 64 ) not null comment 'hash tag associated with this notice',
notice_id integer not null comment 'notice tagged' references notice (id),
created datetime not null comment 'date this record was created',
constraint primary key (tag, notice_id),
index notice_tag_created_idx (created)
) ENGINE=MyISAM;

46
fixup_hashtags.php Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env php
<?php
/*
* Laconica - a distributed open-source microblogging tool
* Copyright (C) 2008, Controlez-Vous, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
# Abort if called from a web server
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
print "This script must be run from the command line\n";
exit();
}
define('INSTALLDIR', dirname(__FILE__));
define('LACONICA', true);
require_once(INSTALLDIR . '/lib/common.php');
common_log(LOG_INFO, 'Starting to do old notices.');
$notice = new Notice();
$cnt = $notice->find();
while ($notice->fetch()) {
common_log(LOG_INFO, 'Getting replies for notice #' . $notice->id);
$notice->saveTags();
$original = clone($notice);
$notice->rendered = common_render_content($notice->content, $notice);
$result = $notice->update($original);
if (!$result) {
common_log_db_error($notice, 'UPDATE', __FILE__);
}
}

View File

@ -115,6 +115,5 @@ require_once(INSTALLDIR.'/classes/Confirm_address.php');
require_once(INSTALLDIR.'/classes/Remember_me.php'); require_once(INSTALLDIR.'/classes/Remember_me.php');
require_once(INSTALLDIR.'/classes/Queue_item.php'); require_once(INSTALLDIR.'/classes/Queue_item.php');
require_once(INSTALLDIR.'/classes/Reply.php'); require_once(INSTALLDIR.'/classes/Reply.php');
require_once(INSTALLDIR.'/classes/Sms_carrier.php');
require_once('markdown.php'); require_once('markdown.php');

View File

@ -275,6 +275,7 @@ function common_nav_menu() {
} }
common_menu_item(common_local_url('public'), _('Public')); common_menu_item(common_local_url('public'), _('Public'));
common_menu_item(common_local_url('peoplesearch'), _('Search')); common_menu_item(common_local_url('peoplesearch'), _('Search'));
common_menu_item(common_local_url('tags'), _('Tags'));
common_menu_item(common_local_url('doc', array('title' => 'help')), common_menu_item(common_local_url('doc', array('title' => 'help')),
_('Help')); _('Help'));
if ($user) { if ($user) {
@ -603,11 +604,15 @@ function common_render_content($text, $notice) {
$r = preg_replace('@https?://[^)\]>\s]+@', '<a href="\0" class="extlink">\0</a>', $r); $r = preg_replace('@https?://[^)\]>\s]+@', '<a href="\0" class="extlink">\0</a>', $r);
$r = preg_replace('/(^|\s+)@([a-z0-9]{1,64})/e', "'\\1@'.common_at_link($id, '\\2')", $r); $r = preg_replace('/(^|\s+)@([a-z0-9]{1,64})/e', "'\\1@'.common_at_link($id, '\\2')", $r);
$r = preg_replace('/^T ([A-Z0-9]{1,64}) /e', "'T '.common_at_link($id, '\\1').' '", $r); $r = preg_replace('/^T ([A-Z0-9]{1,64}) /e', "'T '.common_at_link($id, '\\1').' '", $r);
# XXX: # tags $r = preg_replace('/(^|\s+)#([a-z0-9]{1,64})/e', "'\\1#'.common_tag_link('\\2')", $r);
# XXX: machine tags # XXX: machine tags
return $r; return $r;
} }
function common_tag_link($tag) {
return '<a href="' . htmlspecialchars(common_path('tag/' . $tag)) . '" class="hashlink">' . $tag . '</a>';
}
function common_at_link($sender_id, $nickname) { function common_at_link($sender_id, $nickname) {
$sender = Profile::staticGet($sender_id); $sender = Profile::staticGet($sender_id);
$recipient = common_relative_profile($sender, $nickname); $recipient = common_relative_profile($sender, $nickname);
@ -790,6 +795,16 @@ function common_fancy_url($action, $args=NULL) {
return common_path('search/notice/rss' . (($args) ? ('?' . http_build_query($args)) : '')); return common_path('search/notice/rss' . (($args) ? ('?' . http_build_query($args)) : ''));
case 'avatarbynickname': case 'avatarbynickname':
return common_path($args['nickname'].'/avatar/'.$args['size']); return common_path($args['nickname'].'/avatar/'.$args['size']);
case 'tag':
if (isset($args['tag']) && $args['tag']) {
$path = 'tag/' . $args['tag'];
unset($args['tag']);
} else {
$path = 'tags';
}
return common_path($path . (($args) ? ('?' . http_build_query($args)) : ''));
case 'tags':
return common_path('tags' . (($args) ? ('?' . http_build_query($args)) : ''));
default: default:
return common_simple_url($action, $args); return common_simple_url($action, $args);
} }
@ -859,12 +874,12 @@ function common_date_w3dtf($dt) {
function common_date_rfc2822($dt) { function common_date_rfc2822($dt) {
$t = strtotime($dt); $t = strtotime($dt);
return date("r", $t); return date("r", $t);
} }
function common_date_iso8601($dt) { function common_date_iso8601($dt) {
$t = strtotime($dt); $t = strtotime($dt);
return date("c", $t); return date("c", $t);
} }
function common_redirect($url, $code=307) { function common_redirect($url, $code=307) {
@ -1314,7 +1329,7 @@ function common_profile_uri($profile) {
if ($user) { if ($user) {
return $user->uri; return $user->uri;
} }
$remote = Remote_profile::staticGet($profile->id); $remote = Remote_profile::staticGet($profile->id);
if ($remote) { if ($remote) {
return $remote->uri; return $remote->uri;

View File

@ -27,20 +27,20 @@ function xmppdaemon_error_handler($errno, $errstr, $errfile, $errline, $errconte
echo "Aborting...\n"; echo "Aborting...\n";
exit(1); exit(1);
break; break;
case E_USER_WARNING: case E_USER_WARNING:
echo "WARNING [$errno] $errstr\n"; echo "WARNING [$errno] $errstr\n";
break; break;
case E_USER_NOTICE: case E_USER_NOTICE:
echo "My NOTICE [$errno] $errstr\n"; echo "My NOTICE [$errno] $errstr\n";
break; break;
default: default:
echo "Unknown error type: [$errno] $errstr\n"; echo "Unknown error type: [$errno] $errstr\n";
break; break;
} }
/* Don't execute PHP internal error handler */ /* Don't execute PHP internal error handler */
return true; return true;
} }
@ -93,7 +93,7 @@ class XMPPDaemon {
if (!$this->conn) { if (!$this->conn) {
return false; return false;
} }
return !$this->conn->isDisconnected(); return !$this->conn->isDisconnected();
} }
@ -127,12 +127,12 @@ class XMPPDaemon {
$this->confirmation_queue(); $this->confirmation_queue();
} }
} }
function handle_session($pl) { function handle_session($pl) {
# XXX what to do here? # XXX what to do here?
return true; return true;
} }
function get_user($from) { function get_user($from) {
$user = User::staticGet('jabber', jabber_normalize_jid($from)); $user = User::staticGet('jabber', jabber_normalize_jid($from));
return $user; return $user;
@ -184,7 +184,7 @@ class XMPPDaemon {
return false; return false;
} }
} }
function from_site($address, $msg) { function from_site($address, $msg) {
$text = '['.common_config('site', 'name') . '] ' . $msg; $text = '['.common_config('site', 'name') . '] ' . $msg;
jabber_send_message($address, $text); jabber_send_message($address, $text);
@ -251,7 +251,8 @@ class XMPPDaemon {
return; return;
} }
$notice->query('COMMIT'); $notice->query('COMMIT');
common_save_replies($notice); common_save_replies($notice);
$notice->saveTags();
common_real_broadcast($notice); common_real_broadcast($notice);
$this->log(LOG_INFO, $this->log(LOG_INFO,
'Added notice ' . $notice->id . ' from user ' . $user->nickname); 'Added notice ' . $notice->id . ' from user ' . $user->nickname);
@ -372,7 +373,7 @@ class XMPPDaemon {
$user = User::staticGet($notice->profile_id); $user = User::staticGet($notice->profile_id);
return !$user; return !$user;
} }
function confirmation_queue() { function confirmation_queue() {
# $this->clear_old_confirm_claims(); # $this->clear_old_confirm_claims();
$this->log(LOG_INFO, 'checking for queued confirmations'); $this->log(LOG_INFO, 'checking for queued confirmations');
@ -407,7 +408,7 @@ class XMPPDaemon {
} }
} while ($confirm); } while ($confirm);
} }
function next_confirm() { function next_confirm() {
$confirm = new Confirm_address(); $confirm = new Confirm_address();
$confirm->whereAdd('claimed IS NULL'); $confirm->whereAdd('claimed IS NULL');
@ -433,14 +434,14 @@ class XMPPDaemon {
} }
return NULL; return NULL;
} }
function clear_old_confirm_claims() { function clear_old_confirm_claims() {
$confirm = new Confirm(); $confirm = new Confirm();
$confirm->claimed = NULL; $confirm->claimed = NULL;
$confirm->whereAdd('now() - claimed > '.CLAIM_TIMEOUT); $confirm->whereAdd('now() - claimed > '.CLAIM_TIMEOUT);
$confirm->update(DB_DATAOBJECT_WHEREADD_ONLY); $confirm->update(DB_DATAOBJECT_WHEREADD_ONLY);
} }
} }
$resource = ($argc > 1) ? $argv[1] : NULL; $resource = ($argc > 1) ? $argv[1] : NULL;