Change sorting order on ML display to use sort_name.
[platal.git] / classes / profile.php
index 73a9fff..6722784 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /***************************************************************************
- *  Copyright (C) 2003-2011 Polytechnique.org                              *
+ *  Copyright (C) 2003-2014 Polytechnique.org                              *
  *  http://opensource.polytechnique.org/                                   *
  *                                                                         *
  *  This program is free software; you can redistribute it and/or modify   *
@@ -48,6 +48,17 @@ class Profile implements PlExportable
     const DEGREE_M = 'Master';
     const DEGREE_D = 'Doctorat';
 
+    static public $cycles = array(
+        self::DEGREE_X => 'polytechnicien',
+        self::DEGREE_M => 'master',
+        self::DEGREE_D => 'docteur'
+    );
+    static public $cycle_prefixes = array(
+        self::DEGREE_X => 'X',
+        self::DEGREE_M => 'M',
+        self::DEGREE_D => 'D'
+    );
+
     static public $name_variants = array(
             self::LASTNAME => array(self::VN_MARITAL, self::VN_ORDINARY),
             self::FIRSTNAME => array(self::VN_ORDINARY, self::VN_INI, self::VN_OTHER)
@@ -98,10 +109,14 @@ class Profile implements PlExportable
     const FETCH_PHONES         = 0x000100;
     const FETCH_JOB_TERMS      = 0x000200;
     const FETCH_MENTOR_TERMS   = 0x000400;
+    const FETCH_DELTATEN       = 0x000800;
+    const FETCH_PARTNER        = 0x001000;
+    const FETCH_SKILL          = 0x002000;
+    const FETCH_LANGUAGE       = 0x004000;
 
     const FETCH_MINIFICHES   = 0x00012D; // FETCH_ADDRESSES | FETCH_EDU | FETCH_JOBS | FETCH_NETWORKING | FETCH_PHONES
 
-    const FETCH_ALL          = 0x0007FF; // OR of FETCH_*
+    const FETCH_ALL          = 0x007FFF; // OR of FETCH_*
 
     static public $descriptions = array(
         'search_names'    => 'Noms',
@@ -113,11 +128,13 @@ class Profile implements PlExportable
         'networking'      => 'Messageries…',
         'tels'            => 'Téléphones',
         'edus'            => 'Formations',
+        'main_edus'       => 'Formations à l\'X',
         'promo'           => 'Promotion de sortie',
         'birthdate'       => 'Date de naissance',
         'yourself'        => 'Nom affiché',
         'freetext'        => 'Commentaire',
         'freetext_pub'    => 'Affichage du commentaire',
+        'axfreetext'      => 'Commentaire AX',
         'photo'           => 'Photographie',
         'photo_pub'       => 'Affichage de la photographie',
         'addresses'       => 'Adresses',
@@ -132,7 +149,8 @@ class Profile implements PlExportable
         'langues'         => 'Langues',
         'expertise'       => 'Expertises (mentoring)',
         'terms'           => 'Compétences (mentoring)',
-        'countries'       => 'Pays (mentoring)'
+        'countries'       => 'Pays (mentoring)',
+        'deltaten'        => 'Opération N N-10',
     );
 
     private $fetched_fields  = 0x000000;
@@ -146,12 +164,19 @@ class Profile implements PlExportable
     private $visibility = null;
 
 
-    private function __construct(array $data)
+    private function __construct(array $data, Visibility $visibility)
     {
         $this->data = $data;
         $this->pid = $this->data['pid'];
         $this->hrpid = $this->data['hrpid'];
-        $this->visibility = new ProfileVisibility();
+        $this->visibility = $visibility;
+    }
+
+    public function __destruct()
+    {
+        // Need to delete objects allocated by the profile
+        // http://www.php.net/manual/en/function.unset.php#98692
+        unset($this->owner);
     }
 
     public function id()
@@ -181,14 +206,26 @@ class Profile implements PlExportable
         return false;
     }
 
-    public function promo()
+    public function promo($details = false)
     {
+        if ($details && ($this->program || $this->fieldid)) {
+            $text = array();
+            if ($this->program) {
+                $text[] = $this->program;
+            }
+            if ($this->fieldid) {
+                $fieldsList = DirEnum::getOptions(DirEnum::EDUFIELDS);
+                $text[] = $fieldsList[$this->fieldid];
+            }
+            return $this->promo . ' (' . implode(', ', $text) . ')';
+        }
+
         return $this->promo;
     }
 
     public function yearpromo()
     {
-        return intval(substr($this->promo, 1, 4));
+        return $this->promo_year;
     }
 
     /** Check if user is an orange (associated with several promos)
@@ -247,6 +284,20 @@ class Profile implements PlExportable
         }
     }
 
+    public static function educationDuration($education)
+    {
+        switch ($education) {
+          case self::DEGREE_X:
+            return 3;
+          case self::DEGREE_M:
+            return 2;
+          case self::DEGREE_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.
@@ -259,6 +310,35 @@ class Profile implements PlExportable
         return 0;
     }
 
+    // Returns the profile's color.
+    public function promoColor()
+    {
+        switch ($this->mainEducation()) {
+          case 'X':
+            if (($this->yearpromo() % 2) === 0) {
+                return 'red';
+            } else {
+                return 'yellow';
+            }
+          case 'M':
+            return 'green';
+          case 'D':
+            return 'blue';
+          default:
+            return 'gray';
+        }
+    }
+
+    // Returns younger/older promotion year for a given education.
+    static public function extremePromotions($education)
+    {
+        return XDB::fetchOneRow("SELECT  MIN(pe.promo_year) AS min, MAX(pe.promo_year) AS max
+                                     FROM  profile_education             AS pe
+                               INNER JOIN  profile_education_degree_enum AS pede ON (pe.degreeid = pede.id)
+                                    WHERE  pede.degree = {?} AND FIND_IN_SET('primary', pe.flags)",
+                                  $education);
+    }
+
     /** Print a name with the given formatting:
      * %s = • for women
      * %f = firstname
@@ -292,9 +372,14 @@ class Profile implements PlExportable
         return $this->short_name;
     }
 
+    public function sortName()
+    {
+        return $this->sort_name;
+    }
+
     public function firstName()
     {
-        return $this->firstname;
+        return $this->firstname_ordinary;
     }
 
     public function firstNames()
@@ -304,7 +389,7 @@ class Profile implements PlExportable
 
     public function lastName()
     {
-        return $this->lastname;
+        return $this->lastname_ordinary;
     }
 
     public function lastNames()
@@ -325,7 +410,7 @@ class Profile implements PlExportable
     public function displayEmail()
     {
         $o = $this->owner();
-        if ($o != null) {
+        if ($o != null && $this->isVisible(Visibility::EXPORT_PRIVATE)) {
             return $o->bestEmail();
         } else {
             return $this->email_directory;
@@ -354,15 +439,15 @@ class Profile implements PlExportable
     public function nationalities()
     {
         $nats = array();
-        $countries = DirEnum::getOptions(DirEnum::COUNTRIES);
+        $nationalities = DirEnum::getOptions(DirEnum::NATIONALITIES);
         if ($this->nationality1) {
-            $nats[$this->nationality1] = $countries[$this->nationality1];
+            $nats[$this->nationality1] = $nationalities[$this->nationality1];
         }
         if ($this->nationality2) {
-            $nats[$this->nationality2] = $countries[$this->nationality2];
+            $nats[$this->nationality2] = $nationalities[$this->nationality2];
         }
         if ($this->nationality3) {
-            $nats[$this->nationality3] = $countries[$this->nationality3];
+            $nats[$this->nationality3] = $nationalities[$this->nationality3];
         }
         return $nats;
     }
@@ -397,11 +482,12 @@ class Profile implements PlExportable
 
     /**
      * Clears a profile.
-     *  *always deletes in: profile_addresses, profile_binets, profile_job,
-     *      profile_langskills, profile_mentor, profile_networking,
-     *      profile_phones, profile_skills, watch_profile
+     *  *always deletes in: profile_addresses, profile_binets, profile_deltaten,
+     *      profile_job, profile_langskills, profile_mentor, profile_networking,
+     *      profile_partnersharing_settings, profile_phones, profile_skills,
+     *      watch_profile
      *  *always keeps in: profile_corps, profile_display, profile_education,
-     *      profile_medals, profile_name, profile_photos, search_name
+     *      profile_medals, profile_*_names, profile_photos, search_name
      *  *modifies: profiles
      */
     public function clear()
