From: Raphaël Barrois Date: Tue, 16 Feb 2010 10:34:25 +0000 (+0100) Subject: Add UserIterator, ProfileIterator X-Git-Tag: xorg/1.0.0~332^2~210 X-Git-Url: http://git.polytechnique.org/?a=commitdiff_plain;h=0d90610978302dc5be0552c7d27f985f7d270055;p=platal.git Add UserIterator, ProfileIterator Wrappers around the XDB::iterator over the data for building those objects Signed-off-by: Raphaël Barrois --- diff --git a/classes/profile.php b/classes/profile.php index a801efc..3e9ea2d 100644 --- a/classes/profile.php +++ b/classes/profile.php @@ -205,8 +205,8 @@ class Profile public function setVisibilityLevel($visibility) { - if ($visibility != self::VISIBILITY_PRIVATE - && $visibility != self::VISIBILITY_AX + if ($visibility != self::VISIBILITY_PRIVATE + && $visibility != self::VISIBILITY_AX && $visibility != self::VISIBILITY_PUBLIC) { Platal::page()->kill("Visibility invalide: " . $visibility); } @@ -419,35 +419,44 @@ class Profile return User::getSilent($this); } - private static function fetchProfileData(array $pids) + private static function fetchProfileData(array $pids, $respect_order = true) { if (count($pids) == 0) { return array(); } - return XDB::fetchAllAssoc('SELECT p.*, p.sex = \'female\' AS sex, pe.entry_year, pe.grad_year, - pn_f.name AS firstname, pn_l.name AS lastname, pn_n.name AS nickname, - IF(pn_uf.name IS NULL, pn_f.name, pn_uf.name) AS firstname_ordinary, - IF(pn_ul.name IS NULL, pn_l.name, pn_ul.name) AS lastname_ordinary, - pd.promo AS promo, pd.short_name, pd.directory_name AS full_name, - pd.directory_name, pp.display_tel AS mobile, pp.pub AS mobile_pub, - ph.pub AS photo_pub - FROM profiles AS p - INNER JOIN profile_display AS pd ON (pd.pid = p.pid) - INNER JOIN profile_education AS pe ON (pe.uid = p.pid AND FIND_IN_SET(\'primary\', pe.flags)) - INNER JOIN profile_name AS pn_f ON (pn_f.pid = p.pid - AND pn_f.typeid = ' . self::getNameTypeId('firstname', true) . ') - INNER JOIN profile_name AS pn_l ON (pn_l.pid = p.pid - AND pn_l.typeid = ' . self::getNameTypeId('lastname', true) . ') - LEFT JOIN profile_name AS pn_uf ON (pn_uf.pid = p.pid - AND pn_uf.typeid = ' . self::getNameTypeId('firstname_ordinary', true) . ') - LEFT JOIN profile_name AS pn_ul ON (pn_ul.pid = p.pid - AND pn_ul.typeid = ' . self::getNameTypeId('lastname_ordinary', true) . ') - LEFT JOIN profile_name AS pn_n ON (pn_n.pid = p.pid - AND pn_n.typeid = ' . self::getNameTypeId('nickname', true) . ') - LEFT JOIN profile_phones AS pp ON (pp.uid = p.pid AND pp.link_type = \'user\' AND tel_type = \'mobile\') - LEFT JOIN photo AS ph ON (ph.uid = p.pid) - WHERE p.pid IN ' . XDB::formatArray($pids) . ' - GROUP BY p.pid'); + + if ($respect_order) { + $order = 'ORDER BY ' . XDB::formatCustomOrder('p.pid', $pids); + } else { + $order = ''; + } + + return XDB::Iterator('SELECT p.*, p.sex = \'female\' AS sex, pe.entry_year, pe.grad_year, + pn_f.name AS firstname, pn_l.name AS lastname, pn_n.name AS nickname, + IF(pn_uf.name IS NULL, pn_f.name, pn_uf.name) AS firstname_ordinary, + IF(pn_ul.name IS NULL, pn_l.name, pn_ul.name) AS lastname_ordinary, + pd.promo AS promo, pd.short_name, pd.directory_name AS full_name, + pd.directory_name, pp.display_tel AS mobile, pp.pub AS mobile_pub, + ph.pub AS photo_pub, ap.uid AS owner_id + FROM profiles AS p + INNER JOIN profile_display AS pd ON (pd.pid = p.pid) + INNER JOIN profile_education AS pe ON (pe.uid = p.pid AND FIND_IN_SET(\'primary\', pe.flags)) + INNER JOIN profile_name AS pn_f ON (pn_f.pid = p.pid + AND pn_f.typeid = ' . self::getNameTypeId('firstname', true) . ') + INNER JOIN profile_name AS pn_l ON (pn_l.pid = p.pid + AND pn_l.typeid = ' . self::getNameTypeId('lastname', true) . ') + LEFT JOIN profile_name AS pn_uf ON (pn_uf.pid = p.pid + AND pn_uf.typeid = ' . self::getNameTypeId('firstname_ordinary', true) . ') + LEFT JOIN profile_name AS pn_ul ON (pn_ul.pid = p.pid + AND pn_ul.typeid = ' . self::getNameTypeId('lastname_ordinary', true) . ') + LEFT JOIN profile_name AS pn_n ON (pn_n.pid = p.pid + AND pn_n.typeid = ' . self::getNameTypeId('nickname', true) . ') + LEFT JOIN profile_phones AS pp ON (pp.uid = p.pid AND pp.link_type = \'user\' AND tel_type = \'mobile\') + LEFT JOIN photo AS ph ON (ph.uid = p.pid) + LEFT JOIN account_profiles AS ap ON (ap.pid = p.pid AND FIND_IN_SET(\'owner\', ap.perms)) + WHERE p.pid IN ' . XDB::formatArray($pids) . ' + GROUP BY p.pid + ' . $order); } public static function getPID($login) @@ -468,6 +477,19 @@ class Profile } } + public static function getPIDsFromUIDs($uids, $respect_order = true) + { + if ($respect_order) { + $order = 'ORDER BY ' . XDB::formatCustomOrder('uid', $uids); + } else { + $order = ''; + } + return XDB::fetchAllAssoc('uid', 'SELECT ap.uid, ap.pid + FROM account_profiles AS ap + WHERE FIND_IN_SET(\'owner\', ap.perms) + AND ap.uid IN ' . XDB::formatArray($uids) .' + ' . $order); + } /** Return the profile associated with the given login. */ @@ -475,8 +497,8 @@ class Profile { $pid = self::getPID($login); if (!is_null($pid)) { - $data = self::fetchProfileData(array($pid)); - return new Profile(array_pop($data)); + $it = self::iterOverPIDs(array($pid), false); + return $it->next(); } else { /* Let say we can identify a profile using the identifiers of its owner. */ @@ -490,6 +512,16 @@ class Profile } } + public static function iterOverUIDs($uids, $respect_order = true) + { + return self::iterOverPIDs(self::getPIDsFromUIDs($uids), $respect_order); + } + + public static function iterOverPIDs($pids, $respect_order = true) + { + return new ProfileIterator(self::fetchProfileData($pids, $respect_order)); + } + /** Return profiles for the list of pids. */ public static function getBulkProfilesWithPIDs(array $pids) @@ -497,13 +529,10 @@ class Profile if (count($pids) == 0) { return array(); } - $data = self::fetchProfileData($pids); - $inv = array_flip($pids); + $it = self::iterOverPIDs($pids); $profiles = array(); - foreach ($data AS $p) { - $p = new Profile($p); - $key = $inv[$p->id()]; - $profiles[$key] = $p; + while ($p = $it->next()) { + $profiles[$p->id()] = $p; } return $profiles; } @@ -515,11 +544,7 @@ class Profile if (count($uids) == 0) { return array(); } - $table = XDB::fetchAllAssoc('uid', 'SELECT ap.uid, ap.pid - FROM account_profiles AS ap - WHERE FIND_IN_SET(\'owner\', ap.perms) - AND ap.uid IN ' . XDB::formatArray($uids)); - return self::getBulkProfilesWithPIDs($table); + return self::getBulkProfilesWithPIDs(self::getPIDsFromUIDs($uids)); } public static function isDisplayName($name) @@ -547,5 +572,43 @@ class Profile } } +/** Iterator over a set of Profiles + * @param an XDB::Iterator obtained from a Profile::fetchProfileData + */ +class ProfileIterator implements PlIterator +{ + private $dbiter; + + public function __construct($dbiter) + { + $this->dbiter = $dbiter; + } + + public function next() + { + $data = $this->dbiter->next(); + if ($data == null) { + return null; + } else { + return new Profile($data); + } + } + + public function total() + { + return $this->dbiter->total(); + } + + public function first() + { + return $this->dbiter->first(); + } + + public function last() + { + return $this->dbiter->last(); + } +} + // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: ?> diff --git a/classes/user.php b/classes/user.php index dc85970..0123003 100644 --- a/classes/user.php +++ b/classes/user.php @@ -146,7 +146,7 @@ class User extends PlUser throw new UserNotFoundException($res->fetchColumn(1)); } - protected static function loadMainFieldsFromUIDs(array $uids) + protected static function loadMainFieldsFromUIDs(array $uids, $respect_order = true) { global $globals; $joins = ''; @@ -161,7 +161,15 @@ class User extends PlUser } else { $fields = ''; } + + if ($respect_order) { + $order = 'ORDER BY ' . XDB::formatCustomOrder('a.uid', $uids); + } else { + $order = ''; + } + $uids = array_map(array('XDB', 'escape'), $uids); + return XDB::iterator('SELECT a.uid, a.hruid, a.registration_date, CONCAT(af.alias, \'@' . $globals->mail->domain . '\') AS forlife, CONCAT(af.alias, \'@' . $globals->mail->domain2 . '\') AS forlife_alternate, @@ -183,7 +191,8 @@ class User extends PlUser LEFT JOIN email_options AS eo ON (eo.uid = a.uid) ' . $joins . ' WHERE a.uid IN (' . implode(', ', $uids) . ') - GROUP BY a.uid'); + GROUP BY a.uid + ' . $order); } // Implementation of the data loader. @@ -535,7 +544,18 @@ class User extends PlUser || $dom == $globals->mail->alias_dom2; } - // Fetch a set of users from a list of UIDs + public static function iterOverUIDs($uids, $respect_order = true) + { + return new UserIterator(self::loadMainFieldsFromUIDs($uids, $respect_order)); + } + + /** Fetch a set of users from a list of UIDs + * @param $data The list of uids to fetch, or an array of arrays + * @param $orig If $data is an array of arrays, the subfield where uids are stored + * @param $dest If $data is an array of arrays, the subfield to fill with Users + * @param $fetchProfile Whether to fetch Profiles as well + * @return either an array of $uid => User, or $data with $data[$i][$dest] = User + */ public static function getBulkUsersWithUIDs(array $data, $orig = null, $dest = null, $fetchProfile = true) { // Fetch the list of uids @@ -557,30 +577,33 @@ class User extends PlUser if (count($uids) == 0) { return $data; } - $fields = self::loadMainFieldsFromUIDs($uids); + $users = self::iterOverUIDs($uids, true); + $table = array(); if ($fetchProfile) { - $profiles = Profile::getBulkProfilesWithUIDS($uids); + $profiles = Profile::iterOverUIDS($uids, true); + $profile = $profiles->next(); } - while (($list = $fields->next())) { - $uid = $list['uid']; - $user = User::getSilentWithValues(null, $list); + + /** We iterate through the users, moving in + * profiles when they match the user ID : + * there can be users without a profile, but not + * the other way around. + */ + while (($user = $users->next())) { if ($fetchProfile) { - if (isset($profiles[$uid])) { - $user->_profile = $profiles[$uid]; + if ($profile->owner_id == $user->id()) { + $user->_profile = $profile; + $profile = $profiles->next(); } $user->_profile_fetched = true; } - $table[$list['uid']] = $user; + $table[$user->id()] = $user; } // Build the result with respect to input order. if (is_null($orig)) { - $users = array(); - foreach ($uids as $key=>$uid) { - $users[$key] = $table[$uid]; - } - return $users; + return $table; } else { foreach ($data as $key=>$entry) { if (isset($entry[$orig])) { @@ -600,5 +623,43 @@ class User extends PlUser } } +/** Iterator over a set of Users + * @param an XDB::Iterator obtained from a User::loadMainFieldsFromUIDs + */ +class UserIterator implements PlIterator +{ + private $dbiter; + + public function __construct($dbiter) + { + $this->dbiter = $dbiter; + } + + public function next() + { + $data = $this->dbiter->next(); + if ($data == null) { + return null; + } else { + return User::getSilentWithValues(null, $data); + } + } + + public function total() + { + return $this->dbiter->total(); + } + + public function first() + { + return $this->dbiter->first(); + } + + public function last() + { + return $this->dbiter->last(); + } +} + // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: ?> diff --git a/classes/userfilter.php b/classes/userfilter.php index 20b9247..52ad12d 100644 --- a/classes/userfilter.php +++ b/classes/userfilter.php @@ -1702,11 +1702,21 @@ class UserFilter extends PlFilter return User::getBulkUsersWithUIDs($this->getUIDs($limit)); } + public function iterUsers($limit = null) + { + return User::iterOverUIDs($this->getUIDs($limit)); + } + public function getProfiles($limit = null) { return Profile::getBulkProfilesWithPIDs($this->getPIDs($limit)); } + public function iterProfiles($limit = null) + { + return Profile::iterOverPIDs($this->getPIDs($limit)); + } + public function get($limit = null) { return $this->getUsers($limit); diff --git a/core b/core index 2ab7557..47595f9 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 2ab75571bf840471fa9559292b75852bfce004d3 +Subproject commit 47595f9a4a4f4ee903e6ac02d64b9b5b5b6bf191