X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=classes%2Fuserfilter.php;h=dffa8a7191f6dd15eb02152f156457825c378bcd;hb=05613e9aa75a084c495c82f6af043d5246e003ab;hp=453d94a21390d9a6110a90afbbbfd7ef3a7ffb4c;hpb=486bc076249f9eb8ccc843498a5ca583ed8d9387;p=platal.git diff --git a/classes/userfilter.php b/classes/userfilter.php index 453d94a..dffa8a7 100644 --- a/classes/userfilter.php +++ b/classes/userfilter.php @@ -1,6 +1,6 @@ profile_visibility = new ProfileVisibility(); + $this->visibility = Visibility::defaultForRead(); } - public function getVisibilityLevels() - { - return $this->profile_visibility->levels(); - } - - public function getVisibilityLevel() - { - return $this->profile_visibility->level(); - } - - public function restrictVisibilityTo($level) - { - $this->profile_visibility->setLevel($level); + /** 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) { - return $field . ' IN ' . XDB::formatArray($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() @@ -543,12 +568,12 @@ class UserFilter extends PlFilter static public function sortByName() { - return array(new UFO_Name(Profile::LASTNAME), new UFO_Name(Profile::FIRSTNAME)); + return array(new UFO_Name()); } static public function sortByPromo() { - return array(new UFO_Promo(), new UFO_Name(Profile::LASTNAME), new UFO_Name(Profile::FIRSTNAME)); + return array(new UFO_Promo(), new UFO_Name()); } static private function getDBSuffix($string) @@ -676,44 +701,6 @@ class UserFilter extends PlFilter return $joins; } - /** NAMES - */ - - static public function assertName($name) - { - if (!DirEnum::getID(DirEnum::NAMETYPES, $name)) { - Platal::page()->kill('Invalid name type: ' . $name); - } - } - - private $pn = array(); - public function addNameFilter($type, $variant = null) - { - $this->requireProfiles(); - if (!is_null($variant)) { - $ft = $type . '_' . $variant; - } else { - $ft = $type; - } - $sub = '_' . $ft; - self::assertName($ft); - - if (!is_null($variant) && $variant == 'other') { - $sub .= $this->option++; - } - $this->pn[$sub] = DirEnum::getID(DirEnum::NAMETYPES, $ft); - return $sub; - } - - protected function nameJoins() - { - $joins = array(); - foreach ($this->pn as $sub => $type) { - $joins['pn' . $sub] = PlSqlJoin::left('profile_name', '$ME.pid = $PID AND $ME.typeid = {?}', $type); - } - return $joins; - } - /** NAMETOKENS */ private $name_tokens = array(); @@ -1005,44 +992,28 @@ class UserFilter extends PlFilter /** ADDRESSES */ - private $with_pa = false; - public function addAddressFilter() + private $types = array(); + public function addAddressFilter($type) { $this->requireProfiles(); $this->with_pa = true; - return 'pa'; - } - - private $with_pac = false; - public function addAddressCountryFilter() - { - $this->requireProfiles(); - $this->addAddressFilter(); - $this->with_pac = true; - return 'gc'; - } - private $with_pal = false; - public function addAddressLocalityFilter() - { - $this->requireProfiles(); - $this->addAddressFilter(); - $this->with_pal = true; - return 'gl'; + $sub = '_' . $this->option++; + $this->types[$type] = $sub; + return $sub; } protected function addressJoins() { $joins = array(); - if ($this->with_pa) { - $joins['pa'] = PlSqlJoin::left('profile_addresses', '$ME.pid = $PID'); - } - if ($this->with_pac) { - $joins['gc'] = PlSqlJoin::left('geoloc_countries', '$ME.iso_3166_1_a2 = pa.countryID'); - } - if ($this->with_pal) { - $joins['gl'] = PlSqlJoin::left('geoloc_localities', '$ME.id = pa.localityID'); + foreach ($this->types as $type => $sub) { + $joins['pa' . $sub] = PlSqlJoin::inner('profile_addresses', '$ME.pid = $PID'); + $joins['pac' . $sub] = PlSqlJoin::inner('profile_addresses_components', + '$ME.pid = pa' . $sub . '.pid AND $ME.jobid = pa' . $sub . '.jobid AND $ME.groupid = pa' . $sub . '.groupid AND $ME.type = pa' . $sub . '.type AND $ME.id = pa' . $sub . '.id'); + $joins['pace' . $sub] = PlSqlJoin::inner('profile_addresses_components_enum', + '$ME.id = pac' . $sub . '.component_id AND FIND_IN_SET({?}, $ME.types)', $type); } + return $joins; } @@ -1406,6 +1377,77 @@ class UserFilter extends PlFilter return array(); } } + + + /** PARTNER SHARING + */ + + // Lists partner shortnames in use, as a $partner_shortname => true map. + private $ppss = array(); + + /** Add a filter on user having settings for a given partner. + * @param $partner_id the ID of the partner + * @return the name of the table to use in joins (e.g ppss_$partner_id). + */ + public function addPartnerSharingFilter($partner_id) + { + $this->requireProfiles(); + $sub = "ppss_" . $partner_id; + $this->ppss[$sub] = $partner_id; + return $sub; + } + + protected function partnerSharingJoins() + { + $joins = array(); + foreach ($this->ppss as $sub => $partner_id) { + $joins[$sub] = PlSqlJoin::left('profile_partnersharing_settings', '$ME.pid = $PID AND $ME.partner_id = {?} AND $ME.sharing_level != \'none\'', $partner_id); + } + return $joins; + } + + public function restrictVisibilityForPartner($partner_id) + { + $sub = $this->addPartnerSharingFilter($partner_id); + $this->visibility_field = $sub . '.sharing_level'; + } + + /** 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; + } + + /** Since this method might perform inner joins on tables which have been + * joined previously (e.g when using addVisibilityFieldFilter), it has to + * come after the Joins() methods for those tables. + * This is due to the implementation logic for discovering joins and the + * ordering used by PHP introspection. + */ + 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; + } + } // }}} // {{{ class ProfileFilter @@ -1438,5 +1480,5 @@ class ProfileFilter extends UserFilter } // }}} -// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: +// vim:set et sw=4 sts=4 sws=4 foldmethod=marker fenc=utf-8: ?>