*
* @see DB_DataObject
*/
-
class Bookmark extends Memcached_DataObject
{
public $__table = 'bookmark'; // table name
- public $profile_id; // int(4) primary_key not_null
- public $url; // varchar(255) primary_key not_null
- public $title; // varchar(255)
- public $description; // text
- public $uri; // varchar(255)
- public $url_crc32; // int(4) not_null
- public $created; // datetime
+ public $id; // char(36) primary_key not_null
+ public $profile_id; // int(4) not_null
+ public $url; // varchar(255) not_null
+ public $title; // varchar(255)
+ public $description; // text
+ public $uri; // varchar(255)
+ public $created; // datetime
/**
* Get an instance by key
* @return User_greeting_count object found, or null for no hits
*
*/
-
function staticGet($k, $v=null)
{
return Memcached_DataObject::staticGet('Bookmark', $k, $v);
* @return Bookmark object found, or null for no hits
*
*/
-
function pkeyGet($kv)
{
return Memcached_DataObject::pkeyGet('Bookmark', $kv);
*
* @return array array of column definitions
*/
-
function table()
{
- return array('profile_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
+ return array('id' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
+ 'profile_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
'url' => DB_DATAOBJECT_STR,
'title' => DB_DATAOBJECT_STR,
'description' => DB_DATAOBJECT_STR,
'uri' => DB_DATAOBJECT_STR,
- 'url_crc32' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
- 'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
+ 'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE +
+ DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
}
/**
*
* @return array list of key field names
*/
-
function keys()
{
return array_keys($this->keyTypes());
*
* @return array associative array of key definitions
*/
-
function keyTypes()
{
- return array('profile_id' => 'K',
- 'url' => 'K',
+ return array('id' => 'K',
'uri' => 'U');
}
*
* @return array magic three-false array that stops auto-incrementing.
*/
-
function sequenceKey()
{
return array(false, false, false);
/**
* Get a bookmark based on a notice
- *
+ *
* @param Notice $notice Notice to check for
*
* @return Bookmark found bookmark or null
*/
-
function getByNotice($notice)
{
return self::staticGet('uri', $notice->uri);
*
* @return Bookmark bookmark found or null
*/
-
static function getByURL($profile, $url)
{
- return self::pkeyGet(array('profile_id' => $profile->id,
- 'url' => $url));
- return null;
- }
-
- /**
- * Get the bookmark that a user made for an URL
- *
- * @param Profile $profile Profile to check for
- * @param integer $crc32 CRC-32 of URL to check for
- *
- * @return array Bookmark objects found (usually 1 or 0)
- */
-
- static function getByCRC32($profile, $crc32)
- {
- $bookmarks = array();
-
$nb = new Bookmark();
-
+
$nb->profile_id = $profile->id;
- $nb->url_crc32 = $crc32;
+ $nb->url = $url;
- if ($nb->find()) {
- while ($nb->fetch()) {
- $bookmarks[] = clone($nb);
- }
+ if ($nb->find(true)) {
+ return $nb;
+ } else {
+ return null;
}
-
- return $bookmarks;
}
/**
*
* @return Notice saved notice
*/
-
static function saveNew($profile, $title, $url, $rawtags, $description,
$options=null)
{
$nb = self::getByURL($profile, $url);
if (!empty($nb)) {
- throw new ClientException(_('Bookmark already exists.'));
+ // TRANS: Client exception thrown when trying to save a new bookmark that already exists.
+ throw new ClientException(_m('Bookmark already exists.'));
}
if (empty($options)) {
$options = array();
}
+ if (array_key_exists('uri', $options)) {
+ $other = Bookmark::staticGet('uri', $options['uri']);
+ if (!empty($other)) {
+ // TRANS: Client exception thrown when trying to save a new bookmark that already exists.
+ throw new ClientException(_m('Bookmark already exists.'));
+ }
+ }
+
if (is_string($rawtags)) {
- $rawtags = preg_split('/[\s,]+/', $rawtags);
+ if (empty($rawtags)) {
+ $rawtags = array();
+ } else {
+ $rawtags = preg_split('/[\s,]+/', $rawtags);
+ }
}
$nb = new Bookmark();
+ $nb->id = UUID::gen();
$nb->profile_id = $profile->id;
$nb->url = $url;
$nb->title = $title;
$nb->description = $description;
- $nb->url_crc32 = crc32($nb->url);
if (array_key_exists('created', $options)) {
$nb->created = $options['created'];
if (array_key_exists('uri', $options)) {
$nb->uri = $options['uri'];
} else {
- $dt = new DateTime($nb->created, new DateTimeZone('UTC'));
-
- // I posit that it's sufficiently impossible
- // for the same user to generate two CRC-32-clashing
- // URLs in the same second that this is a safe unique identifier.
- // If you find a real counterexample, contact me at acct:evan@status.net
- // and I will publicly apologize for my hubris.
+ // FIXME: hacks to work around router bugs in
+ // queue daemons
- $created = $dt->format('YmdHis');
+ $r = Router::get();
- $crc32 = sprintf('%08x', $nb->url_crc32);
+ $path = $r->build('showbookmark',
+ array('id' => $nb->id));
- $nb->uri = common_local_url('showbookmark',
- array('user' => $profile->id,
- 'created' => $created,
- 'crc32' => $crc32));
+ if (empty($path)) {
+ $nb->uri = common_path('bookmark/'.$nb->id, false, false);
+ } else {
+ $nb->uri = common_local_url('showbookmark',
+ array('id' => $nb->id),
+ null,
+ null,
+ false);
+ }
}
$nb->insert();
foreach ($rawtags as $tag) {
if (strtolower(mb_substr($tag, 0, 4)) == 'for:') {
- $nickname = mb_substr($tag, 4);
- $other = common_relative_profile($profile,
- $nickname);
- if (!empty($other)) {
- $replies[] = $other->getUri();
+ // skip if done by caller
+ if (!array_key_exists('replies', $options)) {
+ $nickname = mb_substr($tag, 4);
+ $other = common_relative_profile($profile,
+ $nickname);
+ if (!empty($other)) {
+ $replies[] = $other->getUri();
+ }
}
} else {
$tags[] = common_canonical_tag($tag);
}
}
- //
-
$hashtags = array();
$taglinks = array();
// Use user's preferences for short URLs, if possible
- $user = User::staticGet('id', $profile->id);
+ try {
+ $user = User::staticGet('id', $profile->id);
- $shortUrl = File_redirection::makeShort($url,
- empty($user) ? null : $user);
+ $shortUrl = File_redirection::makeShort($url,
+ empty($user) ? null : $user);
+ } catch (Exception $e) {
+ // Don't let this stop us.
+ $shortUrl = $url;
+ }
- $content = sprintf(_('"%s" %s %s %s'),
+ // TRANS: Bookmark content.
+ // TRANS: %1$s is a title, %2$s is a short URL, %3$s is the bookmark description,
+ // TRANS: %4$s is space separated list of hash tags.
+ $content = sprintf(_m('"%1$s" %2$s %3$s %4$s'),
$title,
$shortUrl,
$description,
implode(' ', $hashtags));
- $rendered = sprintf(_('<span class="xfolkentry">'.
- '<a class="taggedlink" href="%s">%s</a> '.
- '<span class="description">%s</span> '.
- '<span class="meta">%s</span>'.
+ // TRANS: Rendered bookmark content.
+ // TRANS: %1$s is a URL, %2$s the bookmark title, %3$s is the bookmark description,
+ // TRANS: %4$s is space separated list of hash tags.
+ $rendered = sprintf(_m('<span class="xfolkentry">'.
+ '<a class="taggedlink" href="%1$s">%2$s</a> '.
+ '<span class="description">%3$s</span> '.
+ '<span class="meta">%4$s</span>'.
'</span>'),
htmlspecialchars($url),
htmlspecialchars($title),
htmlspecialchars($description),
implode(' ', $taglinks));
- $options = array_merge($options, array('urls' => array($url),
- 'rendered' => $rendered,
- 'tags' => $tags,
- 'replies' => $replies));
+ $options = array_merge(array('urls' => array($url),
+ 'rendered' => $rendered,
+ 'tags' => $tags,
+ 'replies' => $replies,
+ 'object_type' => ActivityObject::BOOKMARK),
+ $options);
if (!array_key_exists('uri', $options)) {
$options['uri'] = $nb->uri;
}
- $saved = Notice::saveNew($profile->id,
- $content,
- array_key_exists('source', $options) ?
- $options['source'] : 'web',
- $options);
+ try {
+ $saved = Notice::saveNew($profile->id,
+ $content,
+ array_key_exists('source', $options) ?
+ $options['source'] : 'web',
+ $options);
+ } catch (Exception $e) {
+ $nb->delete();
+ throw $e;
+ }
+
+ if (empty($saved)) {
+ $nb->delete();
+ }
return $saved;
}