From 38a86f60ef2563469ac50ed1cc435d1ac554ff68 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Barrois?= Date: Tue, 14 Jun 2011 01:25:28 +0200 Subject: [PATCH] Update the ProfileVisibility class. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit A ProfileVisibility is now 'immutable'; use '->restrict(new_level)' if you need to use a different visibility level. Signed-off-by: Raphaël Barrois --- classes/profile.php | 58 +++++++++++----------- classes/profilevisibility.php | 92 +++++++++++++++++++++-------------- classes/user.php | 48 ++++++++++++++++++ classes/userfilter.php | 19 +++----- classes/userfilter/conditions.inc.php | 8 +-- include/userset.inc.php | 2 +- include/vcard.inc.php | 2 +- 7 files changed, 144 insertions(+), 85 deletions(-) diff --git a/classes/profile.php b/classes/profile.php index b7a190c..d004321 100644 --- a/classes/profile.php +++ b/classes/profile.php @@ -160,12 +160,15 @@ class Profile implements PlExportable private $visibility = null; - private function __construct(array $data) + private function __construct(array $data, ProfileVisibility $visibility = null) { $this->data = $data; $this->pid = $this->data['pid']; $this->hrpid = $this->data['hrpid']; - $this->visibility = new ProfileVisibility(); + if ($visibility == null) { + $visibility = ProfileVisibility::defaultForRead(); + } + $this->visibility = $visibility; } public function id() @@ -485,15 +488,6 @@ class Profile implements PlExportable $this->id()); } - /** Sets the level of visibility of the profile - * Sets $this->visibility to a list of valid visibilities. - * @param one of the self::VIS_* values - */ - public function setVisibilityLevel($visibility) - { - $this->visibility->setLevel($visibility); - } - /** Determine whether an item with visibility $visibility can be displayed * with the current level of visibility of the profile * @param $visibility The level of visibility to be checked @@ -959,7 +953,7 @@ class Profile implements PlExportable ); } - private static function fetchProfileData(array $pids, $respect_order = true, $fields = 0x0000, $visibility = null) + private static function fetchProfileData(array $pids, $respect_order = true, $fields = 0x0000, ProfileVisibility $visibility = null) { if (count($pids) == 0) { return null; @@ -971,13 +965,15 @@ class Profile implements PlExportable $order = ''; } - $visibility = new ProfileVisibility($visibility); + if ($visibility == null) { + $visibility = ProfileVisibility::defaultForRead(); + } $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, IF ({?}, p.cv, NULL) AS 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, + IF (p.freetext_pub >= {?}, p.freetext, NULL) AS freetext, pe.entry_year, pe.grad_year, pe.promo_year, pe.program, pe.fieldid, IF ({?}, pse.text, NULL) AS section, ppn.firstname_main AS firstname, ppn.lastname_main AS lastname, IF ({?}, pn.name, NULL) AS nickname, @@ -985,8 +981,8 @@ class Profile implements PlExportable IF (ppn.lastname_ordinary = \'\', ppn.firstname_main, ppn.lastname_ordinary) AS lastname_ordinary, pd.yourself, pd.promo, pd.short_name, pd.public_name AS full_name, pd.directory_name, pd.public_name, pd.private_name, - IF (pp.pub IN {?}, pp.display_tel, NULL) AS mobile, - (ph.pub IN {?} AND ph.attach IS NOT NULL) AS has_photo, + IF (pp.pub >= {?}, pp.display_tel, NULL) AS mobile, + (ph.pub >= {?} 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, @@ -1007,11 +1003,11 @@ class Profile implements PlExportable GROUP BY p.pid ' . $order, $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // CV - $visibility->levels(), // freetext + $visibility->level(), // freetext $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // section $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // nickname - $visibility->levels(), // mobile - $visibility->levels(), // photo + $visibility->level(), // mobile + $visibility->level(), // photo $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // deltaten_message $pids ); @@ -1052,11 +1048,14 @@ class Profile implements PlExportable /** Return the profile associated with the given login. */ - public static function get($login, $fields = 0x0000, $visibility = null) + public static function get($login, $fields = 0x0000, ProfileVisibility $visibility = null) { + if ($visibility == null) { + $visibility = ProfileVisibility::defaultForRead(); + } + if (is_array($login)) { - $pf = new Profile($login); - $pf->setVisibilityLevel($visibility); + $pf = new Profile($login, $visibility); return $pf; } $pid = self::getPID($login); @@ -1076,19 +1075,19 @@ class Profile implements PlExportable } } - public static function iterOverUIDs($uids, $respect_order = true, $fields = 0x0000, $visibility = null) + public static function iterOverUIDs($uids, $respect_order = true, $fields = 0x0000, ProfileVisibility $visibility = null) { return self::iterOverPIDs(self::getPIDsFromUIDs($uids), $respect_order, $fields, $visibility); } - public static function iterOverPIDs($pids, $respect_order = true, $fields = 0x0000, $visibility = null) + public static function iterOverPIDs($pids, $respect_order = true, $fields = 0x0000, ProfileVisibility $visibility = null) { return self::fetchProfileData($pids, $respect_order, $fields, $visibility); } /** Return profiles for the list of pids. */ - public static function getBulkProfilesWithPIDs(array $pids, $fields = 0x0000, $visibility = null) + public static function getBulkProfilesWithPIDs(array $pids, $fields = 0x0000, ProfileVisibility $visibility = null) { if (count($pids) == 0) { return array(); @@ -1103,12 +1102,12 @@ class Profile implements PlExportable /** Return profiles for uids. */ - public static function getBulkProfilesWithUIDS(array $uids, $fields = 0x000, $visibility = null) + public static function getBulkProfilesWithUIDS(array $uids, $fields = 0x000, ProfileVisibility $visibility = null) { if (count($uids) == 0) { return array(); } - return self::getBulkProfilesWithPIDs(self::getPIDsFromUIDs($uids), $fields, $visibility); + return self::getBulkProfilesWithPIDs(self::getPIDsFromUIDs($uids), $fields, ProfileVisibility $visibility); } public static function isDisplayName($name) @@ -1276,7 +1275,7 @@ class ProfileIterator implements PlIterator require_once 'profilefields.inc.php'; if ($visibility == null) { - $visibility = new ProfileVisibility(); + $visibility = ProfileVisibility::defaultForRead(); } $this->fields = $fields; @@ -1307,8 +1306,7 @@ class ProfileIterator implements PlIterator private function fillProfile(array $vals) { - $pf = Profile::get($vals[0]); - $pf->setVisibilityLevel($this->visibility->level()); + $pf = Profile::get($vals[0], $this->visibility); $pf->setFetchedFields($this->fields); if ($this->hasData(Profile::FETCH_PHONES, $vals)) { diff --git a/classes/profilevisibility.php b/classes/profilevisibility.php index cf5687d..9d870ea 100644 --- a/classes/profilevisibility.php +++ b/classes/profilevisibility.php @@ -21,72 +21,90 @@ class ProfileVisibility { - 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)); - + /** Visibility levels. + * none => Can't see anything + * public => Can see public data + * ax => Can see AX and public data + * private => Can see private, AX and public data + * hidden => Can only be seen by admins + */ + const VIS_NONE = 'none'; const VIS_PUBLIC = 'public'; const VIS_AX = 'ax'; const VIS_PRIVATE = 'private'; + const VIS_HIDDEN = 'hidden'; private $level; - public function __construct($level = null, $force = false) + static private $v_levels = array( + self::VIS_NONE => 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), + self::VIS_HIDDEN => array(self::VIS_HIDDEN, self::VIS_PRIVATE, self::VIS_AX, self::VIS_PUBLIC), + ); + + public function __construct($level = null) { - if ($force) { - $this->forceLevel($level); - } else { - $this->setLevel($level); - } + $this->level = $level; } - public function setLevel($level = self::VIS_PUBLIC) + public function level() { - if ($level != null && $level != self::VIS_PRIVATE && $level != self::VIS_AX && $level != self::VIS_PUBLIC) { - Platal::page()->kill("Invalid visibility: " . $level); + if ($this->level == null) { + return self::VIS_PUBLIC; + } else { + return $this->level; } + } - // Unlogged or not allowed to view directory_ax or requesting public - // => public view - if (!S::logged() || !S::user()->checkPerms('directory_ax') || $level == self::VIS_PUBLIC) { - $level = self::VIS_PUBLIC; - // Not allowed to view directory_private or requesting ax - } else if (!S::user()->checkPerms('directory_private') || $level == self::VIS_AX) { - $level = self::VIS_AX; + public static function defaultForRead($max_level = null) + { + if (!S::logged()) { + $vis = new ProfileVisibility(self::VIS_PUBLIC); } else { - $level = self::VIS_PRIVATE; + $vis = S::user()->readVisibility(); } - - if ($this->level == null || $this->level == self::VIS_PRIVATE) { - $this->level = $level; - } else if ($this->level == self::VIS_AX && $level == self::VIS_PRIVATE) { - return; + if ($max_level != null) { + return $vis->restrict($max_level); } else { - $this->level = self::VIS_PUBLIC; + return $vis; } } - public function forceLevel($level) + public static function defaultForEdit($max_level = null) { - if ($level != self::VIS_PRIVATE && $level != self::VIS_AX && $level != self::VIS_PUBLIC) { - Platal::page()->kill('Invalid visibility: ' . $level); + if (!S::logged()) { + $vis = new ProfileVisibility(self::VIS_NONE); + } else { + $vis = S::user()->editVisibility(); + } + if ($max_level != null) { + return $vis->restrict($max_level); + } else { + return $vis; } - - $this->level = $level; } - public function level() + /** Retrieve a 'restricted' version of the current ProfileVisibility. + * + * @param $level The visibility level to restrict to + * @return A new ProfileVisibility instance, whose level is min($this->level, $level) + */ + public function restrict($level = null) { - if ($this->level == null) { - return self::VIS_PUBLIC; + if ($level != null && !$this->isVisible($level)) { + $level = $this->level(); } else { - return $this->level; + $level = $this->level(); } + + return new ProfileVisibility($level); } public function levels() { - return self::$v_values[$this->level()]; + return self::$v_levels[$this->level()]; } public function isVisible($visibility) diff --git a/classes/user.php b/classes/user.php index f24a8dc..b7ac5f2 100644 --- a/classes/user.php +++ b/classes/user.php @@ -225,6 +225,54 @@ class User extends PlUser $this->perm_flags = null; } + /** Retrieve the 'general' read visibility. + * This is the maximum level of fields that may be viewed by the current user on other profiles. + * + * Rules are: + * - Everyone can view 'public' + * - directory_ax gives access to 'AX' level + * - directory_private gives access to 'private' level + * - admin gives access to 'hidden' level + */ + public function readVisibility() + { + $level = ProfileVisibility::VIS_NONE; + if ($this->is_admin) { + $level = ProfileVisibility::VIS_HIDDEN; + } elseif ($this->checkPerms('directory_private')) { + $level = ProfileVisibility::VIS_PRIVATE; + } elseif ($this->checkPerms('directory_ax')) { + $level = ProfileVisibility::VIS_AX; + } else { + $level = ProfileVisibility::VIS_PUBLIC; + } + return new ProfileVisibility($level); + } + + /** Retrieve the 'general' edit visibility. + * This is the maximum level of fields that may be edited by the current user on other profiles. + * + * Rules are: + * - Only admins can edit the 'hidden' fields + * - If someone has 'directory_edit' and 'directory_ax': AX level + * - If someone has 'directory_edit' and 'directory_private': Private level + * - Otherwise, nothing. + */ + public function editVisibility() + { + $level = ProfileVisibility::VIS_NONE; + if ($this->is_admin) { + $level = ProfileVisibility::VIS_HIDDEN; + } elseif ($this->checkPerms('directory_edit')) { + if ($this->checkPerms('directory_ax')) { + $level = ProfileVisibility::VIS_AX; + } elseif ($this->checkPerms('directory_private')) { + $level = ProfileVisibility::VIS_PRIVATE; + } + } + return new ProfileVisibility($level); + } + // We do not want to store the password in the object. // So, fetch it 'on demand' public function password() diff --git a/classes/userfilter.php b/classes/userfilter.php index 21fc1bf..bbaceba 100644 --- a/classes/userfilter.php +++ b/classes/userfilter.php @@ -117,12 +117,12 @@ class UserFilter extends PlFilter } // This will set the visibility to the default correct level. - $this->profile_visibility = new ProfileVisibility(); + $this->profile_visibility = ProfileVisibility::defaultForRead(); } - public function getVisibilityLevels() + public function isVisible($level) { - return $this->profile_visibility->levels(); + return $this->profile_visibility->isVisible($level); } public function getVisibilityLevel() @@ -130,14 +130,9 @@ class UserFilter extends PlFilter return $this->profile_visibility->level(); } - public function restrictVisibilityTo($level) - { - $this->profile_visibility->setLevel($level); - } - public function getVisibilityCondition($field) { - return $field . ' IN ' . XDB::formatArray($this->getVisibilityLevels()); + return XDB::format($field . ' >= {?}', $this->getVisibilityLevel()); } private function buildQuery() @@ -393,12 +388,12 @@ class UserFilter extends PlFilter return User::iterOverUIDs($this->getUIDs($limit)); } - public function getProfiles($limit = null, $fields = 0x0000, $visibility = null) + public function getProfiles($limit = null, $fields = 0x0000, ProfileVisibility $visibility = null) { return Profile::getBulkProfilesWithPIDs($this->getPIDs($limit), $fields, $visibility); } - public function getProfile($pos = 0, $fields = 0x0000, $visibility = null) + public function getProfile($pos = 0, $fields = 0x0000, ProfileVisibility $visibility = null) { $pid = $this->getPID($pos); if ($pid == null) { @@ -408,7 +403,7 @@ class UserFilter extends PlFilter } } - public function iterProfiles($limit = null, $fields = 0x0000, $visibility = null) + public function iterProfiles($limit = null, $fields = 0x0000, ProfileVisibility $visibility = null) { return Profile::iterOverPIDs($this->getPIDs($limit), true, $fields, $visibility); } diff --git a/classes/userfilter/conditions.inc.php b/classes/userfilter/conditions.inc.php index 4070c3f..ab7503e 100644 --- a/classes/userfilter/conditions.inc.php +++ b/classes/userfilter/conditions.inc.php @@ -920,7 +920,7 @@ class UFC_Binet extends UserFilterCondition public function buildCondition(PlFilter $uf) { // Binets are private. - if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) { + if (!$uf->isVisible(ProfileVisibility::VIS_PRIVATE)) { return self::COND_TRUE; } $sub = $uf->addBinetsFilter(); @@ -944,7 +944,7 @@ class UFC_Section extends UserFilterCondition public function buildCondition(PlFilter $uf) { // Sections are private. - if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) { + if (!$uf->isVisible(ProfileVisibility::VIS_PRIVATE)) { return self::COND_TRUE; } $uf->requireProfiles(); @@ -1281,14 +1281,14 @@ class UFC_Job_Description extends UserFilterCondition // CV is private => if only CV requested, and not private, // don't do anything. Otherwise restrict to standard job visibility. if ($this->fields == UserFilter::JOB_CV) { - if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) { + if (!$uf->isVisible(ProfileVisibility::VIS_PRIVATE)) { return self::COND_TRUE; } } if ($this->fields & UserFilter::JOB_USERDEFINED) { $conds[] = $jsub . '.description ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description); } - if ($this->fields & UserFilter::JOB_CV && $uf->getVisibilityLevel() == ProfileVisibility::VIS_PRIVATE) { + if ($this->fields & UserFilter::JOB_CV && $uf->isVisible(ProfileVisibility::VIS_PRIVATE)) { $uf->requireProfiles(); $conds[] = 'p.cv ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description); } diff --git a/include/userset.inc.php b/include/userset.inc.php index 1a7e7d7..75c432d 100644 --- a/include/userset.inc.php +++ b/include/userset.inc.php @@ -424,7 +424,7 @@ class AddressesView implements PlView public function apply(PlPage $page) { $pids = $this->set->getIds(new PlLimit()); - $visibility = new ProfileVisibility(ProfileVisibility::VIS_AX); + $visibility = ProfileVisibility::defaultForRead(ProfileVisibility::VIS_AX); pl_cached_content_headers('text/x-csv', 1); $csv = fopen('php://output', 'w'); diff --git a/include/vcard.inc.php b/include/vcard.inc.php index de0b49d..ee6ee0c 100644 --- a/include/vcard.inc.php +++ b/include/vcard.inc.php @@ -30,7 +30,7 @@ class VCard extends PlVCard public function __construct($photos = true, $freetext = null) { PlVCard::$folding = false; - $this->visibility = new ProfileVisibility(ProfileVisibility::VIS_PRIVATE); + $this->visibility = ProfileVisibility::defaultForRead(ProfileVisibility::VIS_PRIVATE); $this->freetext = $freetext; $this->photos = $photos; } -- 2.1.4