diff options
author | Evan Prodromou <evan@status.net> | 2010-01-27 22:05:32 -0500 |
---|---|---|
committer | Evan Prodromou <evan@status.net> | 2010-01-27 22:05:32 -0500 |
commit | 5e1a9ad04d4e10ee44881a26ea72c9a80f748188 (patch) | |
tree | 78b7f4287d00a2ff32cf6adf82c6289a5d3b6b95 /classes | |
parent | 817f01c3b18ec626701de2a1402562eeb87eee6d (diff) | |
parent | ee4ea3f3e1eb64df2dd3ba677f5201f8787482a8 (diff) |
Merge branch 'testing'
Conflicts:
theme/base/css/display.css
Diffstat (limited to 'classes')
-rw-r--r-- | classes/Consumer.php | 21 | ||||
-rw-r--r-- | classes/Memcached_DataObject.php | 177 | ||||
-rw-r--r-- | classes/Notice.php | 10 | ||||
-rw-r--r-- | classes/Oauth_application.php | 140 | ||||
-rw-r--r-- | classes/Oauth_application_user.php | 44 | ||||
-rw-r--r-- | classes/Profile.php | 25 | ||||
-rw-r--r-- | classes/Status_network.php | 31 | ||||
-rw-r--r-- | classes/Token.php | 6 | ||||
-rw-r--r-- | classes/statusnet.ini | 34 |
9 files changed, 433 insertions, 55 deletions
diff --git a/classes/Consumer.php b/classes/Consumer.php index d5b7b7e33..ad64a8491 100644 --- a/classes/Consumer.php +++ b/classes/Consumer.php @@ -4,16 +4,17 @@ */ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; -class Consumer extends Memcached_DataObject +class Consumer extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ public $__table = 'consumer'; // table name public $consumer_key; // varchar(255) primary_key not_null + public $consumer_secret; // varchar(255) not_null public $seed; // char(32) not_null - public $created; // datetime() not_null - public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP + public $created; // datetime not_null + public $modified; // timestamp not_null default_CURRENT_TIMESTAMP /* Static get */ function staticGet($k,$v=null) @@ -21,4 +22,18 @@ class Consumer extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + static function generateNew() + { + $cons = new Consumer(); + $rand = common_good_rand(16); + + $cons->seed = $rand; + $cons->consumer_key = md5(time() + $rand); + $cons->consumer_secret = md5(md5(time() + time() + $rand)); + $cons->created = common_sql_now(); + + return $cons; + } + } diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 2c9dcf595..2cc6377f8 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -66,7 +66,6 @@ class Memcached_DataObject extends DB_DataObject // Clear this out so we don't accidentally break global // state in *this* process. $this->_DB_resultid = null; - // We don't have any local DBO refs, so clear these out. $this->_link_loaded = false; } @@ -91,9 +90,7 @@ class Memcached_DataObject extends DB_DataObject unset($i); } $i = Memcached_DataObject::getcached($cls, $k, $v); - if ($i) { - return $i; - } else { + if ($i === false) { // false == cache miss $i = DB_DataObject::factory($cls); if (empty($i)) { $i = false; @@ -101,22 +98,34 @@ class Memcached_DataObject extends DB_DataObject } $result = $i->get($k, $v); if ($result) { + // Hit! $i->encache(); - return $i; } else { + // save the fact that no such row exists + $c = self::memcache(); + if (!empty($c)) { + $ck = self::cachekey($cls, $k, $v); + $c->set($ck, null); + } $i = false; - return $i; } } + return $i; } - function &pkeyGet($cls, $kv) + /** + * @fixme Should this return false on lookup fail to match staticGet? + */ + function pkeyGet($cls, $kv) { $i = Memcached_DataObject::multicache($cls, $kv); - if ($i) { + if ($i !== false) { // false == cache miss return $i; } else { - $i = new $cls(); + $i = DB_DataObject::factory($cls); + if (empty($i)) { + return false; + } foreach ($kv as $k => $v) { $i->$k = $v; } @@ -124,6 +133,11 @@ class Memcached_DataObject extends DB_DataObject $i->encache(); } else { $i = null; + $c = self::memcache(); + if (!empty($c)) { + $ck = self::multicacheKey($cls, $kv); + $c->set($ck, null); + } } return $i; } @@ -132,6 +146,9 @@ class Memcached_DataObject extends DB_DataObject function insert() { $result = parent::insert(); + if ($result) { + $this->encache(); // in case of cached negative lookups + } return $result; } @@ -186,6 +203,17 @@ class Memcached_DataObject extends DB_DataObject function keyTypes() { + // ini-based classes return number-indexed arrays. handbuilt + // classes return column => keytype. Make this uniform. + + $keys = $this->keys(); + + $keyskeys = array_keys($keys); + + if (is_string($keyskeys[0])) { + return $keys; + } + global $_DB_DATAOBJECT; if (!isset($_DB_DATAOBJECT['INI'][$this->_database][$this->__table."__keys"])) { $this->databaseStructure(); @@ -197,6 +225,7 @@ class Memcached_DataObject extends DB_DataObject function encache() { $c = $this->memcache(); + if (!$c) { return false; } else if ($this->tableName() == 'user' && is_object($this->id)) { @@ -206,64 +235,86 @@ class Memcached_DataObject extends DB_DataObject str_replace("\n", " ", $e->getTraceAsString())); return false; } else { - $pkey = array(); - $pval = array(); - $types = $this->keyTypes(); - ksort($types); - foreach ($types as $key => $type) { - if ($type == 'K') { - $pkey[] = $key; - $pval[] = $this->$key; - } else { - $c->set($this->cacheKey($this->tableName(), $key, $this->$key), $this); - } - } - # XXX: should work for both compound and scalar pkeys - $pvals = implode(',', $pval); - $pkeys = implode(',', $pkey); - $c->set($this->cacheKey($this->tableName(), $pkeys, $pvals), $this); + $keys = $this->_allCacheKeys(); + + foreach ($keys as $key) { + $c->set($key, $this); + } } } function decache() { $c = $this->memcache(); + if (!$c) { return false; - } else { - $pkey = array(); - $pval = array(); - $types = $this->keyTypes(); - ksort($types); - foreach ($types as $key => $type) { - if ($type == 'K') { - $pkey[] = $key; - $pval[] = $this->$key; - } else { - $c->delete($this->cacheKey($this->tableName(), $key, $this->$key)); + } + + $keys = $this->_allCacheKeys(); + + foreach ($keys as $key) { + $c->delete($key, $this); + } + } + + function _allCacheKeys() + { + $ckeys = array(); + + $types = $this->keyTypes(); + ksort($types); + + $pkey = array(); + $pval = array(); + + foreach ($types as $key => $type) { + + assert(!empty($key)); + + if ($type == 'U') { + if (empty($this->$key)) { + continue; } + $ckeys[] = $this->cacheKey($this->tableName(), $key, $this->$key); + } else if ($type == 'K' || $type == 'N') { + $pkey[] = $key; + $pval[] = $this->$key; + } else { + throw new Exception("Unknown key type $key => $type for " . $this->tableName()); } - # should work for both compound and scalar pkeys - # XXX: comma works for now but may not be safe separator for future keys - $pvals = implode(',', $pval); - $pkeys = implode(',', $pkey); - $c->delete($this->cacheKey($this->tableName(), $pkeys, $pvals)); } + + assert(count($pkey) > 0); + + // XXX: should work for both compound and scalar pkeys + $pvals = implode(',', $pval); + $pkeys = implode(',', $pkey); + + $ckeys[] = $this->cacheKey($this->tableName(), $pkeys, $pvals); + + return $ckeys; } function multicache($cls, $kv) { ksort($kv); - $c = Memcached_DataObject::memcache(); + $c = self::memcache(); if (!$c) { return false; } else { - $pkeys = implode(',', array_keys($kv)); - $pvals = implode(',', array_values($kv)); - return $c->get(Memcached_DataObject::cacheKey($cls, $pkeys, $pvals)); + return $c->get(self::multicacheKey($cls, $kv)); } } + static function multicacheKey($cls, $kv) + { + ksort($kv); + $pkeys = implode(',', array_keys($kv)); + $pvals = implode(',', array_values($kv)); + return self::cacheKey($cls, $pkeys, $pvals); + } + function getSearchEngine($table) { require_once INSTALLDIR.'/lib/search_engines.php'; @@ -298,7 +349,8 @@ class Memcached_DataObject extends DB_DataObject $key_part = common_keyize($cls).':'.md5($qry); $ckey = common_cache_key($key_part); $stored = $c->get($ckey); - if ($stored) { + + if ($stored !== false) { return new ArrayWrapper($stored); } @@ -313,6 +365,39 @@ class Memcached_DataObject extends DB_DataObject return new ArrayWrapper($cached); } + /** + * sends query to database - this is the private one that must work + * - internal functions use this rather than $this->query() + * + * Overridden to do logging. + * + * @param string $string + * @access private + * @return mixed none or PEAR_Error + */ + function _query($string) + { + $start = microtime(true); + $result = parent::_query($string); + $delta = microtime(true) - $start; + + $limit = common_config('db', 'log_slow_queries'); + if (($limit > 0 && $delta >= $limit) || common_config('db', 'log_queries')) { + $clean = $this->sanitizeQuery($string); + common_log(LOG_DEBUG, sprintf("DB query (%0.3fs): %s", $delta, $clean)); + } + return $result; + } + + // Sanitize a query for logging + // @fixme don't trim spaces in string literals + function sanitizeQuery($string) + { + $string = preg_replace('/\s+/', ' ', $string); + $string = trim($string); + return $string; + } + // We overload so that 'SET NAMES "utf8"' is called for // each connection diff --git a/classes/Notice.php b/classes/Notice.php index 0966697e2..6b364fb5c 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -326,9 +326,13 @@ class Notice extends Memcached_DataObject # XXX: someone clever could prepend instead of clearing the cache $notice->blowOnInsert(); - $qm = QueueManager::get(); - - $qm->enqueue($notice, 'distrib'); + if (common_config('queue', 'inboxes')) { + $qm = QueueManager::get(); + $qm->enqueue($notice, 'distrib'); + } else { + $handler = new DistribQueueHandler(); + $handler->handle($notice); + } return $notice; } diff --git a/classes/Oauth_application.php b/classes/Oauth_application.php new file mode 100644 index 000000000..a6b539087 --- /dev/null +++ b/classes/Oauth_application.php @@ -0,0 +1,140 @@ +<?php +/** + * Table Definition for oauth_application + */ +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +class Oauth_application extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'oauth_application'; // table name + public $id; // int(4) primary_key not_null + public $owner; // int(4) not_null + public $consumer_key; // varchar(255) not_null + public $name; // varchar(255) not_null + public $description; // varchar(255) + public $icon; // varchar(255) not_null + public $source_url; // varchar(255) + public $organization; // varchar(255) + public $homepage; // varchar(255) + public $callback_url; // varchar(255) not_null + public $type; // tinyint(1) + public $access_type; // tinyint(1) + public $created; // datetime not_null + public $modified; // timestamp not_null default_CURRENT_TIMESTAMP + + /* Static get */ + function staticGet($k,$v=NULL) { + return Memcached_DataObject::staticGet('Oauth_application',$k,$v); + } + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE + + // Bit flags + public static $readAccess = 1; + public static $writeAccess = 2; + + public static $browser = 1; + public static $desktop = 2; + + function getConsumer() + { + return Consumer::staticGet('consumer_key', $this->consumer_key); + } + + static function maxDesc() + { + $desclimit = common_config('application', 'desclimit'); + // null => use global limit (distinct from 0!) + if (is_null($desclimit)) { + $desclimit = common_config('site', 'textlimit'); + } + return $desclimit; + } + + static function descriptionTooLong($desc) + { + $desclimit = self::maxDesc(); + return ($desclimit > 0 && !empty($desc) && (mb_strlen($desc) > $desclimit)); + } + + function setAccessFlags($read, $write) + { + if ($read) { + $this->access_type |= self::$readAccess; + } else { + $this->access_type &= ~self::$readAccess; + } + + if ($write) { + $this->access_type |= self::$writeAccess; + } else { + $this->access_type &= ~self::$writeAccess; + } + } + + function setOriginal($filename) + { + $imagefile = new ImageFile($this->id, Avatar::path($filename)); + + // XXX: Do we want to have a bunch of different size icons? homepage, stream, mini? + // or just one and control size via CSS? --Zach + + $orig = clone($this); + $this->icon = Avatar::url($filename); + common_debug(common_log_objstring($this)); + return $this->update($orig); + } + + static function getByConsumerKey($key) + { + if (empty($key)) { + return null; + } + + $app = new Oauth_application(); + $app->consumer_key = $key; + $app->limit(1); + $result = $app->find(true); + + return empty($result) ? null : $app; + } + + /** + * Handle an image upload + * + * Does all the magic for handling an image upload, and crops the + * image by default. + * + * @return void + */ + + function uploadLogo() + { + if ($_FILES['app_icon']['error'] == + UPLOAD_ERR_OK) { + + try { + $imagefile = ImageFile::fromUpload('app_icon'); + } catch (Exception $e) { + common_debug("damn that sucks"); + $this->showForm($e->getMessage()); + return; + } + + $filename = Avatar::filename($this->id, + image_type_to_extension($imagefile->type), + null, + 'oauth-app-icon-'.common_timestamp()); + + $filepath = Avatar::path($filename); + + move_uploaded_file($imagefile->filepath, $filepath); + + $this->setOriginal($filename); + } + } + +} diff --git a/classes/Oauth_application_user.php b/classes/Oauth_application_user.php new file mode 100644 index 000000000..57986281f --- /dev/null +++ b/classes/Oauth_application_user.php @@ -0,0 +1,44 @@ +<?php +/** + * Table Definition for oauth_application_user + */ +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +class Oauth_application_user extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'oauth_application_user'; // table name + public $profile_id; // int(4) primary_key not_null + public $application_id; // int(4) primary_key not_null + public $access_type; // tinyint(1) + public $token; // varchar(255) + public $created; // datetime not_null + public $modified; // timestamp not_null default_CURRENT_TIMESTAMP + + /* Static get */ + function staticGet($k,$v=NULL) { + return Memcached_DataObject::staticGet('Oauth_application_user',$k,$v); + } + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE + + static function getByKeys($user, $app) + { + if (empty($user) || empty($app)) { + return null; + } + + $oau = new Oauth_application_user(); + + $oau->profile_id = $user->id; + $oau->application_id = $app->id; + $oau->limit(1); + + $result = $oau->find(true); + + return empty($result) ? null : $oau; + } + +} diff --git a/classes/Profile.php b/classes/Profile.php index 25d908dbf..1076fb2cb 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -352,6 +352,31 @@ class Profile extends Memcached_DataObject return $profile; } + function getApplications($offset = 0, $limit = null) + { + $qry = + 'SELECT a.* ' . + 'FROM oauth_application_user u, oauth_application a ' . + 'WHERE u.profile_id = %d ' . + 'AND a.id = u.application_id ' . + 'AND u.access_type > 0 ' . + 'ORDER BY u.created DESC '; + + if ($offset > 0) { + if (common_config('db','type') == 'pgsql') { + $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= ' LIMIT ' . $offset . ', ' . $limit; + } + } + + $application = new Oauth_application(); + + $cnt = $application->query(sprintf($qry, $this->id)); + + return $application; + } + function subscriptionCount() { $c = common_memcache(); diff --git a/classes/Status_network.php b/classes/Status_network.php index 445f8a5a3..4bda24b6a 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -39,9 +39,19 @@ class Status_network extends DB_DataObject public $logo; // varchar(255) public $created; // datetime() not_null public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP + public $tags; // text /* Static get */ - function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('Status_network',$k,$v); } + function staticGet($k,$v=NULL) { + $i = DB_DataObject::staticGet('Status_network',$k,$v); + + // Don't use local process cache; if we're fetching multiple + // times it's because we're reloading it in a long-running + // process; we need a fresh copy! + global $_DB_DATAOBJECT; + unset($_DB_DATAOBJECT['CACHE']['status_network']); + return $i; + } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE @@ -245,4 +255,23 @@ class Status_network extends DB_DataObject return $this->nickname . '.' . self::$wildcard; } } + + /** + * Return site meta-info tags as an array + * @return array of strings + */ + function getTags() + { + return array_filter(explode("|", strval($this->tags))); + } + + /** + * Check if this site record has a particular meta-info tag attached. + * @param string $tag + * @return bool + */ + function hasTag($tag) + { + return in_array($tag, $this->getTags()); + } } diff --git a/classes/Token.php b/classes/Token.php index 1fabd72f1..a129d1fd1 100644 --- a/classes/Token.php +++ b/classes/Token.php @@ -4,7 +4,7 @@ */ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; -class Token extends Memcached_DataObject +class Token extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -14,7 +14,9 @@ class Token extends Memcached_DataObject public $tok; // char(32) primary_key not_null public $secret; // char(32) not_null public $type; // tinyint(1) not_null - public $state; // tinyint(1) + public $state; // tinyint(1) + public $verifier; // varchar(255) + public $verified_callback; // varchar(255) public $created; // datetime() not_null public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP diff --git a/classes/statusnet.ini b/classes/statusnet.ini index 6ce4495be..6203650a6 100644 --- a/classes/statusnet.ini +++ b/classes/statusnet.ini @@ -39,6 +39,7 @@ code = K [consumer] consumer_key = 130 +consumer_secret = 130 seed = 130 created = 142 modified = 384 @@ -348,6 +349,37 @@ created = 142 tag = K notice_id = K +[oauth_application] +id = 129 +owner = 129 +consumer_key = 130 +name = 130 +description = 2 +icon = 130 +source_url = 2 +organization = 2 +homepage = 2 +callback_url = 130 +type = 17 +access_type = 17 +created = 142 +modified = 384 + +[oauth_application__keys] +id = N + +[oauth_application_user] +profile_id = 129 +application_id = 129 +access_type = 17 +token = 2 +created = 142 +modified = 384 + +[oauth_application_user__keys] +profile_id = K +application_id = K + [profile] id = 129 nickname = 130 @@ -484,6 +516,8 @@ tok = 130 secret = 130 type = 145 state = 17 +verifier = 2 +verified_callback = 2 created = 142 modified = 384 |