From 22771578c2d44fe4488546116a84e1561f083ed7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Barrois?= Date: Tue, 5 Jul 2011 23:41:15 +0200 Subject: [PATCH] Refactor Visibility to use a database instead of IN ({?}) queries. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Raphaël Barrois --- classes/address.php | 21 +++-- classes/phone.php | 27 +++--- classes/profile.php | 49 +++++----- classes/profilevisibility.php | 124 -------------------------- classes/user.php | 29 +++--- classes/userfilter.php | 97 +++++++++++++++----- classes/userfilter/conditions.inc.php | 50 ++++------- classes/visibility.php | 163 ++++++++++++++++++++++++++++++++++ include/profilefields.inc.php | 63 +++++++------ include/userset.inc.php | 2 +- include/vcard.inc.php | 2 +- modules/profile.php | 15 ++-- modules/profile/jobs.inc.php | 21 +++-- modules/profile/page.inc.php | 2 +- templates/profile/profile.tpl | 21 +++-- upgrade/1.1.2/06_visibility.sql | 29 ++++-- 16 files changed, 410 insertions(+), 305 deletions(-) delete mode 100644 classes/profilevisibility.php create mode 100644 classes/visibility.php diff --git a/classes/address.php b/classes/address.php index a532c8d..665d91d 100644 --- a/classes/address.php +++ b/classes/address.php @@ -575,7 +575,7 @@ class Address public function format() { $this->text = trim($this->text); - $this->phones = Phone::formatFormArray($this->phones, $this->error, new ProfileVisibility($this->pub)); + $this->phones = Phone::formatFormArray($this->phones, $this->error, $this->pub); if ($this->removed == 1) { if (!S::user()->checkPerms('directory_private') && Phone::hasPrivate($this->phones)) { Platal::page()->trigWarning("L'adresse ne peut être supprimée car elle contient des informations pour lesquelles vous n'avez le droit d'édition."); @@ -826,7 +826,7 @@ class Address // addresses before secondary addresses. static private function compare(array $a, array $b) { - $value = ProfileVisibility::comparePublicity($a, $b); + $value = Visibility::comparePublicity($a, $b); if ($value == 0) { if ($a['secondary'] != $b['secondary']) { $value = $a['secondary'] ? 1 : -1; @@ -878,9 +878,9 @@ class Address } static public function iterate(array $pids = array(), array $types = array(), - array $jobids = array(), array $pubs = array()) + array $jobids = array(), Visibility $visibility) { - return new AddressIterator($pids, $types, $jobids, $pubs); + return new AddressIterator($pids, $types, $jobids, $visibility); } } @@ -895,7 +895,7 @@ class AddressIterator implements PlIterator { private $dbiter; - public function __construct(array $pids, array $types, array $jobids, array $pubs) + public function __construct(array $pids, array $types, array $jobids, Visibility $visibility) { $where = array(); if (count($pids) != 0) { @@ -907,9 +907,11 @@ class AddressIterator implements PlIterator if (count($jobids) != 0) { $where[] = XDB::format('(pa.jobid IN {?})', $jobids); } - if (count($pubs) != 0) { - $where[] = XDB::format('(pa.pub IN {?})', $pubs); + if ($visibility == null) { + $visibility = Visibility::defaultForRead(); } + $where[] = 'pve.best_display_level+0 <= pa.pub+0'; + $sql = 'SELECT pa.pid, pa.jobid, pa.groupid, pa.type, pa.id, pa.flags, pa.text, pa.postalText, pa.pub, pa.comment, pa.types, pa.formatted_address, pa.location_type, pa.partial_match, pa.latitude, pa.longitude, pa.southwest_latitude, pa.southwest_longitude, pa.northeast_latitude, pa.northeast_longitude, @@ -924,10 +926,11 @@ class AddressIterator implements PlIterator LEFT JOIN profile_addresses_components_enum AS pace2 ON (FIND_IN_SET(\'locality\', pace2.types) AND pace2.id = pc.component_id) LEFT JOIN profile_addresses_components_enum AS pace3 ON (FIND_IN_SET(\'administrative_area_level_1\', pace3.types) AND pace3.id = pc.component_id) LEFT JOIN profile_addresses_components_enum AS pace4 ON (FIND_IN_SET(\'country\', pace4.types) AND pace4.id = pc.component_id) - ' . ((count($where) > 0) ? 'WHERE ' . implode(' AND ', $where) : '') . ' + LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?}) + WHERE ' . implode(' AND ', $where) . ' GROUP BY pa.pid, pa.jobid, pa.groupid, pa.type, pa.id ORDER BY pa.pid, pa.jobid, pa.id'; - $this->dbiter = XDB::iterator($sql); + $this->dbiter = XDB::iterator($sql, $visibility->level()); } public function next() diff --git a/classes/phone.php b/classes/phone.php index 4a16ca9..0cb0703 100644 --- a/classes/phone.php +++ b/classes/phone.php @@ -333,17 +333,17 @@ class Phone $success = (!$phone->error && ($phone->format() || $phone->isEmpty()) && $success); if (!$phone->isEmpty()) { // Restrict phone visibility to $maxPublicity - if (!is_null($maxPublicity) && $maxPublicity->isVisible($phone->pub)) { - $phone->pub = $maxPublicity->level(); + if (!is_null($maxPublicity) && Visibility::isLessRestrictive($phone->pub, $maxPublicity)) { + $phone->pub = $maxPublicity; } $phones[] = call_user_func(array($phone, $function)); } } if (count($phones) == 0 && $requiresEmptyPhone) { $phone = new Phone(); - if (!is_null($maxPublicity) && $maxPublicity->isVisible($phone->pub)) { + if (!is_null($maxPublicity) && Visibility::isLessRestrictive($phone->pub, $maxPublicity)) { // Restrict phone visibility to $maxPublicity - $phone->pub = $maxPublicity->level(); + $phone->pub = $maxPublicity; } $phones[] = call_user_func(array($phone, $function)); } @@ -354,7 +354,7 @@ class Phone static public function formatFormArray(array $data, &$success = true, $maxPublicity = null) { $phones = self::formArrayWalk($data, 'toFormArray', $success, true, $maxPublicity); - usort($phones, 'ProfileVisibility::comparePublicity'); + usort($phones, 'Visibility::comparePublicity'); return $phones; } @@ -374,9 +374,9 @@ class Phone } static public function iterate(array $pids = array(), array $link_types = array(), - array $link_ids = array(), array $pubs = array()) + array $link_ids = array(), Visibility $visibility) { - return new PhoneIterator($pids, $link_types, $link_ids, $pubs); + return new PhoneIterator($pids, $link_types, $link_ids, $visibility); } } @@ -391,7 +391,7 @@ class PhoneIterator implements PlIterator { private $dbiter; - public function __construct(array $pids, array $link_types, array $link_ids, array $pubs) + public function __construct(array $pids, array $link_types, array $link_ids, Visibility $visibility) { $where = array(); if (count($pids) != 0) { @@ -403,15 +403,18 @@ class PhoneIterator implements PlIterator if (count($link_ids) != 0) { $where[] = XDB::format('(link_id IN {?})', $link_ids); } - if (count($pubs) != 0) { - $where[] = XDB::format('(pub IN {?})', $pubs); + if ($visibility == null) { + $visibility = Visibility::defaultForRead(); } + $where[] = 'pve.best_display_level+0 <= pub+0'; + $sql = 'SELECT search_tel AS search, display_tel AS display, comment, link_id, tel_type AS type, link_type, tel_id AS id, pid, pub FROM profile_phones - ' . ((count($where) > 0) ? 'WHERE ' . implode(' AND ', $where) : '') . ' + LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?}) + WHERE ' . implode(' AND ', $where) . ' ORDER BY pid, link_id, tel_id'; - $this->dbiter = XDB::iterator($sql); + $this->dbiter = XDB::iterator($sql, $visibility->level()); } public function next() diff --git a/classes/profile.php b/classes/profile.php index b5456fe..6b06231 100644 --- a/classes/profile.php +++ b/classes/profile.php @@ -160,14 +160,11 @@ class Profile implements PlExportable private $visibility = null; - private function __construct(array $data, ProfileVisibility $visibility = null) + private function __construct(array $data, Visibility $visibility) { $this->data = $data; $this->pid = $this->data['pid']; $this->hrpid = $this->data['hrpid']; - if ($visibility == null) { - $visibility = ProfileVisibility::defaultForRead(); - } $this->visibility = $visibility; } @@ -387,7 +384,7 @@ class Profile implements PlExportable public function displayEmail() { $o = $this->owner(); - if ($o != null && $this->isVisible(ProfileVisibility::VIS_PRIVATE)) { + if ($o != null && $this->isVisible(Visibility::EXPORT_PRIVATE)) { return $o->bestEmail(); } else { return $this->email_directory; @@ -877,7 +874,7 @@ class Profile implements PlExportable */ public function getBinets() { - if ($this->visibility->isVisible(ProfileVisibility::VIS_PRIVATE)) { + if ($this->visibility->isVisible(Visibility::EXPORT_PRIVATE)) { return XDB::fetchColumn('SELECT binet_id FROM profile_binets WHERE pid = {?}', $this->id()); @@ -887,7 +884,7 @@ class Profile implements PlExportable } public function getBinetsNames() { - if ($this->visibility->isVisible(ProfileVisibility::VIS_PRIVATE)) { + if ($this->visibility->isVisible(Visibility::EXPORT_PRIVATE)) { return XDB::fetchColumn('SELECT text FROM profile_binets AS pb LEFT JOIN profile_binet_enum AS pbe ON (pbe.id = pb.binet_id) @@ -953,7 +950,7 @@ class Profile implements PlExportable ); } - private static function fetchProfileData(array $pids, $respect_order = true, $fields = 0x0000, ProfileVisibility $visibility = null) + private static function fetchProfileData(array $pids, $respect_order = true, $fields = 0x0000, $visibility = null) { if (count($pids) == 0) { return null; @@ -965,8 +962,8 @@ class Profile implements PlExportable $order = ''; } - if ($visibility == null) { - $visibility = ProfileVisibility::defaultForRead(); + if ($visibility === null) { + $visibility = Visibility::defaultForRead(); } $it = XDB::Iterator('SELECT p.pid, p.hrpid, p.xorg_id, p.ax_id, p.birthdate, p.birthdate_ref, @@ -1002,13 +999,13 @@ class Profile implements PlExportable WHERE p.pid IN {?} GROUP BY p.pid ' . $order, - $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // CV + $visibility->isVisible(Visibility::EXPORT_PRIVATE), // CV $visibility->level(), // freetext - $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // section - $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // nickname + $visibility->isVisible(Visibility::EXPORT_PRIVATE), // section + $visibility->isVisible(Visibility::EXPORT_PRIVATE), // nickname $visibility->level(), // mobile $visibility->level(), // photo - $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // deltaten_message + $visibility->isVisible(Visibility::EXPORT_PRIVATE), // deltaten_message $pids ); return new ProfileIterator($it, $pids, $fields, $visibility); @@ -1048,10 +1045,10 @@ class Profile implements PlExportable /** Return the profile associated with the given login. */ - public static function get($login, $fields = 0x0000, ProfileVisibility $visibility = null) + public static function get($login, $fields = 0x0000, $visibility = null) { - if ($visibility == null) { - $visibility = ProfileVisibility::defaultForRead(); + if ($visibility === null) { + $visibility = Visibility::defaultForRead(); } if (is_array($login)) { @@ -1068,26 +1065,26 @@ class Profile implements PlExportable if (!($login instanceof PlUser)) { $user = User::getSilent($login); if ($user && $user->hasProfile()) { - return $user->profile(); + return $user->profile(false, $fields, $visibility); } } return null; } } - public static function iterOverUIDs($uids, $respect_order = true, $fields = 0x0000, ProfileVisibility $visibility = null) + public static function iterOverUIDs($uids, $respect_order = true, $fields = 0x0000, $visibility = null) { return self::iterOverPIDs(self::getPIDsFromUIDs($uids), $respect_order, $fields, $visibility); } - public static function iterOverPIDs($pids, $respect_order = true, $fields = 0x0000, ProfileVisibility $visibility = null) + public static function iterOverPIDs($pids, $respect_order = true, $fields = 0x0000, $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, ProfileVisibility $visibility = null) + public static function getBulkProfilesWithPIDs(array $pids, $fields = 0x0000, $visibility = null) { if (count($pids) == 0) { return array(); @@ -1102,7 +1099,7 @@ class Profile implements PlExportable /** Return profiles for uids. */ - public static function getBulkProfilesWithUIDS(array $uids, $fields = 0x000, ProfileVisibility $visibility = null) + public static function getBulkProfilesWithUIDS(array $uids, $fields = 0x000, $visibility = null) { if (count($uids) == 0) { return array(); @@ -1270,12 +1267,12 @@ class ProfileIterator implements PlIterator const FETCH_ALL = 0x000033F; // FETCH_ADDRESSES | FETCH_CORPS | FETCH_EDU | FETCH_JOBS | FETCH_MEDALS | FETCH_NETWORKING | FETCH_PHONES | FETCH_JOB_TERMS - public function __construct(PlIterator $it, array $pids, $fields = 0x0000, ProfileVisibility $visibility = null) + public function __construct(PlIterator $it, array $pids, $fields = 0x0000, $visibility = null) { require_once 'profilefields.inc.php'; - if ($visibility == null) { - $visibility = ProfileVisibility::defaultForRead(); + if ($visibility === null) { + $visibility = Visibility::defaultForRead(); } $this->fields = $fields; @@ -1306,7 +1303,7 @@ class ProfileIterator implements PlIterator private function fillProfile(array $vals) { - $pf = Profile::get($vals[0], $this->visibility); + $pf = Profile::get($vals[0], 0x0, $this->visibility); $pf->setFetchedFields($this->fields); if ($this->hasData(Profile::FETCH_PHONES, $vals)) { diff --git a/classes/profilevisibility.php b/classes/profilevisibility.php deleted file mode 100644 index 1dd8d6c..0000000 --- a/classes/profilevisibility.php +++ /dev/null @@ -1,124 +0,0 @@ - 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; - - 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) - { - $this->level = $level; - } - - public function level() - { - if ($this->level == null) { - return self::VIS_PUBLIC; - } else { - return $this->level; - } - } - - public static function defaultForRead($max_level = null) - { - if (!S::logged()) { - $vis = new ProfileVisibility(self::VIS_PUBLIC); - } else { - $vis = S::user()->readVisibility(); - } - if ($max_level != null) { - return $vis->restrict($max_level); - } else { - return $vis; - } - } - - public static function defaultForEdit($max_level = null) - { - 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; - } - } - - /** 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 ($level != null && !$this->isVisible($level)) { - $level = $this->level(); - } - - return new ProfileVisibility($level); - } - - public function levels() - { - return self::$v_levels[$this->level()]; - } - - public function isVisible($visibility) - { - return in_array($visibility, $this->levels()); - } - - static public function comparePublicity($a, $b) - { - $a_pub = new ProfileVisibility($a['pub'], true); - $b_pub = new ProfileVisibility($b['pub'], true); - - return !$a_pub->isVisible($b_pub->level()); - } -} - - -// 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 b7ac5f2..8647ddd 100644 --- a/classes/user.php +++ b/classes/user.php @@ -236,17 +236,17 @@ class User extends PlUser */ public function readVisibility() { - $level = ProfileVisibility::VIS_NONE; + $level = Visibility::VIEW_NONE; if ($this->is_admin) { - $level = ProfileVisibility::VIS_HIDDEN; + $level = Visibility::VIEW_ADMIN; } elseif ($this->checkPerms('directory_private')) { - $level = ProfileVisibility::VIS_PRIVATE; + $level = Visibility::VIEW_PRIVATE; } elseif ($this->checkPerms('directory_ax')) { - $level = ProfileVisibility::VIS_AX; + $level = Visibility::VIEW_AX; } else { - $level = ProfileVisibility::VIS_PUBLIC; + $level = Visibility::VIEW_PUBLIC; } - return new ProfileVisibility($level); + return Visibility::get($level); } /** Retrieve the 'general' edit visibility. @@ -254,23 +254,18 @@ class User extends PlUser * * 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 + * - If someone has 'directory_edit' (which is actually directory_ax_edit): AX level * - Otherwise, nothing. */ public function editVisibility() { - $level = ProfileVisibility::VIS_NONE; + $level = Visibility::VIEW_NONE; if ($this->is_admin) { - $level = ProfileVisibility::VIS_HIDDEN; + $level = Visibility::VIEW_ADMIN; } elseif ($this->checkPerms('directory_edit')) { - if ($this->checkPerms('directory_ax')) { - $level = ProfileVisibility::VIS_AX; - } elseif ($this->checkPerms('directory_private')) { - $level = ProfileVisibility::VIS_PRIVATE; - } + $level = Visibility::VIEW_AX; } - return new ProfileVisibility($level); + return Visibility::get($level); } // We do not want to store the password in the object. @@ -368,6 +363,8 @@ class User extends PlUser if (!$this->_profile_fetched || $forceFetch) { $this->_profile_fetched = true; $this->_profile = Profile::get($this, $fields, $visibility); + } else if (!$this->_profile->visibility->equals($visibility)) { + return Profile::get($this, $fields, $visibility); } return $this->_profile; } diff --git a/classes/userfilter.php b/classes/userfilter.php index d392073..2314915 100644 --- a/classes/userfilter.php +++ b/classes/userfilter.php @@ -85,7 +85,9 @@ class UserFilter extends PlFilter private $orderby = null; // Store the current 'search' visibility. - private $profile_visibility = null; + private $visibility = null; + // If the 'search' visibility should be based on a DB field instead. + private $visibility_field = null; private $lastusercount = null; private $lastprofilecount = null; @@ -117,29 +119,50 @@ class UserFilter extends PlFilter } // This will set the visibility to the default correct level. - $this->profile_visibility = ProfileVisibility::defaultForRead(); + $this->visibility = Visibility::defaultForRead(); } - public function isVisible($level) - { - return $this->profile_visibility->isVisible($level); - } - - public function getVisibilityLevel() - { - return $this->profile_visibility->level(); - } - - public function getVisibilityLevels() - { - return $this->profile_visibility->levels(); + /** Get the SQL condition to filter by visibility level for a field. + * This will return a SQL condition which evaluates to True if the given + * field display level is available from the current access level. + * @param $field Name of the field holding a display level + * @return string SQL condition, properly escaped, for that field. + */ + public function getVisibilityConditionForField($field) + { + if ($this->visibility_field != null) { + // Use enum 'bit' arithmetic. + // Display levels are ordered as 'hidden, private, ax, public' + // Thus ax > private. + // The $sub.display_level cell will contain the 'most private' display + // level available based on $field. If it is 'ax' and $field is + // 'private','ax' <= 'private' is false. + $sub = $this->addVisibilityFieldFilter($this->visibility_field); + return $sub . '.best_display_level + 0 <= 0 + ' . $field; + } else { + $sub = $this->addVisibilityAbsoluteFilter($this->visibility->level()); + return $sub . '.best_display_level + 0 <= 0 + ' . $field; + } } - public function getVisibilityCondition($field) + /** Get the SQL condition to filter by a given visibility level. + * @param $level One of Visibility::EXPORT_* + * @return string A SQL condition, properly escaped, which evaluates to 'true' if the $level can be viewed with the current access level. + */ + public function getVisibilityConditionAbsolute($level) { - // Fields are ordered as ('hidden', 'private', 'ax', 'public', 'none') - // Which gives 'ax' >= 'private' - return XDB::format($field . ' IN {?}', $this->getVisibilityLevels()); + if ($this->visibility_field != null) { + // The $sub.display_levels cell will contain allowed display levels + // for an access level of $this->visibility_field. + $sub = $this->addVisibilityFieldFilter($this->visibility_field); + return XDB::format('FIND_IN_SET({?}, ' . $sub . '.display_levels', $level); + } else { + if ($this->visibility->isVisible($level)) { + return 'TRUE'; + } else { + return 'FALSE'; + } + } } private function buildQuery() @@ -395,12 +418,12 @@ class UserFilter extends PlFilter return User::iterOverUIDs($this->getUIDs($limit)); } - public function getProfiles($limit = null, $fields = 0x0000, ProfileVisibility $visibility = null) + public function getProfiles($limit = null, $fields = 0x0000, $visibility = null) { return Profile::getBulkProfilesWithPIDs($this->getPIDs($limit), $fields, $visibility); } - public function getProfile($pos = 0, $fields = 0x0000, ProfileVisibility $visibility = null) + public function getProfile($pos = 0, $fields = 0x0000, $visibility = null) { $pid = $this->getPID($pos); if ($pid == null) { @@ -410,7 +433,7 @@ class UserFilter extends PlFilter } } - public function iterProfiles($limit = null, $fields = 0x0000, ProfileVisibility $visibility = null) + public function iterProfiles($limit = null, $fields = 0x0000, $visibility = null) { return Profile::iterOverPIDs($this->getPIDs($limit), true, $fields, $visibility); } @@ -620,6 +643,36 @@ class UserFilter extends PlFilter return $joins; } + /** VISIBILITY + */ + private $vlevels = array(); + private $vfields = array(); + public function addVisibilityAbsoluteFilter($level) + { + $sub = 'pvel_' . $level; + $this->vlevels[$level] = $sub; + return $sub; + } + + public function addVisibilityFieldFilter($field) + { + $sub = 'pvef_' . self::getDBSuffix($field); + $this->vfields[$field] = $sub; + return $sub; + } + + protected function visibilityJoins() + { + $joins = array(); + foreach ($this->vlevels as $level => $sub) { + $joins[$sub] = PlSqlJoin::inner('profile_visibility_enum', '$ME.access_level = {?}', $level); + } + foreach ($this->vfields as $field => $sub) { + $joins[$sub] = PlSqlJoin::inner('profile_visibility_enum', '$ME.access_level = ' . $field); + } + return $joins; + } + /** PERMISSIONS */ private $at = false; diff --git a/classes/userfilter/conditions.inc.php b/classes/userfilter/conditions.inc.php index 9c361c1..351ad2a 100644 --- a/classes/userfilter/conditions.inc.php +++ b/classes/userfilter/conditions.inc.php @@ -410,7 +410,7 @@ class UFC_Comment extends UserFilterCondition public function buildCondition(PlFilter $uf) { $uf->requireProfiles(); - return $uf->getVisibilityCondition('p.freetext_pub') . ' AND p.freetext ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->text); + return $uf->getVisibilityConditionForField('p.freetext_pub') . ' AND p.freetext ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->text); } public function export() @@ -668,9 +668,7 @@ class UFC_NameTokens extends UserFilterCondition if ($this->general_type) { $c .= XDB::format(' AND ' . $sub . '.general_type = {?}', $this->general_type); } - if (!$uf->isVisible(ProfileVisibility::VIS_PRIVATE)) { - $c .= XDB::format(' AND ' . $sub . '.general_type != \'nickname\''); - } + $c .= ' AND (' . $uf->getVisibilityConditionAbsolute(Visibility::EXPORT_PRIVATE) . ' OR ' . $sub . '.general_type != \'nickname\')'; $conds[] = $c; } @@ -922,12 +920,9 @@ class UFC_Binet extends UserFilterCondition public function buildCondition(PlFilter $uf) { - // Binets are private. - if (!$uf->isVisible(ProfileVisibility::VIS_PRIVATE)) { - return self::COND_TRUE; - } $sub = $uf->addBinetsFilter(); - return XDB::format($sub . '.binet_id IN {?}', $this->val); + // Binets are private. + return XDB::format($uf->getVisibilityConditionAbsolute(Visibility::EXPORT_PRIVATE) . ' AND ' . $sub . '.binet_id IN {?}', $this->val); } } // }}} @@ -947,11 +942,8 @@ class UFC_Section extends UserFilterCondition public function buildCondition(PlFilter $uf) { // Sections are private. - if (!$uf->isVisible(ProfileVisibility::VIS_PRIVATE)) { - return self::COND_TRUE; - } $uf->requireProfiles(); - return XDB::format('p.section IN {?}', $this->section); + return XDB::format($uf->getVisibilityConditionAbsolute(Visibility::EXPORT_PRIVATE) . ' AND p.section IN {?}', $this->section); } } // }}} @@ -1109,7 +1101,7 @@ class UFC_AddressComponent extends UFC_Address public function buildCondition(PlFilter $uf) { $sub = $uf->addAddressFilter($this->fieldtype); - $conds = $this->initConds($sub, $uf->getVisibilityCondition('pa' . $sub . '.pub')); + $conds = $this->initConds($sub, $uf->getVisibilityConditionForField('pa' . $sub . '.pub')); $conds[] = XDB::format('pace' . $sub . '.id IN {?}', $this->val); return implode(' AND ', $conds); @@ -1152,7 +1144,7 @@ class UFC_Corps extends UserFilterCondition } // XXX(x2006barrois): find a way to get rid of that hardcoded // reference to 'pc'. - $cond .= ' AND ' . $uf->getVisibilityCondition('pc.corps_pub'); + $cond .= ' AND ' . $uf->getVisibilityConditionForField('pc.corps_pub'); return $cond; } } @@ -1186,7 +1178,7 @@ class UFC_Corps_Rank extends UserFilterCondition } // XXX(x2006barrois): find a way to get rid of that hardcoded // reference to 'pc'. - $cond .= ' AND ' . $uf->getVisibilityCondition('pc.corps_pub'); + $cond .= ' AND ' . $uf->getVisibilityConditionForField('pc.corps_pub'); return $cond; } } @@ -1224,7 +1216,7 @@ class UFC_Job_Company extends UserFilterCondition $sub = $uf->addJobCompanyFilter(); $cond = $sub . '.' . $this->type . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->value); $jsub = $uf->addJobFilter(); - $cond .= ' AND ' . $uf->getVisibilityCondition($jsub . '.pub'); + $cond .= ' AND ' . $uf->getVisibilityConditionForField($jsub . '.pub'); return $cond; } } @@ -1254,7 +1246,7 @@ class UFC_Job_Terms extends UserFilterCondition $conditions[] = $sub[$i] . '.jtid_1 = ' . XDB::escape($jtid); } $jsub = $uf->addJobFilter(); - $conditions[] = $uf->getVisibilityCondition($jsub . '.pub'); + $conditions[] = $uf->getVisibilityConditionForField($jsub . '.pub'); return implode(' AND ', $conditions); } } @@ -1281,24 +1273,18 @@ class UFC_Job_Description extends UserFilterCondition $conds = array(); $jsub = $uf->addJobFilter(); - // 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->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->isVisible(ProfileVisibility::VIS_PRIVATE)) { + if ($this->fields & UserFilter::JOB_CV) { $uf->requireProfiles(); - $conds[] = 'p.cv ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description); + // CV is private + $conds[] = '( ' . $uf->getVisibilityConditionAbsolute(Visibility::EXPORT_PRIVATE) . ' AND p.cv ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description) . ')'; } if (count($conds) == 0) { return self::COND_TRUE; } - return $uf->getVisibilityCondition($jsub . '.pub') . ' AND ( ' . implode(' OR ', $conds) . ' )'; + return $uf->getVisibilityConditionForField($jsub . '.pub') . ' AND ( ' . implode(' OR ', $conds) . ' )'; } } // }}} @@ -1322,7 +1308,7 @@ class UFC_Networking extends UserFilterCondition { $sub = $uf->addNetworkingFilter(); $conds = array(); - $conds[] = $uf->getVisibilityCondition($sub . '.pub'); + $conds[] = $uf->getVisibilityConditionForField($sub . '.pub'); $conds[] = $sub . '.address ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->value); if ($this->type != -1) { $conds[] = $sub . '.nwid = ' . XDB::format('{?}', $this->type); @@ -1367,7 +1353,7 @@ class UFC_Phone extends UserFilterCondition $sub = $uf->addPhoneFilter(); $conds = array(); - $conds[] = $uf->getVisibilityCondition($sub . '.pub'); + $conds[] = $uf->getVisibilityConditionForField($sub . '.pub'); $conds[] = $sub . '.search_tel = ' . XDB::format('{?}', $this->number); if ($this->num_type != self::NUM_ANY) { @@ -1403,7 +1389,7 @@ class UFC_Medal extends UserFilterCondition // This will require profiles => table 'p' will be available. $sub = $uf->addMedalFilter(); - $conds[] = $uf->getVisibilityCondition('p.medals_pub'); + $conds[] = $uf->getVisibilityConditionForField('p.medals_pub'); $conds[] = $sub . '.mid = ' . XDB::format('{?}', $this->medal); if ($this->grade != null) { @@ -1421,7 +1407,7 @@ class UFC_Photo extends UserFilterCondition public function buildCondition(PlFilter $uf) { $sub = $uf->addPhotoFilter(); - return $sub . '.attach IS NOT NULL AND ' . $uf->getVisibilityCondition($sub . '.pub'); + return $sub . '.attach IS NOT NULL AND ' . $uf->getVisibilityConditionForField($sub . '.pub'); } } // }}} diff --git a/classes/visibility.php b/classes/visibility.php new file mode 100644 index 0000000..dba6578 --- /dev/null +++ b/classes/visibility.php @@ -0,0 +1,163 @@ + array(), + self::VIEW_PUBLIC => array(self::EXPORT_PUBLIC), + self::VIEW_AX => array(self::EXPORT_AX, self::EXPORT_PUBLIC), + self::VIEW_PRIVATE => array(self::EXPORT_PRIVATE, self::EXPORT_AX, self::EXPORT_PUBLIC), + self::VIEW_ADMIN => array(self::EXPORT_HIDDEN, self::EXPORT_PRIVATE, self::EXPORT_AX, self::EXPORT_PUBLIC), + ); + + static private $display_levels = array( + self::EXPORT_PUBLIC => 0, + self::EXPORT_AX => 1, + self::EXPORT_PRIVATE => 2, + self::EXPORT_HIDDEN => 3, + ); + + private $level; + + private function __construct($level) + { + $this->level = $level; + } + + static private $vis_list = array(); + public static function get($level) + { + Platal::assert(array_key_exists($level, self::$view_levels), "Invalid visibility access level $level."); + if (!array_key_exists($level, self::$vis_list)) { + self::$vis_list[$level] = new Visibility($level); + } + return self::$vis_list[$level]; + } + + public function level() + { + return $this->level; + } + + public static function defaultForRead($max_level = null) + { + if (!S::logged()) { + $vis = self::get(self::VIEW_PUBLIC); + } else { + $vis = S::user()->readVisibility(); + } + if ($max_level != null) { + return $vis->restrict($max_level); + } else { + return $vis; + } + } + + public static function defaultForEdit($max_level = null) + { + if (!S::logged()) { + $vis = self::get(self::VIEW_NONE); + } else { + $vis = S::user()->editVisibility(); + } + if ($max_level != null) { + return $vis->restrict($max_level); + } else { + return $vis; + } + } + + /** Retrieve a 'restricted' version of the current Visibility. + * + * @param $level The visibility level to restrict to + * @return A new Visibility instance, whose level is min($this->level, $level) + */ + public function restrict($level = null) + { + if ($level != null && !$this->isVisible($level)) { + $level = $this->level(); + } + + return self::get($level); + } + + public function isVisible($visibility) + { + return in_array($visibility, self::$view_levels[$this->level()]); + } + + public function equals($visibility) + { + return $visibility !== null && $this->level() == $visibility->level(); + } + + static public function isLessRestrictive($level_a, $level_b) + { + // self::$display_levels is order from least restrictive + // to most restrictive. + return self::$display_levels[$a] >= self::$display_levels[$b]; + } + + /** Compare the visibility of two fields. + * Returns: + * >0 if $a is less restrictive than $b, + * <0 if $a is more restrictive than $b, + * 0 if $a is equal to $b. + */ + static public function cmpLessRestrictive($a, $b) + { + $a_pub = self::$display_levels[$a]; + $b_pub = self::$display_levels[$b]; + /* self::$display_levels is ordered from least restrictive to + * most restrictive. + * This will be 0 if both levels are equal, < 0 if $b_pub is less + * than $a_pub, thus less restrictive, which means that $a comes + * before $b in descending restrictiveness order. + */ + return $b_pub - $a_pub; + } + + static public function comparePublicity($a, $b) + { + return self::cmpLessRestrictive($a['pub'], $b['pub']); + } +} + +// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: +?> diff --git a/include/profilefields.inc.php b/include/profilefields.inc.php index 8d4ef1b..6bcf258 100644 --- a/include/profilefields.inc.php +++ b/include/profilefields.inc.php @@ -50,12 +50,12 @@ abstract class ProfileField * * MUST be reimplemented for each kind of ProfileField. */ - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { return PlIteratorUtils::emptyIterator(); } - public static function buildForPID($cls, $pid, ProfileVisibility $visibility) + public static function buildForPID($cls, $pid, Visibility $visibility) { $res = self::buildFromPIDs($cls, array($pid), $visibility); return array_pop($res); @@ -67,7 +67,7 @@ abstract class ProfileField * @param $visibility An array of allowed visibility contexts * @return An array of $pid => ProfileField */ - public static function buildFromPIDs($cls, array $pids, ProfileVisibility $visibility) + public static function buildFromPIDs($cls, array $pids, Visibility $visibility) { $it = new ProfileFieldIterator($cls, $pids, $visibility); $res = array(); @@ -77,7 +77,7 @@ abstract class ProfileField return $res; } - public static function getForPID($cls, $pid, ProfileVisibility $visibility) + public static function getForPID($cls, $pid, Visibility $visibility) { $it = new ProfileFieldIterator($cls, array($pid), $visibility); return $it->next(); @@ -91,7 +91,7 @@ class ProfileFieldIterator implements PlIterator private $data; private $cls; - public function __construct($cls, array $pids, ProfileVisibility $visibility) + public function __construct($cls, array $pids, Visibility $visibility) { if (is_numeric($cls) && isset(ProfileField::$fields[$cls])) { $cls = ProfileField::$fields[$cls]; @@ -333,7 +333,7 @@ class ProfileEducation extends ProfileField return $educations; } - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { $data = XDB::iterator('SELECT pe.id, pe.pid, pe.entry_year, pe.grad_year, pe.program, pe.flags, @@ -368,16 +368,17 @@ class ProfileMedals extends ProfileField } } - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { $data = XDB::iterator('SELECT pm.pid, pm.mid, pm.gid, pme.text, pme.img, pmge.text AS grade FROM profile_medals AS pm LEFT JOIN profiles AS p ON (pm.pid = p.pid) LEFT JOIN profile_medal_enum AS pme ON (pme.id = pm.mid) LEFT JOIN profile_medal_grade_enum AS pmge ON (pmge.mid = pm.mid AND pmge.gid = pm.gid) - WHERE pm.pid IN {?} AND p.medals_pub IN {?} + LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?}) + WHERE pm.pid IN {?} AND pve.best_display_level + 0 <= p.medals_pub + 0 ORDER BY ' . XDB::formatCustomOrder('pm.pid', $pids), - $pids, $visibility->levels()); + $visibility->level(), $pids); return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid')); } @@ -397,15 +398,16 @@ class ProfileNetworking extends ProfileField } } - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { $data = XDB::iterator('SELECT pid, id, address, pne.nwid, pne.network_type, pne.link, pne.name FROM profile_networking AS pn LEFT JOIN profile_networking_enum AS pne USING(nwid) - WHERE pid IN {?} AND pub IN {?} + LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?}) + WHERE pn.pid IN {?} AND pve.best_display_level + 0 <= pn.pub + 0 ORDER BY ' . XDB::formatCustomOrder('pid', $pids) . ', pn.nwid, id', - $pids, $visibility->levels()); + $visibility->level(), $pids); return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid')); } @@ -453,7 +455,7 @@ class ProfileCorps extends ProfileField } } - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { $data = XDB::iterator('SELECT pc.pid, pc.original_corpsid AS original, pc.current_corpsid AS current, pceo.name AS original_name, pceo.abbreviation AS original_abbrev, @@ -466,9 +468,10 @@ class ProfileCorps extends ProfileField LEFT JOIN profile_corps_enum AS pceo ON (pceo.id = pc.original_corpsid) LEFT JOIN profile_corps_enum AS pcec ON (pcec.id = pc.current_corpsid) LEFT JOIN profile_corps_rank_enum AS pcrec ON (pcrec.id = pc.rankid) - WHERE pc.pid IN {?} AND pc.corps_pub IN {?} AND pceo.id != 1 + LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?}) + WHERE pc.pid IN {?} AND pve.best_display_level + 0 <= pc.corps_pub + 0 AND pceo.id != 1 ORDER BY ' . XDB::formatCustomOrder('pid', $pids), - $pids, $visibility->levels()); + $visibility->level(), $pids); return $data; } @@ -487,7 +490,7 @@ class ProfileMentoringCountries extends ProfileField } } - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { $data = XDB::iterator('SELECT pmc.pid, pmc.country AS id, gc.country AS name FROM profile_mentor_country AS pmc @@ -533,9 +536,9 @@ class ProfileAddresses extends ProfileField return $addresses; } - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { - $it = Address::iterate($pids, array(), array(), $visibility->levels()); + $it = Address::iterate($pids, array(), array(), $visibility); return PlIteratorUtils::subIterator($it->value(), PlIteratorUtils::arrayValueCallback('pid')); } @@ -584,9 +587,9 @@ class ProfilePhones extends ProfileField return $phones; } - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { - $it = Phone::iterate($pids, array(), array(), $visibility->levels()); + $it = Phone::iterate($pids, array(), array(), $visibility); return PlIteratorUtils::subIterator($it->value(), PlIteratorUtils::arrayValueCallback('pid')); } } @@ -604,15 +607,16 @@ class ProfileJobs extends ProfileField } } - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { CompanyList::preload($pids); $data = XDB::iterator('SELECT id, pid, description, url as user_site, jobid, - IF(email_pub IN {?}, email, NULL) AS user_email + IF(pve.best_display_level + 0 <= email_pub + 0, email, NULL) AS user_email FROM profile_job - WHERE pid IN {?} AND pub IN {?} + LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?}) + WHERE pid IN {?} AND pve.best_display_level + 0 <= pub + 0 ORDER BY ' . XDB::formatCustomOrder('pid', $pids) . ', id', - $visibility->levels(), $pids, $visibility->levels()); + $visibility->level(), $pids); return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid')); } @@ -686,15 +690,16 @@ class ProfileJobTerms extends ProfileField return $this->jobterms; } - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { $data = XDB::iterator('SELECT jt.jtid, jte.full_name, jt.pid, jt.jid FROM profile_job_term AS jt INNER JOIN profile_job AS j ON (jt.pid = j.pid AND jt.jid = j.id) LEFT JOIN profile_job_term_enum AS jte USING(jtid) - WHERE jt.pid IN {?} AND j.pub IN {?} + LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?}) + WHERE jt.pid IN {?} AND pve.best_display_level + 0 <= j.pub + 0 ORDER BY ' . XDB::formatCustomOrder('jt.pid', $pids), - $pids, $visibility->levels()); + $visibility->level(), $pids); return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid')); } } @@ -702,7 +707,7 @@ class ProfileJobTerms extends ProfileField // {{{ class ProfileMentoringTerms [ Field ] class ProfileMentoringTerms extends ProfileJobTerms { - public static function fetchData(array $pids, ProfileVisibility $visibility) + public static function fetchData(array $pids, Visibility $visibility) { $data = XDB::iterator('SELECT mt.jtid, jte.full_name, mt.pid FROM profile_mentor_term AS mt @@ -753,7 +758,7 @@ class CompanyList // Add phones to hq if (count($newcompanies)) { - $it = Phone::iterate(array(), array(Phone::LINK_COMPANY), $newcompanies); + $it = Phone::iterate(array(), array(Phone::LINK_COMPANY), $newcompanies, Visibility::defaultForRead()); while ($phone = $it->next()) { self::$companies[$phone->link_id]->setPhone($phone); } diff --git a/include/userset.inc.php b/include/userset.inc.php index 75c432d..62b5a02 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 = ProfileVisibility::defaultForRead(ProfileVisibility::VIS_AX); + $visibility = Visibility::defaultForRead(Visibility::VIEW_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 ee6ee0c..b544ef1 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 = ProfileVisibility::defaultForRead(ProfileVisibility::VIS_PRIVATE); + $this->visibility = Visibility::defaultForRead(Visibility::VIEW_PRIVATE); $this->freetext = $freetext; $this->photos = $photos; } diff --git a/modules/profile.php b/modules/profile.php index b9c5698..6e606af 100644 --- a/modules/profile.php +++ b/modules/profile.php @@ -225,13 +225,13 @@ class ProfileModule extends PLModule // Determines the access level at which the profile will be displayed. if (Env::v('view') == 'public') { - $view = ProfileVisibility::VIS_PUBLIC; + $view = Visibility::VIEW_PUBLIC; } else if (Env::v('view') == 'ax') { - $view = ProfileVisibility::VIS_AX; + $view = Visibility::VIEW_AX; } else { - $view = ProfileVisibility::VIS_PRIVATE; + $view = Visibility::VIEW_PRIVATE; } - $vis = ProfileVisibility::defaultForRead($view); + $visibility = Visibility::defaultForRead($view); // Display pending picture if (S::logged() && Env::v('modif') == 'new') { @@ -242,7 +242,7 @@ class ProfileModule extends PLModule if (is_null($pid)) { $owner = User::getSilent($id); if ($owner) { - $profile = $owner->profile(true, Profile::FETCH_ALL, $vis); + $profile = $owner->profile(true, Profile::FETCH_ALL, $visibility); if ($profile) { $pid = $profile->id(); } @@ -250,7 +250,7 @@ class ProfileModule extends PLModule } else { // Fetches profile's and profile's owner information and redirects to // marketing if the owner has not subscribed and the requirer has logged in. - $profile = Profile::get($pid, Profile::FETCH_ALL, $vis); + $profile = Profile::get($pid, Profile::FETCH_ALL, $visibility); $owner = $profile->owner(); } if (is_null($pid)) { @@ -259,6 +259,7 @@ class ProfileModule extends PLModule } return PL_NOT_FOUND; } + // Now that we know this is an existing profile, we can switch to the // appropriate template. $page->changeTpl('profile/profile.tpl', SIMPLE); @@ -278,7 +279,7 @@ class ProfileModule extends PLModule $page->assign_by_ref('profile', $profile); $page->assign_by_ref('owner', $owner); - $page->assign('view', $view); + $page->assign('view', $visibility); $page->assign('logged', S::logged()); header('Last-Modified: ' . date('r', strtotime($profile->last_change))); diff --git a/modules/profile/jobs.inc.php b/modules/profile/jobs.inc.php index b31f327..d29a5ef 100644 --- a/modules/profile/jobs.inc.php +++ b/modules/profile/jobs.inc.php @@ -131,7 +131,7 @@ class ProfileSettingJob implements ProfileSetting return $jobs; } - private function cleanJob(ProfilePage $page, $jobid, array &$job, &$success, $maxPublicity) + private function cleanJob(ProfilePage $page, $jobid, array &$job, &$success, $job_level) { if ($job['w_email'] == "new@example.org") { $job['w_email'] = $job['w_email_new']; @@ -178,10 +178,10 @@ class ProfileSettingJob implements ProfileSetting } } - if ($maxPublicity->isVisible($job['w_email_pub'])) { - $job['w_email_pub'] = $maxPublicity->level(); + if (Visibility::isLessRestrictive($job['w_email_pub'], $job_level)) { + $job['w_email_pub'] = $job_level; } - $job['w_phone'] = Phone::formatFormArray($job['w_phone'], $s, $maxPublicity); + $job['w_phone'] = Phone::formatFormArray($job['w_phone'], $s, $job_level); if ($job['w_entry_year'] && strlen($job['w_entry_year']) != 4) { $job['w_entry_year_error'] = true; @@ -244,17 +244,20 @@ class ProfileSettingJob implements ProfileSetting foreach ($value as $key => &$job) { $address = new Address($job['w_address']); $s = $address->format(); - $maxPublicity = new ProfileVisibility($job['pub']); - if ($maxPublicity->isVisible($address->pub)) { - $address->pub = $maxPublicity->level(); + + // Force the address publicity to be at least as restricted as + // the job publicity. + $job_level = $job['pub']; + if (Visibility::isLessRestrictive($address->pub, $job_level)) { + $address->pub = $job_level; } $job['w_address'] = $address->toFormArray(); - $this->cleanJob($page, $key, $job, $s, $maxPublicity); + $this->cleanJob($page, $key, $job, $s, $job_level); if (!$init) { $success = ($success && $s); } } - usort($value, 'ProfileVisibility::comparePublicity'); + usort($value, 'Visibility::comparePublicity'); return $value; } diff --git a/modules/profile/page.inc.php b/modules/profile/page.inc.php index 242733f..c6eae36 100644 --- a/modules/profile/page.inc.php +++ b/modules/profile/page.inc.php @@ -108,7 +108,7 @@ class ProfileSettingPhones implements ProfileSetting $phones = array(); if (is_null($value)) { - $it = Phone::iterate(array($page->pid()), array(Phone::LINK_PROFILE), array(0)); + $it = Phone::iterate(array($page->pid()), array(Phone::LINK_PROFILE), array(0), Visibility::defaultForEdit()); while ($phone = $it->next()) { $success = ($phone->format() && $success); $phones[] = $phone->toFormArray(); diff --git a/templates/profile/profile.tpl b/templates/profile/profile.tpl index 13004b4..ea76a36 100644 --- a/templates/profile/profile.tpl +++ b/templates/profile/profile.tpl @@ -41,13 +41,12 @@ $($.closeOnEsc); //]]> {/literal} -
{assign var=photo value=$profile->getPhoto(false)} {if $photo}Photo de {$profile->fullName()}{/if} - {if $logged && $profile->isVisible(#ProfileVisibility::VIS_AX#) && ( $profile->section|smarty:nodefaults || $profile->getBinets()|smarty:nodefaults || ($owner && $owner->groups(true,true)|smarty:nodefaults))} + {if $logged && $view->isVisible(#Visibility::EXPORT_AX#) && ( $profile->section|smarty:nodefaults || $profile->getBinets()|smarty:nodefaults || ($owner && $owner->groups(true,true)|smarty:nodefaults))}

À l'X…

{if $profile->section}
Section : {$profile->section}
{/if} @@ -55,7 +54,7 @@ $($.closeOnEsc); {if $binets|@count}
Binet{if count($binets) > 1}s{/if} : {', '|implode:$profile->getBinetsNames()}
{/if} - {if $owner && $profile->isVisible(#ProfileVisibility::VIS_AX#)} + {if $owner && $view->isVisible(#Visibility::EXPORT_AX#)} {assign var=groups value=$owner->groups(true,true)} {if $groups|@count}
Groupe{if count($groups) > 1}s{/if} et institution{if count($groups) > 1}s{/if} X :
@@ -92,7 +91,7 @@ $($.closeOnEsc);
{if $profile->isFemale()}•{/if} - {if $profile->isVisible(#ProfileVisibility::VIS_PRIVATE#)}{$profile->private_name}{else}{$profile->public_name}{/if} + {if $view->isVisible(#Visibility::EXPORT_PRIVATE#)}{$profile->private_name}{else}{$profile->public_name}{/if} {if $logged}  {if !$profile->isDead()}{* @@ -121,7 +120,7 @@ $($.closeOnEsc); {/if}
- {if $logged && $profile->isVisible(#ProfileVisibility::VIS_AX#) && $owner && $owner->state eq 'active'} + {if $logged && $view->isVisible(#Visibility::EXPORT_AX#) && $owner && $owner->state eq 'active'}
Fiche mise à jour
le {$profile->last_change|date_format} @@ -130,9 +129,9 @@ $($.closeOnEsc); {* 121634816 is Profile::PHONE_LINK_PROFILE | Profile::PHONE_TYPE_ANY = 0x7400000 *} {assign var=phones value=$profile->getPhones(121634816)} - {if ($logged && $profile->isVisible(#ProfileVisibility::VIS_AX#)) || count($phones) > 0} + {if ($logged && $view->isVisible(#Visibility::EXPORT_AX#)) || count($phones) > 0}
- {if $logged && $profile->isVisible(#ProfileVisibility::VIS_AX#)} + {if $logged && $view->isVisible(#Visibility::EXPORT_AX#)} {/if} - {if $view eq 'public'} + {if $view->level() eq #Visibility::VIEW_PUBLIC#}
Cette fiche est publique et visible par tout internaute,
vous pouvez aussi voir celle réservée aux X.
- {elseif $view eq 'ax'} + {elseif $view->level() eq #Visibility::VIEW_AX#}
Cette fiche est privée et ne recense que les informations transmises à l'AX. diff --git a/upgrade/1.1.2/06_visibility.sql b/upgrade/1.1.2/06_visibility.sql index f0dbffe..c93f5ca 100644 --- a/upgrade/1.1.2/06_visibility.sql +++ b/upgrade/1.1.2/06_visibility.sql @@ -1,5 +1,24 @@ -ALTER TABLE profile_addresses CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public', 'none') NOT NULL DEFAULT 'private'; -ALTER TABLE profile_corps CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public', 'none') NOT NULL DEFAULT 'private'; -ALTER TABLE profile_job CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public', 'none') NOT NULL DEFAULT 'private'; -ALTER TABLE profile_job CHANGE COLUMN email_pub email_pub ENUM('hidden', 'private', 'ax', 'public', 'none') NOT NULL DEFAULT 'private'; -ALTER TABLE profile_phone CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public', 'none') NOT NULL DEFAULT 'private'; +ALTER TABLE profile_addresses CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private'; +ALTER TABLE profile_corps CHANGE COLUMN corps_pub corps_pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private'; +ALTER TABLE profile_job CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private'; +ALTER TABLE profile_job CHANGE COLUMN email_pub email_pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private'; +ALTER TABLE profile_networking CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private'; +ALTER TABLE profile_photos CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private'; +ALTER TABLE profile_phones CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private'; +ALTER TABLE profiles CHANGE COLUMN freetext_pub freetext_pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private'; +ALTER TABLE profiles CHANGE COLUMN medals_pub medals_pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private'; +ALTER TABLE profiles CHANGE COLUMN alias_pub alias_pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private'; + +DROP TABLE IF EXISTS profile_visibility_enum; +CREATE TABLE profile_visibility_enum ( + access_level ENUM('admin', 'private', 'ax', 'public', 'none'), + best_display_level ENUM('hidden', 'private', 'ax', 'public') NULL, + display_levels SET('hidden', 'private', 'ax', 'public') +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO profile_visibility_enum (access_level, best_display_level, display_levels) VALUES + ('admin', 'hidden', 'hidden,private,ax,public'), + ('private', 'private', 'private,ax,public'), + ('ax', 'ax', 'ax,public'), + ('public', 'public', 'public'), + ('none', NULL, ''); -- 2.1.4