@@ -409,7 +495,8 @@ class Profile implements PlExportable
         $tables = array(
             'profile_job', 'profile_langskills', 'profile_mentor',
             'profile_networking', 'profile_skills', 'watch_profile',
-            'profile_phones', 'profile_addresses', 'profile_binets');
+            'profile_phones', 'profile_addresses', 'profile_binets',
+            'profile_deltaten', 'profile_partnersharing_settings');
 
         foreach ($tables as $t) {
             XDB::execute('DELETE FROM  ' . $t . '
@@ -418,22 +505,13 @@ class Profile implements PlExportable
         }
 
         XDB::execute("UPDATE  profiles
-                         SET  cv = NULL, freetext = NULL, freetext_pub = 'private',
-                              medals_pub = 'private', alias_pub = 'private',
+                         SET  cv = NULL, freetext = NULL, freetext_pub = 'private', axfreetext = NULL,
+                              medals_pub = 'private', alias_pub = 'hidden',
                               email_directory = NULL
                        WHERE  pid = {?}",
                      $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
@@ -623,7 +701,10 @@ class Profile implements PlExportable
     public function getEducations($flags, $limit = null)
     {
         if ($this->educations == null && !$this->fetched(self::FETCH_EDU)) {
-            $this->setEducations($this->getProfileField(self::FETCH_EDU));
+            $educations = $this->getProfileField(self::FETCH_EDU);
+            if ($educations) {
+                $this->setEducations($educations);
+            }
         }
 
         if ($this->educations == null) {
@@ -648,11 +729,42 @@ class Profile implements PlExportable
     public function getCorps()
     {
         if ($this->corps == null && !$this->fetched(self::FETCH_CORPS)) {
-            $this->setCorps($this->getProfileField(self::FETCH_CORPS));
+            $corps = $this->getProfileField(self::FETCH_CORPS);
+            if ($corps) {
+                $this->setCorps($corps);
+            }
         }
         return $this->corps;
     }
 
+    /**
+     * Retrieve the name of the corps which has been done.
+     *
+     * Note: this function first tries getCorps(), and if this field is blank
+     * tries to find an education which degree is "Corps".
+     *
+     * Returns an empty string if nothing has been found.
+     */
+    public function getCorpsName()
+    {
+        $corps = $this->getCorps();
+        if ($corps && $corps->current) {
+            $corpsList = DirEnum::getOptions(DirEnum::CURRENTCORPS);
+            return $corpsList[$corps->current];
+        }
+
+        foreach ($this->getExtraEducations() as $edu) {
+            if (!strcasecmp($edu->degree, 'Corps')) {
+                if ($edu->school_short) {
+                    return $edu->school_short;
+                } elseif ($edu->school) {
+                    return $edu->school;
+                }
+            }
+        }
+        return '';
+    }
+
     /** Networking
      */
     private $networks = null;
@@ -743,7 +855,10 @@ class Profile implements PlExportable
     public function getMentoringCountries()
     {
         if ($this->mentor_countries == null && !$this->fetched(self::FETCH_MENTOR_COUNTRY)) {
-            $this->setMentoringCountries($this->getProfileField(self::FETCH_MENTOR_COUNTRY));
+            $countries = $this->getProfileField(self::FETCH_MENTOR_COUNTRY);
+            if ($countries) {
+                $this->setMentoringCountries($countries);
+            }
         }
 
         if ($this->mentor_countries == null) {
@@ -770,7 +885,10 @@ class Profile implements PlExportable
     public function getMentoringTerms()
     {
         if ($this->mentor_terms == null && !$this->fetched(self::FETCH_MENTOR_TERMS)) {
-            $this->setMentoringTerms($this->getProfileField(self::FETCH_MENTOR_TERMS));
+            $terms = $this->getProfileField(self::FETCH_MENTOR_TERMS);
+            if ($terms) {
+                $this->setMentoringTerms($terms);
+            }
         }
 
         if ($this->mentor_terms == null) {
@@ -780,12 +898,94 @@ class Profile implements PlExportable
         }
     }
 
+    /* Skills */
+    private $skills = null;
+    public function setSkills(ProfileSkills $skills)
+    {
+        $this->skills = $skills;
+    }
+    public function getSkills()
+    {
+        if ($this->skills == null && !$this->fetched(self::FETCH_SKILL)) {
+            $skills = $this->getProfileField(self::FETCH_SKILL);
+            if ($skills) {
+                $this->setSkills($skills);
+            }
+        }
+
+        if ($this->skills == null) {
+            return array();
+        } else {
+            return $this->skills->skills;
+        }
+    }
+
+    /* Languades */
+    private $languages = null;
+    public function setLanguages(ProfileLanguages $languages)
+    {
+        $this->languages = $languages;
+    }
+    public function getLanguages()
+    {
+        if ($this->languages == null && !$this->fetched(self::FETCH_LANGUAGE)) {
+            $languages = $this->getProfileField(self::FETCH_LANGUAGE);
+            if ($languages) {
+                $this->setLanguages($languages);
+            }
+        }
+
+        if ($this->languages == null) {
+            return array();
+        } else {
+            return $this->languages->languages;
+        }
+    }
+
+    /** DeltaTen
+     */
+
+    /** Find out whether this profile may take part to the "DeltaTen" operation.
+     * @param $role Which role to select ('young' or 'old')
+     * @return Boolean: whether it is enabled.
+     */
+    const DELTATEN_YOUNG = 'young';
+    const DELTATEN_OLD = 'old';
+    public function isDeltaTenEnabled($role)
+    {
+        global $globals;
+        switch ($role) {
+        case self::DELTATEN_YOUNG:
+            return ($this->mainGrade() == UserFilter::GRADE_ING && $this->yearpromo() >= $globals->deltaten->first_promo_young);
+        case self::DELTATEN_OLD:
+            // Roughly compute the current promo in second year on the campus:
+            // Promo 2010 is in second year between 09/2011 and 08/2012 => use 2012.
+            // DeltaTen program begins around January of the second year.
+            $promo_on_platal = ((int) date('Y')) - 2;
+            return ($this->mainGrade() == UserFilter::GRADE_ING && $this->yearpromo() >= $globals->deltaten->first_promo_young - 10 && $this->yearpromo() <= $promo_on_platal - 10);
+        default:
+            Platal::assert(false, "Invalid DeltaTen role $role");
+        }
+    }
+
+    /** Retrieve the "Deltaten" message of the user.
+     * Returns "null" if the message is empty or the user is not taking part to the
+     * DeltaTen operation.
+     */
+    public function getDeltatenMessage()
+    {
+        if ($this->isDeltaTenEnabled(self::DELTATEN_OLD)) {
+            return $this->deltaten_message;
+        } else {
+            return null;
+        }
+    }
 
     /* Binets
      */
     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());
@@ -793,9 +993,22 @@ class Profile implements PlExportable
             return array();
         }
     }
+
+    public function getFullBinets()
+    {
+        if ($this->visibility->isVisible(Visibility::EXPORT_PRIVATE)) {
+            return XDB::fetchAllAssoc('SELECT  binet_id, text, url
+                                         FROM  profile_binets AS pb
+                                    LEFT JOIN  profile_binet_enum AS pbe ON (pbe.id = pb.binet_id)
+                                        WHERE  pid = {?}', $this->id());
+        } else {
+            return array();
+        }
+    }
+
     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)
@@ -805,6 +1018,22 @@ class Profile implements PlExportable
         }
     }
 
+    /* Hobbies
+     */
+    public function getHobbies() {
+        if ($this->visibility->isVisible(Visibility::EXPORT_PRIVATE)) {
+            return XDB::fetchAllAssoc('type', 'SELECT  type, GROUP_CONCAT(text)
+                                         FROM  profile_hobby
+                                        WHERE  pid = {?}
+                                     GROUP BY  type', $this->id());
+        } else {
+            return XDB::fetchAllAssoc('type', 'SELECT  type, GROUP_CONCAT(text)
+                                         FROM  profile_hobby
+                                        WHERE  pub = \'public\' AND pid = {?}
+                                      GROUP BY type', $this->id());
+        }
+    }
+
     /* Medals
      */
     private $medals = null;
@@ -816,7 +1045,10 @@ class Profile implements PlExportable
     public function getMedals()
     {
         if ($this->medals == null && !$this->fetched(self::FETCH_MEDALS)) {
-            $this->setMedals($this->getProfileField(self::FETCH_MEDALS));
+            $medals = $this->getProfileField(self::FETCH_MEDALS);
+            if ($medals) {
+                $this->setMedals($medals);
+            }
         }
         if ($this->medals == null) {
             return array();
@@ -824,6 +1056,28 @@ class Profile implements PlExportable
         return $this->medals->medals;
     }
 
+    /** Sharing data with partner websites
+     */
+    private $partners_settings = null;
+    public function setPartnersSettings(ProfilePartnerSharing $partners_settings)
+    {
+        $this->partners_settings = $partners_settings;
+    }
+
+    public function getPartnerSettings($partner_id)
+    {
+        if ($this->partners_settings === null && !$this->fetched(self::FETCH_PARTNER)) {
+            $settings = $this->getProfileField(self::FETCH_PARTNER);
+            if ($settings) {
+                $this->setPartnersSettings($settings);
+            }
+        }
+        if ($this->partners_settings === null) {
+            return PartnerSettings::getEmpty($partner_id);
+        }
+        return $this->partners_settings->get($partner_id);
+    }
+
     public function compareNames($firstname, $lastname)
     {
         $_lastname  = mb_strtoupper($this->lastName());
@@ -873,54 +1127,50 @@ class Profile implements PlExportable
             $order = '';
         }
 
-        $visibility = new ProfileVisibility($visibility);
+        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,
                                      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,
-                                     pe.entry_year, pe.grad_year,
+                                     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,
-                                     pn_f.name AS firstname, pn_l.name AS lastname,
-                                     IF( {?}, pn_n.name, NULL) 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,
+                                     ppn.firstname_main AS firstname, ppn.lastname_main AS lastname, IF ({?}, pn.name, NULL) AS nickname,
+                                     IF (ppn.firstname_ordinary = \'\', ppn.firstname_main, ppn.firstname_ordinary) AS firstname_ordinary,
+                                     IF (ppn.lastname_ordinary = \'\', ppn.lastname_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,
+                                     pd.directory_name, pd.public_name, pd.private_name, pd.sort_name,
+                                     IF (pp.pub >= {?}, pp.display_tel, NULL) AS mobile,
+                                     (ph.pub >= {?} AND ph.attach IS NOT NULL) AS has_photo, ph.pub as photo_pub,
                                      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,
+                                     IF ({?}, pdt.message, NULL) AS deltaten_message,
                                      ap.uid AS owner_id
                                FROM  profiles AS p
                          INNER JOIN  profile_display AS pd ON (pd.pid = p.pid)
                          INNER JOIN  profile_education AS pe ON (pe.pid = p.pid AND FIND_IN_SET(\'primary\', pe.flags))
                           LEFT JOIN  profile_section_enum AS pse ON (pse.id = p.section)
-                         INNER JOIN  profile_name AS pn_f ON (pn_f.pid = p.pid
-                                                              AND pn_f.typeid = ' . self::getNameTypeId('firstname', true) . ')
-                         INNER JOIN  profile_name AS pn_l ON (pn_l.pid = p.pid
-                                                              AND pn_l.typeid = ' . self::getNameTypeId('lastname', true) . ')
-                          LEFT JOIN  profile_name AS pn_uf ON (pn_uf.pid = p.pid
-                                                               AND pn_uf.typeid = ' . self::getNameTypeId('firstname_ordinary', true) . ')
-                          LEFT JOIN  profile_name AS pn_ul ON (pn_ul.pid = p.pid
-                                                               AND pn_ul.typeid = ' . self::getNameTypeId('lastname_ordinary', true) . ')
-                          LEFT JOIN  profile_name AS pn_n ON (pn_n.pid = p.pid
-                                                              AND pn_n.typeid = ' . self::getNameTypeId('nickname', true) . ')
+                         INNER JOIN  profile_public_names AS ppn ON (ppn.pid = p.pid)
+                          LEFT JOIN  profile_private_names AS pn ON (pn.pid = p.pid AND type = \'nickname\')
                           LEFT JOIN  profile_phones AS pp ON (pp.pid = p.pid AND pp.link_type = \'user\' AND tel_type = \'mobile\')
                           LEFT JOIN  profile_photos AS ph ON (ph.pid = p.pid)
                           LEFT JOIN  profile_mentor AS pm ON (pm.pid = p.pid)
+                          LEFT JOIN  profile_deltaten AS pdt ON (pdt.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 {?}
                            GROUP BY  p.pid
                                      ' . $order,
-                           $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // CV
-                           $visibility->levels(), // freetext
-                           $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // section
-                           $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // nickname
-                           $visibility->levels(), // mobile
-                           $visibility->levels(), // photo
+                           $visibility->isVisible(Visibility::EXPORT_PRIVATE), // CV
+                           $visibility->level(), // freetext
+                           $visibility->isVisible(Visibility::EXPORT_PRIVATE), // section
+                           $visibility->isVisible(Visibility::EXPORT_PRIVATE), // nickname
+                           $visibility->level(), // mobile
+                           $visibility->level(), // photo
+                           $visibility->isVisible(Visibility::EXPORT_PRIVATE), // deltaten_message
                            $pids
                        );
         return new ProfileIterator($it, $pids, $fields, $visibility);
@@ -962,9 +1212,12 @@ class Profile implements PlExportable
      */
     public static function get($login, $fields = 0x0000, $visibility = null)
     {
+        if ($visibility === null) {
+            $visibility = Visibility::defaultForRead();
+        }
+
         if (is_array($login)) {
-            $pf = new Profile($login);
-            $pf->setVisibilityLevel($visibility);
+            $pf = new Profile($login, $visibility);
             return $pf;
         }
         $pid = self::getPID($login);
@@ -977,7 +1230,7 @@ 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;
@@ -1031,63 +1284,63 @@ class Profile implements PlExportable
      */
     public static function getAccountEquivalentName($name)
     {
-        switch ($name)
-        {
-        case self::DN_DIRECTORY:
-        case self::DN_SORT:
+        switch ($name) {
+          case self::DN_DIRECTORY:
             return 'directory_name';
-        case self::DN_FULL:
-        case self::DN_PUBLIC:
+          case self::DN_SORT:
+            return 'sort_name';
+          case self::DN_FULL:
+          case self::DN_PUBLIC:
+          case self::DN_PRIVATE:
+          case self::DN_SHORT:
             return 'full_name';
-        case self::DN_PRIVATE:
-        case self::DN_SHORT:
-        case self::DN_YOURSELF:
-        default:
+          case self::DN_YOURSELF:
+            return 'display_name';
+          default:
             return 'display_name';
-        }
-    }
-
-    public static function getNameTypeId($type, $for_sql = false)
-    {
-        if (!S::has('name_types')) {
-            $table = XDB::fetchAllAssoc('type', 'SELECT  id, type
-                                                   FROM  profile_name_enum');
-            S::set('name_types', $table);
-        } else {
-            $table = S::v('name_types');
-        }
-        if ($for_sql) {
-            return XDB::escape($table[$type]);
-        } else {
-            return $table[$type];
         }
     }
 
     public static function rebuildSearchTokens($pids, $transaction = true)
     {
+        require_once 'name.func.inc.php';
         if (!is_array($pids)) {
             $pids = array($pids);
         }
-        $keys = XDB::iterator("(SELECT  n.pid AS pid, n.name AS name, e.score AS score,
-                                        IF(FIND_IN_SET('public', e.flags), 'public', '') AS public
-                                  FROM  profile_name      AS n
-                            INNER JOIN  profile_name_enum AS e ON (n.typeid = e.id)
-                                 WHERE  n.pid IN {?} AND NOT FIND_IN_SET('not_displayed', e.flags))
-                                 UNION
-                                (SELECT  n.pid AS pid, n.particle AS name, 0 AS score,
-                                         IF(FIND_IN_SET('public', e.flags), 'public', '') AS public
-                                   FROM  profile_name      AS n
-                             INNER JOIN  profile_name_enum AS e ON (n.typeid = e.id)
-                                  WHERE  n.pid IN {?} AND NOT FIND_IN_SET('not_displayed', e.flags))
-                               ",
-                              $pids, $pids);
+        $keys = XDB::iterator("(SELECT  pid, name, type, IF(type = 'nickname', 2, 1) AS score, '' AS public
+                                  FROM  profile_private_names
+                                 WHERE  pid IN {?})
+                                UNION
+                               (SELECT  pid, lastname_main, 'lastname' AS type, 10 AS score, 'public' AS public
+                                  FROM  profile_public_names
+                                 WHERE  lastname_main != '' AND pid IN {?})
+                                UNION
+                               (SELECT  pid, lastname_marital, 'lastname' AS type, 10 AS score, 'public' AS public
+                                  FROM  profile_public_names
+                                 WHERE  lastname_marital != '' AND pid IN {?})
+                                UNION
+                               (SELECT  pid, lastname_ordinary, 'lastname' AS type, 10 AS score, 'public' AS public
+                                  FROM  profile_public_names
+                                 WHERE  lastname_ordinary != '' AND pid IN {?})
+                                UNION
+                               (SELECT  pid, firstname_main, 'firstname' AS type, 10 AS score, 'public' AS public
+                                  FROM  profile_public_names
+                                 WHERE  firstname_main != '' AND pid IN {?})
+                                UNION
+                               (SELECT  pid, firstname_ordinary, 'firstname' AS type, 10 AS score, 'public' AS public
+                                  FROM  profile_public_names
+                                 WHERE  firstname_ordinary != '' AND pid IN {?})
+                                UNION
+                               (SELECT  pid, pseudonym, 'nickname' AS type, 10 AS score, 'public' AS public
+                                  FROM  profile_public_names
+                                 WHERE  pseudonym != '' AND pid IN {?})",
+                              $pids, $pids, $pids, $pids, $pids, $pids, $pids);
         $names = array();
         while ($key = $keys->next()) {
             if ($key['name'] == '') {
                 continue;
             }
-            $pid   = $key['pid'];
-            require_once 'name.func.inc.php';
+            $pid  = $key['pid'];
             $toks = split_name_for_search($key['name']);
             $toks = array_reverse($toks);
 
@@ -1100,9 +1353,9 @@ class Profile implements PlExportable
             $token = '';
             foreach ($toks as $tok) {
                 $token = $tok . $token;
-                $names["$pid-$token"] = XDB::format('({?}, {?}, {?}, {?}, {?})',
+                $names["$pid-$token"] = XDB::format('({?}, {?}, {?}, {?}, {?}, {?})',
                                                     $token, $pid, soundex_fr($token),
-                                                    $eltScore, $key['public']);
+                                                    $eltScore, $key['public'], $key['type']);
             }
         }
         if ($transaction) {
@@ -1112,7 +1365,7 @@ class Profile implements PlExportable
                             WHERE  pid IN {?}',
                      $pids);
         if (count($names) > 0) {
-            XDB::rawExecute('INSERT INTO  search_name (token, pid, soundex, score, flags)
+            XDB::rawExecute('INSERT INTO  search_name (token, pid, soundex, score, flags, general_type)
                                   VALUES  ' . implode(', ', $names));
         }
         if ($transaction) {
@@ -1180,12 +1433,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 = new ProfileVisibility();
+        if ($visibility === null) {
+            $visibility = Visibility::defaultForRead();
         }
 
         $this->fields = $fields;
@@ -1216,8 +1469,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], 0x0, $this->visibility);
         $pf->setFetchedFields($this->fields);
 
         if ($this->hasData(Profile::FETCH_PHONES, $vals)) {
@@ -1274,5 +1526,5 @@ class ProfileIterator implements PlIterator
     }
 }
 
-// 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:
 ?>