X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=classes%2Fprofile.php;h=663f2f7a723ea33392cd3d96c6f2f5ea21b53188;hb=f6e35ff3fefafe908e1675690340ab93265192a0;hp=951e6f29f163c529f895eefeeab96d8523f6cc63;hpb=7988f7d68c04cd73cb170e3a4db58427297ea3ec;p=platal.git diff --git a/classes/profile.php b/classes/profile.php index 951e6f2..663f2f7 100644 --- a/classes/profile.php +++ b/classes/profile.php @@ -19,15 +19,66 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ***************************************************************************/ -class Profile +class ProfileVisibility { - static private $v_values = array('public' => array('public'), - 'ax' => array('ax', 'public'), - 'private' => array('private', 'ax', 'public')); + static private $v_values = array(self::VIS_PUBLIC => array(self::VIS_PUBLIC), + self::VIS_AX => array(self::VIS_AX, self::VIS_PUBLIC), + self::VIS_PRIVATE => array(self::VIS_PRIVATE, self::VIS_AX, self::VIS_PUBLIC)); + + const VIS_PUBLIC = 'public'; + const VIS_AX = 'ax'; + const VIS_PRIVATE = 'private'; + + private $level; + + public function __construct($level = null) + { + $this->setLevel($level); + } + + public function setLevel($level = self::VIS_PUBLIC) + { + if ($level != null && $level != self::VIS_PRIVATE && $level != self::VIS_AX && $level != self::VIS_PUBLIC) { + Platal::page()->kill("Invalid visibility: " . $level); + } + + if (!S::logged()) { + $level = self::VIS_PUBLIC; + } else if ($level == null) { + $level = self::VIS_PRIVATE; + } + + if ($this->level == null || $this->level == self::VIS_PRIVATE) { + $this->level = $level; + } else if ($this->level == self::VIS_AX && $level == self::VIS_PRIVATE) { + return; + } else { + $this->level = self::VIS_PUBLIC; + } + } + + public function level() + { + if ($this->level == null) { + return self::VIS_PUBLIC; + } else { + return $this->level; + } + } - const VISIBILITY_PUBLIC = 'public'; - const VISIBILITY_AX = 'ax'; - const VISIBILITY_PRIVATE = 'private'; + public function levels() + { + return self::$v_values[$this->level()]; + } + + public function isVisible($visibility) + { + return in_array($visibility, $this->levels()); + } +} + +class Profile +{ /* name tokens */ const LASTNAME = 'lastname'; @@ -82,89 +133,134 @@ class Profile const NETWORKING_IM = 0x020000; const NETWORKING_SOCIAL = 0x040000; - const FETCH_ADDRESSES = 0x000001; - const FETCH_CORPS = 0x000002; - const FETCH_EDU = 0x000004; - const FETCH_JOBS = 0x000008; - const FETCH_MEDALS = 0x000010; - const FETCH_NETWORKING = 0x000020; - const FETCH_PHONES = 0x000040; + const FETCH_ADDRESSES = 0x000001; + const FETCH_CORPS = 0x000002; + const FETCH_EDU = 0x000004; + const FETCH_JOBS = 0x000008; + const FETCH_MEDALS = 0x000010; + const FETCH_NETWORKING = 0x000020; + const FETCH_MENTOR_SECTOR = 0x000040; + const FETCH_MENTOR_COUNTRY = 0x000080; + const FETCH_PHONES = 0x000100; + + const FETCH_MINIFICHES = 0x00012D; // FETCH_ADDRESSES | FETCH_EDU | FETCH_JOBS | FETCH_NETWORKING | FETCH_PHONES - const FETCH_MINIFICHES = 0x00004D; // FETCH_ADDRESSES | FETCH_EDU | FETCH_JOBS | FETCH_PHONES + const FETCH_ALL = 0x0001FF; // OR of FETCH_* - const FETCH_ALL = 0x0000FF; // OR of FETCH_* + private $fetched_fields = 0x000000; private $pid; private $hrpid; + private $owner; + private $owner_fetched = false; private $data = array(); private $visibility = null; + private function __construct(array $data) { $this->data = $data; $this->pid = $this->data['pid']; $this->hrpid = $this->data['hrpid']; - if (!S::logged()) { - $this->setVisibilityLevel(self::VISIBILITY_PUBLIC); - } else { - $this->setVisibilityLevel(self::VISIBILITY_PRIVATE); - } + $this->visibility = new ProfileVisibility(); } - static private $contexts = array(); - - /** Returns the best visibility context toward $visibility - * @param $visibility A wished visibility level - * @return An array of compatible visibilities - * - * if $visibility is null, the best visibility is returned - */ - static public function getVisibilityContext($visibility = null) + public function id() { - if (array_key_exists($visibility, self::$contexts)) { - return self::$contexts[$visibility]; - } + return $this->pid; + } - $asked_vis = $visibility; + public function hrid() + { + return $this->hrpid; + } - if (S::logged()) { - $minvis = self::VISIBILITY_PRIVATE; - } else { - $minvis = self::VISIBILITY_PUBLIC; - } - if ($visibility == null) { - $visibility = $minvis; + public function owner() + { + if ($this->owner == null && !$this->owner_fetched) { + $this->owner_fetched = true; + $this->owner = User::getSilent($this); } + return $this->owner; + } - if ($minvis == self::VISIBILITY_PUBLIC) { - $visibility = self::VISIBILITY_PUBLIC; - } + public function promo() + { + return $this->promo; + } - $visibility = self::$v_values[$visibility]; - self::$contexts[$asked_vis] = $visibility; + public function yearpromo() + { + return intval(substr($this->promo, 1, 4)); + } - return $visibility; + /** Check if user is an orange (associated with several promos) + */ + public function isMultiPromo() + { + return $this->grad_year != $this->entry_year + $this->mainEducationDuration(); } - public function id() + /** Returns an array with all associated promo years. + */ + public function yearspromo() { - return $this->pid; + $promos = array(); + $d = -$this->deltaPromoToGradYear(); + for ($g = $this->entry_year + $this->mainEducationDuration(); $g <= $this->grad_year; ++$g) { + $promos[] = $g + $d; + } + return $promos; } - public function hrid() + public function mainEducation() { - return $this->hrpid; + if (empty($this->promo)) { + return null; + } else { + return $this->promo{0}; + } } - public function promo() + public function mainGrade() { - return $this->promo; + switch ($this->mainEducation()) { + case 'X': + return UserFilter::GRADE_ING; + case 'M': + return UserFilter::GRADE_MST; + case 'D': + return UserFilter::GRADE_PHD; + default: + return null; + } } - public function yearpromo() + public function mainEducationDuration() { - return intval(substr($this->promo, 1, 4)); + switch ($this->mainEducation()) { + case 'X': + return 3; + case 'M': + return 2; + case 'D': + return 3; + default: + return 0; + } + } + + /** Number of years between the promotion year until the + * graduation year. In standard schools it's 0, but for + * Polytechnique the promo year is the entry year. + */ + public function deltaPromoToGradYear() + { + if ($this->mainEducation() == 'X') { + return $this->mainEducationDuration(); + } + return 0; } /** Print a name with the given formatting: @@ -230,6 +326,16 @@ class Profile return ($this->deathdate != null); } + public function displayEmail() + { + $o = $this->owner(); + if ($o != null) { + return $o->bestEmail(); + } else { + return $this->email_directory; + } + } + public function data() { $this->first_name; @@ -282,21 +388,23 @@ class Profile return property_exists($this, $name) || isset($this->data[$name]); } + public function __unset($name) + { + if (property_exists($this, $name)) { + $this->$name = null; + } else { + unset($this->data[$name]); + } + } + + /** Sets the level of visibility of the profile * Sets $this->visibility to a list of valid visibilities. - * @param one of the self::VISIBILITY_* values + * @param one of the self::VIS_* values */ public function setVisibilityLevel($visibility) { - if ($visibility != self::VISIBILITY_PRIVATE - && $visibility != self::VISIBILITY_AX - && $visibility != self::VISIBILITY_PUBLIC) { - Platal::page()->kill("Visibility invalide: " . $visibility); - } - $this->visibility = self::$v_values[$visibility]; - if ($this->mobile && !in_array($this->mobile_pub, $this->visibility)) { - unset($this->data['mobile']); - } + $this->visibility->setLevel($visibility); } /** Determine whether an item with visibility $visibility can be displayed @@ -305,16 +413,43 @@ class Profile */ public function isVisible($visibility) { - return in_array($visibility, $this->visibility); + return $this->visibility->isVisible($visibility); } - public static function getCompatibleVisibilities($visibility) + /** Stores the list of fields which have already been fetched for this Profile + */ + public function setFetchedFields($fields) { - return self::$v_values[$visibility]; + if (($fields | self::FETCH_ALL) != self::FETCH_ALL) { + Platal::page()->kill("Invalid fetched fields: $fields"); + } + + $this->fetched_fields = $fields; } - private function getProfileField($cls) + private function fetched($field) { + if (!array_key_exists($field, ProfileField::$fields)) { + Platal::page()->kill("Invalid field: $field"); + } + + return ($this->fetched_fields & $field); + } + + /** If not already done, fetches data for the given field + * @param $field One of the Profile::FETCH_* + * @return A ProfileField, or null + */ + private function getProfileField($field) + { + if ($this->fetched($field)) { + return null; + } else { + $this->fetched_fields = $this->fetched_fields | $field; + } + + $cls = ProfileField::$fields[$field]; + return ProfileField::getForPID($cls, $this->id(), $this->visibility); } @@ -339,23 +474,19 @@ class Profile /* Photo */ - private $_photo = null; + private $photo = null; public function getPhoto($fallback = true, $data = false) { - if ($data && $this->has_photo && $this->isVisible($this->photo_pub) && - ($this->_photo == null || $this->_photo->mimeType() == null)) { - $res = XDB::fetchOneAssoc('SELECT attach, attachmime, x, y - FROM profile_photos - WHERE pid = {?}', $this->pid); - $this->_photo = PlImage::fromData($res['attach'], $res['attachmime'], $res['x'], $res['y']); - } - - if (!$data && $this->_photo == null) { - $this->_photo = PlImage::fromData(null, null, $this->photo_width, $this->photo_height); - } - - if ($this->has_photo && $this->isVisible($this->photo_pub)) { - return $this->_photo; + if ($this->has_photo) { + if ($data && ($this->photo == null || $this->photo->mimeType == null)) { + $res = XDB::fetchOneAssoc('SELECT attach, attachmime, x, y + FROM profile_photos + WHERE pid = {?}', $this->pid); + $this->photo = PlImage::fromData($res['attach'], $res['attachmime'], $res['x'], $res['y']); + } else if ($this->photo == null) { + $this->photo = PlImage::fromData(null, null, $this->photo_width, $this->photo_height); + } + return $this->photo; } else if ($fallback) { return PlImage::fromFile(dirname(__FILE__).'/../htdocs/images/none.png', 'image/png'); @@ -374,8 +505,11 @@ class Profile public function getAddresses($flags, $limit = null) { - if ($this->addresses == null) { - $this->setAddresses($this->getProfileField('ProfileAddresses')); + if ($this->addresses == null && !$this->fetched(self::FETCH_ADDRESSES)) { + $addr = $this->getProfileField(self::FETCH_ADDRESSES); + if ($addr) { + $this->setAddresses($addr); + } } if ($this->addresses == null) { @@ -410,8 +544,8 @@ class Profile public function getPhones($flags, $limit = null) { - if ($this->phones == null) { - $this->setPhones($this->getProfileField('ProfilePhones')); + if ($this->phones == null && !$this->fetched(self::FETCH_PHONES)) { + $this->setPhones($this->getProfileField(self::FETCH_PHONES)); } if ($this->phones == null) { @@ -430,8 +564,8 @@ class Profile public function getEducations($flags, $limit = null) { - if ($this->educations == null) { - $this->setEducations($this->getProfileField('ProfileEducation')); + if ($this->educations == null && !$this->fetched(self::FETCH_EDU)) { + $this->setEducations($this->getProfileField(self::FETCH_EDU)); } if ($this->educations == null) { @@ -455,8 +589,8 @@ class Profile public function getCorps() { - if ($this->corps == null) { - $this->setCorps($this->getProfileField('ProfileCorps')); + if ($this->corps == null && !$this->fetched(self::FETCH_CORPS)) { + $this->setCorps($this->getProfileField(self::FETCH_CORPS)); } return $this->corps; } @@ -471,8 +605,11 @@ class Profile public function getNetworking($flags, $limit = null) { - if ($this->networks == null) { - $this->setNetworking($this->getProfileField('ProfileNetworking')); + if ($this->networks == null && !$this->fetched(self::FETCH_NETWORKING)) { + $nw = $this->getProfileField(self::FETCH_NETWORKING); + if ($nw) { + $this->setNetworking($nw); + } } if ($this->networks == null) { return array(); @@ -487,7 +624,7 @@ class Profile return null; } $site = array_pop($site); - return $site['address']; + return $site; } @@ -502,8 +639,11 @@ class Profile public function getJobs($flags, $limit = null) { - if ($this->jobs == null) { - $this->setJobs($this->getProfileField('ProfileJobs')); + if ($this->jobs == null && !$this->fetched(self::FETCH_JOBS)) { + $jobs = $this->getProfileField(self::FETCH_JOBS); + if ($jobs) { + $this->setJobs($jobs); + } } if ($this->jobs == null) { @@ -521,20 +661,68 @@ class Profile return array_pop($job); } + /* Mentoring + */ + private $mentor_sectors = null; + public function setMentoringSectors(ProfileMentoringSectors $sectors) + { + $this->mentor_sectors = $sectors; + } + + public function getMentoringSectors() + { + if ($this->mentor_sectors == null && !$this->fetched(self::FETCH_MENTOR_SECTOR)) { + $this->setMentoringSectors($this->getProfileField(self::FETCH_MENTOR_SECTOR)); + } + + if ($this->mentor_sectors == null) { + return array(); + } else { + return $this->mentor_sectors->sectors; + } + } + + private $mentor_countries = null; + public function setMentoringCountries(ProfileMentoringCountries $countries) + { + $this->mentor_countries = $countries; + } + + public function getMentoringCountries() + { + if ($this->mentor_countries == null && !$this->fetched(self::FETCH_MENTOR_COUNTRY)) { + $this->setMentoringCountries($this->getProfileField(self::FETCH_MENTOR_COUNTRY)); + } + + if ($this->mentor_countries == null) { + return array(); + } else { + return $this->mentor_countries->countries; + } + } + /* Binets */ public function getBinets() { - return XDB::fetchColumn('SELECT binet_id - FROM profile_binets - WHERE pid = {?}', $this->id()); + if ($this->visibility->isVisible(ProfileVisibility::VIS_PRIVATE)) { + return XDB::fetchColumn('SELECT binet_id + FROM profile_binets + WHERE pid = {?}', $this->id()); + } else { + return array(); + } } public function getBinetsNames() { - return XDB::fetchColumn('SELECT text - FROM profile_binets AS pb - LEFT JOIN profile_binet_enum AS pbe ON (pbe.id = pb.binet_id) - WHERE pb.pid = {?}', $this->id()); + if ($this->visibility->isVisible(ProfileVisibility::VIS_PRIVATE)) { + return XDB::fetchColumn('SELECT text + FROM profile_binets AS pb + LEFT JOIN profile_binet_enum AS pbe ON (pbe.id = pb.binet_id) + WHERE pb.pid = {?}', $this->id()); + } else { + return array(); + } } /* Medals @@ -547,8 +735,8 @@ class Profile public function getMedals() { - if ($this->medals == null) { - $this->setMedals($this->getProfileField('ProfileMedals')); + if ($this->medals == null && !$this->fetched(self::FETCH_MEDALS)) { + $this->setMedals($this->getProfileField(self::FETCH_MEDALS)); } if ($this->medals == null) { return array(); @@ -556,11 +744,6 @@ class Profile return $this->medals->medals; } - public function owner() - { - return User::getSilent($this); - } - public function compareNames($firstname, $lastname) { $_lastname = mb_strtoupper($this->lastName()); @@ -592,14 +775,21 @@ class Profile $order = ''; } + $visibility = new ProfileVisibility($visibility); - $it = XDB::Iterator('SELECT p.*, p.sex = \'female\' AS sex, pe.entry_year, pe.grad_year, pse.text AS section, + $it = XDB::Iterator('SELECT p.pid, p.hrpid, p.xorg_id, p.ax_id, p.birthdate, p.birthdate_ref, + p.next_birthday, p.deathdate, p.deathdate_rec, p.sex = \'female\' AS sex, + p.cv, p.medals_pub, p.alias_pub, p.email_directory, p.last_change, + p.nationality1, p.nationality2, p.nationality3, + IF (p.freetext_pub IN {?}, p.freetext, NULL) AS freetext, + pe.entry_year, pe.grad_year, + IF ({?} IN {?}, pse.text, NULL) AS section, 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.attach IS NOT NULL AS has_photo, ph.pub AS photo_pub, + pd.directory_name, IF(pp.pub IN {?}, pp.display_tel, NULL) AS mobile, + (ph.pub IN {?} AND ph.attach IS NOT NULL) AS has_photo, ph.x AS photo_width, ph.y AS photo_height, p.last_change < DATE_SUB(NOW(), INTERVAL 365 DAY) AS is_old, pm.expertise AS mentor_expertise, @@ -622,9 +812,14 @@ class Profile LEFT JOIN profile_photos AS ph ON (ph.pid = p.pid) LEFT JOIN profile_mentor AS pm ON (pm.pid = 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) . ' + WHERE p.pid IN {?} GROUP BY p.pid - ' . $order); + ' . $order, + $visibility->levels(), + ProfileVisibility::VIS_PRIVATE, $visibility->levels(), + $visibility->levels(), $visibility->levels(), + $pids + ); return new ProfileIterator($it, $pids, $fields, $visibility); } @@ -665,7 +860,9 @@ class Profile public static function get($login, $fields = 0x0000, $visibility = null) { if (is_array($login)) { - return new Profile($login); + $pf = new Profile($login); + $pf->setVisibilityLevel($visibility); + return $pf; } $pid = self::getPID($login); if (!is_null($pid)) { @@ -696,7 +893,7 @@ class Profile /** Return profiles for the list of pids. */ - public static function getBulkProfilesWithPIDs(array $pids, $fields = self::FETCH_ADDRESSES, $visibility = null) + public static function getBulkProfilesWithPIDs(array $pids, $fields = 0x0000, $visibility = null) { if (count($pids) == 0) { return array(); @@ -755,7 +952,7 @@ class Profile WHERE n.pid = {?}", $pid); - foreach ($keys as $i => $key) { + while ($key = $keys->next()) { if ($key['name'] == '') { continue; } @@ -829,12 +1026,18 @@ class ProfileIterator implements PlIterator { private $iterator = null; private $fields; + private $visibility; - public function __construct(PlIterator $it, array $pids, $fields = 0x0000, $visibility = null) + public function __construct(PlIterator $it, array $pids, $fields = 0x0000, ProfileVisibility $visibility = null) { require_once 'profilefields.inc.php'; - $visibility = Profile::getVisibilityContext($visibility); + + if ($visibility == null) { + $visibility = new ProfileVisibility(); + } + $this->fields = $fields; + $this->visibility = $visibility; $subits = array(); $callbacks = array(); @@ -881,14 +1084,17 @@ class ProfileIterator implements PlIterator $this->iterator = PlIteratorUtils::parallelIterator($subits, $callbacks, 0); } - private function hasData($flag, $vals) + private function hasData($field, $vals) { - return ($this->fields & $flag) && ($vals[$flag] != null); + return ($this->fields & $field) && ($vals[$field] != null); } private function fillProfile(array $vals) { $pf = Profile::get($vals[0]); + $pf->setVisibilityLevel($this->visibility->level()); + $pf->setFetchedFields($this->fields); + if ($this->hasData(Profile::FETCH_PHONES, $vals)) { $pf->setPhones($vals[Profile::FETCH_PHONES]); }