From 3a2985f931bdbbae9d1c689263a1dc15d9b3b7dc Mon Sep 17 00:00:00 2001 From: =?utf8?q?St=C3=A9phane=20Jacob?= Date: Fri, 6 May 2011 16:04:38 +0200 Subject: [PATCH] Adapts advanced search on addresses to our new geocoding engine (gmaps v3). MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Only search on localities and countries works for now. Signed-off-by: Stéphane Jacob --- classes/direnum.php | 75 +++++++++++----------- classes/profile.php | 8 +-- classes/userfilter.php | 40 ++++-------- classes/userfilter/conditions.inc.php | 113 +++++++-------------------------- include/profilefields.inc.php | 3 +- include/ufbuilder.inc.php | 115 +++++----------------------------- templates/search/adv.form.tpl | 16 +---- 7 files changed, 92 insertions(+), 278 deletions(-) diff --git a/classes/direnum.php b/classes/direnum.php index a616061..2f353ae 100644 --- a/classes/direnum.php +++ b/classes/direnum.php @@ -44,11 +44,13 @@ class DirEnum const ORIGINCORPS = 'origincorps'; const CORPSRANKS = 'corpsranks'; - const NATIONALITIES = 'nationalities'; - const COUNTRIES = 'countries'; - const ADMINAREAS = 'adminareas'; - const SUBADMINAREAS = 'subadminareas'; - const LOCALITIES = 'localities'; + const NATIONALITIES = 'nationalities'; + const SUBLOCALITIES = 'sublocalities'; + const LOCALITIES = 'localities'; + const ADMNISTRATIVEAREAS3 = 'admnistrativeareas3'; + const ADMNISTRATIVEAREAS2 = 'admnistrativeareas2'; + const ADMNISTRATIVEAREAS1 = 'admnistrativeareas1'; + const COUNTRIES = 'countries'; const COMPANIES = 'companies'; const JOBDESCRIPTION = 'jobdescription'; @@ -590,56 +592,49 @@ class DE_Nationalities extends DirEnumeration } // }}} -// {{{ class DE_Countries -class DE_Countries extends DirEnumeration +// {{{ class DE_AddressesComponents +class DE_AddressesComponents extends DirEnumeration { - protected $idfield = 'geoloc_countries.iso_3166_1_a2'; - protected $valfield = 'geoloc_countries.country'; - protected $valfield2 = 'geoloc_countries.countryEn'; - protected $from = 'geoloc_countries'; + protected $idfield = 'profile_addresses_components_enum.short_name'; + protected $valfield = 'profile_addresses_components_enum.long_name'; + protected $from = 'profile_addresses_components_enum'; - protected $ac_join = 'INNER JOIN profile_addresses ON (geoloc_countries.iso_3166_1_a2 = profile_addresses.countryId)'; - protected $ac_unique = 'profile_addresses.pid'; - protected $ac_where = 'profile_addresses.type = \'home\''; + protected $ac_join = 'INNER JOIN profile_addresses_components ON (profile_addresses_components.component_id = profile_addresses_components_enum.id)'; + protected $ac_unique = 'profile_addresses_components.pid'; + protected $ac_where = 'profile_addresses_components.type = \'home\''; } // }}} - -// {{{ class DE_AdminAreas -class DE_AdminAreas extends DE_WithSuboption +// {{{ class DE_AddressesComponents extensions +class DE_Countries extends DE_AddressesComponents { - protected $idfield = 'geoloc_administrativeareas.id'; - protected $optfield = 'geoloc_administrativeareas.country'; - protected $valfield = 'geoloc_administrativeareas.name'; - protected $from = 'geoloc_administrativeareas'; + protected $where = 'WHERE FIND_IN_SET(\'country\', profile_addresses_components_enum.types)'; +} - protected $ac_join = 'INNER JOIN profile_addresses ON (profile_addresses.administrativeAreaId = geoloc_administrativeareas.id)'; - protected $ac_unique = 'profile_addresses.pid'; +class DE_Admnistrativeareas1 extends DE_AddressesComponents +{ + protected $where = 'WHERE FIND_IN_SET(\'admnistrativeareas1\', profile_addresses_components_enum.types)'; } -// }}} -// {{{ class DE_SubAdminAreas -class DE_SubAdminAreas extends DE_WithSuboption +class DE_Admnistrativeareas2 extends DE_AddressesComponents { - protected $idfield = 'geoloc_subadministrativeareas.id'; - protected $optfield = 'geoloc_subadministrativeareas.administrativearea'; - protected $valfield = 'geoloc_subadministrativeareas.name'; - protected $from = 'geoloc_subadministrativeareas'; + protected $where = 'WHERE FIND_IN_SET(\'admnistrativeareas2\', profile_addresses_components_enum.types)'; +} - protected $ac_join = 'INNER JOIN profile_addresses ON (profile_addresses.subadministrativeAreaId = geoloc_subadministrativeareas.id)'; - protected $ac_unique = 'profile_addresses.pid'; +class DE_Admnistrativeareas3 extends DE_AddressesComponents +{ + protected $where = 'WHERE FIND_IN_SET(\'admnistrativeareas3\', profile_addresses_components_enum.types)'; } -// }}} -// {{{ class DE_Localities -class DE_Localities extends DirEnumeration +class DE_Localities extends DE_AddressesComponents { - protected $idfield = 'geoloc_localities.id'; - protected $valfield = 'geoloc_localities.name'; - protected $from = 'geoloc_localities'; + protected $where = 'WHERE FIND_IN_SET(\'localities\', profile_addresses_components_enum.types)'; +} - protected $ac_join = 'INNER JOIN profile_addresses ON (profile_addresses.localityID = geoloc_localities.id)'; - protected $ac_unique = 'profile_addresses.pid'; +class DE_Sublocalities extends DE_AddressesComponents +{ + protected $where = 'WHERE FIND_IN_SET(\'sublocalities\', profile_addresses_components_enum.types)'; } + // }}} /** JOBS diff --git a/classes/profile.php b/classes/profile.php index 5ecfca7..cf6bcd0 100644 --- a/classes/profile.php +++ b/classes/profile.php @@ -397,15 +397,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; } diff --git a/classes/userfilter.php b/classes/userfilter.php index 9dd25c6..b4bf316 100644 --- a/classes/userfilter.php +++ b/classes/userfilter.php @@ -993,44 +993,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; } diff --git a/classes/userfilter/conditions.inc.php b/classes/userfilter/conditions.inc.php index 54932f9..85d1d03 100644 --- a/classes/userfilter/conditions.inc.php +++ b/classes/userfilter/conditions.inc.php @@ -1006,17 +1006,20 @@ class UFC_Email extends UserFilterCondition // {{{ class UFC_Address abstract class UFC_Address extends UserFilterCondition { - /** Valid address type ('hq' is reserved for company addresses) + /** Valid address type */ - const TYPE_HOME = 1; - const TYPE_PRO = 2; - const TYPE_ANY = 3; + const TYPE_HOME = 1; + const TYPE_PRO = 2; + const TYPE_NON_HQ = 3; + const TYPE_HQ = 4; + const TYPE_ANY = 7; /** Text for these types */ protected static $typetexts = array( self::TYPE_HOME => 'home', self::TYPE_PRO => 'pro', + self::TYPE_HQ => 'hq', ); protected $type; @@ -1061,13 +1064,13 @@ abstract class UFC_Address extends UserFilterCondition } } if (count($types)) { - $conds[] = XDB::format($sub . '.type IN {?}', $types); + $conds[] = XDB::format('pa' . $sub . '.type IN {?}', $types); } if ($this->flags != self::FLAG_ANY) { foreach(self::$flagtexts as $flag => $text) { if ($flag & $this->flags) { - $conds[] = 'FIND_IN_SET(' . XDB::format('{?}', $text) . ', ' . $sub . '.flags)'; + $conds[] = 'FIND_IN_SET(' . XDB::format('{?}', $text) . ', pa' . $sub . '.flags)'; } } } @@ -1076,61 +1079,6 @@ abstract class UFC_Address extends UserFilterCondition } // }}} -// {{{ class UFC_AddressText -/** Select users based on their address, using full text search - * @param $text Text for filter in fulltext search - * @param $textSearchMode Mode for search (one of XDB::WILDCARD_*) - * @param $type Filter on address type - * @param $flags Filter on address flags - * @param $country Filter on address country - * @param $locality Filter on address locality - */ -class UFC_AddressText extends UFC_Address -{ - - private $text; - private $textSearchMode; - - public function __construct($text = null, $textSearchMode = XDB::WILDCARD_CONTAINS, - $type = null, $flags = self::FLAG_ANY, $country = null, $locality = null) - { - parent::__construct($type, $flags); - $this->text = $text; - $this->textSearchMode = $textSearchMode; - $this->country = $country; - $this->locality = $locality; - } - - private function mkMatch($txt) - { - return XDB::formatWildcards($this->textSearchMode, $txt); - } - - public function buildCondition(PlFilter $uf) - { - $sub = $uf->addAddressFilter(); - $conds = $this->initConds($sub, $uf->getVisibilityCondition($sub . '.pub')); - if ($this->text != null) { - $conds[] = $sub . '.text' . $this->mkMatch($this->text); - } - - if ($this->country != null) { - $subc = $uf->addAddressCountryFilter(); - $subconds = array(); - $subconds[] = $subc . '.country' . $this->mkMatch($this->country); - $subconds[] = $subc . '.countryFR' . $this->mkMatch($this->country); - $conds[] = implode(' OR ', $subconds); - } - - if ($this->locality != null) { - $subl = $uf->addAddressLocalityFilter(); - $conds[] = $subl . '.name' . $this->mkMatch($this->locality); - } - - return implode(' AND ', $conds); - } -} -// }}} // {{{ class UFC_AddressField /** Filters users based on their address, * @param $val Either a code for one of the fields, or an array of such codes @@ -1138,55 +1086,36 @@ class UFC_AddressText extends UFC_Address * @param $type Filter on address type * @param $flags Filter on address flags */ -class UFC_AddressField extends UFC_Address +class UFC_AddressComponent extends UFC_Address { - const FIELD_COUNTRY = 1; - const FIELD_ADMAREA = 2; - const FIELD_SUBADMAREA = 3; - const FIELD_LOCALITY = 4; - const FIELD_ZIPCODE = 5; + static $components = array('sublocality', 'locality', 'administrative_area_level_3', 'administrative_area_level_2', 'administrative_area_level_1', 'country'); /** Data of the filter */ private $val; private $fieldtype; + private $exact; - public function __construct($val, $fieldtype, $type = null, $flags = self::FLAG_ANY) + public function __construct($val, $fieldtype, $exact = true, $type = null, $flags = self::FLAG_ANY) { - parent::__construct($type, $flags); + if (!in_array($fieldtype, self::$components)) { + Platal::page()->killError('Invalid address field type: ' . $this->fieldtype); + } + parent::__construct($type, $flags); if (!is_array($val)) { $val = array($val); } $this->val = $val; $this->fieldtype = $fieldtype; + $this->exact = $exact; } public function buildCondition(PlFilter $uf) { - $sub = $uf->addAddressFilter(); - $conds = $this->initConds($sub, $uf->getVisibilityCondition($sub . '.pub')); - - switch ($this->fieldtype) { - case self::FIELD_COUNTRY: - $field = 'countryId'; - break; - case self::FIELD_ADMAREA: - $field = 'administrativeAreaId'; - break; - case self::FIELD_SUBADMAREA: - $field = 'subAdministrativeAreaId'; - break; - case self::FIELD_LOCALITY: - $field = 'localityId'; - break; - case self::FIELD_ZIPCODE: - $field = 'postalCode'; - break; - default: - Platal::page()->killError('Invalid address field type: ' . $this->fieldtype); - } - $conds[] = XDB::format($sub . '.' . $field . ' IN {?}', $this->val); + $sub = $uf->addAddressFilter($this->fieldtype); + $conds = $this->initConds($sub, $uf->getVisibilityCondition('pa' . $sub . '.pub')); + $conds[] = XDB::format('pace' . $sub . '.short_name IN {?}', $this->val); return implode(' AND ', $conds); } diff --git a/include/profilefields.inc.php b/include/profilefields.inc.php index 2de1e6b..8d4ef1b 100644 --- a/include/profilefields.inc.php +++ b/include/profilefields.inc.php @@ -735,8 +735,7 @@ class CompanyList } $it = XDB::iterator('SELECT pje.id, pje.name, pje.acronym, pje.url, - pa.flags, pa.text, pa.postalCode, pa.countryId, - pa.type, pa.pub + pa.flags, pa.text, pa.type, pa.pub FROM profile_job_enum AS pje LEFT JOIN profile_addresses AS pa ON (pje.id = pa.jobid AND pa.type = \'hq\') ' . $join . ' diff --git a/include/ufbuilder.inc.php b/include/ufbuilder.inc.php index e329bbc..40ad2fd 100644 --- a/include/ufbuilder.inc.php +++ b/include/ufbuilder.inc.php @@ -347,10 +347,12 @@ class UFB_AdvancedSearch extends UserFilterBuilder new UFBF_HasEmailRedirect('has_email_redirect', 'A une redirection active'), new UFBF_Dead('alive', 'En vie'), - new UFBF_Town('city', 'Ville / Code Postal'), - new UFBF_Country('countryTxt', 'country', 'Pays'), - new UFBF_AdminArea('administrativearea', 'Région'), - new UFBF_SubAdminArea('subadministrativearea', 'Département'), + new UFBF_AddressIndex('sublocality', 'Arrondissement', 'SUBLOCALITIES'), + new UFBF_AddressIndex('administrative_area_level_3', 'Canton', 'ADMNISTRATIVEAREAS3'), + new UFBF_AddressIndex('administrative_area_level_2', 'Département', 'ADMNISTRATIVEAREAS2'), + new UFBF_AddressIndex('administrative_area_level_1', 'Région', 'ADMNISTRATIVEAREAS1'), + new UFBF_AddressMixed('localityTxt', 'locality', 'Ville', 'LOCALITIES'), + new UFBF_AddressMixed('countryTxt', 'country', 'Pays', 'COUNTRIES'), new UFBF_JobCompany('entreprise', 'Entreprise'), new UFBF_JobDescription('jobdescription', 'Fonction'), @@ -1032,69 +1034,16 @@ class UFBF_Dead extends UFBF_Enum } // }}} -// {{{ class UFBF_Town -/** Retrieves a town, either from a postal code or a town name - */ -class UFBF_Town extends UFBF_Text -{ - const TYPE_TEXT = 1; - const TYPE_ZIP = 2; - const TYPE_ANY = 3; - - private $type; - private $onlycurrentfield; - - public function __construct($envfield, $formtext = '', $type = self::TYPE_ANY, $onlycurrentfield = 'only_current') - { - $this->type = $type; - $this->onlycurrentfield = $onlycurrentfield; - parent::__construct($envfield, $formtext, 2, 30); - } - - protected function buildUFC(UserFilterBuilder $ufb) - { - if ($ufb->isOn($this->onlycurrentfield)) { - $flags = UFC_Address::FLAG_CURRENT; - } else { - $flags = UFC_Address::FLAG_ANY; - } - - if (preg_match('/[0-9]/', $this->val)) { - if ($this->type & self::TYPE_ZIP) { - return new UFC_AddressField($this->val, UFC_AddressField::FIELD_ZIPCODE, UFC_Address::TYPE_ANY, $flags); - } else { - return new PFC_False(); - } - } else { - $byname = new UFC_AddressText(null, XDB::WILDCARD_CONTAINS, UFC_Address::TYPE_ANY, $flags, null, $this->val); - $byzip = new UFC_AddressField($this->val, UFC_AddressField::FIELD_ZIPCODE, UFC_Address::TYPE_ANY, $flags); - if ($this->type & self::TYPE_ANY) { - return new PFC_Or($byname, $byzip); - } else if ($this->type & self::TYPE_TEXT) { - return $byname; - } else { - return $byzip; - } - } - } - - public function getEnvFieldNames() - { - return array($this->envfield, $this->onlycurrentfield); - } -} -// }}} - -// {{{ class UFBF_Country -class UFBF_Country extends UFBF_Mixed +// {{{ class UFBF_AddressMixed +class UFBF_AddressMixed extends UFBF_Mixed { - protected $direnum = DirEnum::COUNTRIES; protected $onlycurrentfield; - public function __construct($envfieldtext, $envfieldindex, $formtext = '', $onlycurrentfield = 'only_current') + public function __construct($envfieldtext, $envfieldindex, $formtext = '', $addressfield, $onlycurrentfield = 'only_current') { parent::__construct($envfieldtext, $envfieldindex, $formtext); $this->onlycurrentfield = $onlycurrentfield; + $this->direnum = constant('DirEnum::' . $addressfield); } protected function buildUFC(UserFilterBuilder $ufb) @@ -1105,7 +1054,7 @@ class UFBF_Country extends UFBF_Mixed $flags = UFC_Address::FLAG_ANY; } - return new UFC_AddressField($this->val, UFC_AddressField::FIELD_COUNTRY, UFC_Address::TYPE_ANY, $flags); + return new UFC_AddressComponent($this->val, $this->envfieldindex, UFC_Address::TYPE_NON_HQ, $flags); } public function getEnvFieldNames() @@ -1115,47 +1064,17 @@ class UFBF_Country extends UFBF_Mixed } // }}} -// {{{ class UFBF_AdminArea -class UFBF_AdminArea extends UFBF_Index -{ - protected $direnum = DirEnum::ADMINAREAS; - protected $onlycurrentfield; - - public function __construct($envfield, $formtext = '', $onlycurrentfield = 'only_current') - { - parent::__construct($envfield, $formtext); - $this->onlycurrentfield = $onlycurrentfield; - } - - - protected function buildUFC(UserFilterBuilder $ufb) - { - if ($ufb->isOn($this->onlycurrentfield)) { - $flags = UFC_Address::FLAG_CURRENT; - } else { - $flags = UFC_Address::FLAG_ANY; - } - - return new UFC_AddressField($this->val, UFC_AddressField::FIELD_ADMAREA, UFC_Address::TYPE_ANY, $flags); - } - - public function getEnvFieldNames() - { - return array($this->envfield, $this->onlycurrentfield); - } -} -// }}} - -// {{{ class UFBF_SubAdminArea -class UFBF_SubAdminArea extends UFBF_Index +// {{{ class UFBF_AddressIndex +class UFBF_AddressIndex extends UFBF_Index { - protected $direnum = DirEnum::SUBADMINAREAS; + protected $direnum; protected $onlycurrentfield; - public function __construct($envfield, $formtext = '', $onlycurrentfield = 'only_current') + public function __construct($envfield, $formtext = '', $addressfield, $onlycurrentfield = 'only_current') { parent::__construct($envfield, $formtext); $this->onlycurrentfield = $onlycurrentfield; + $this->direnum = constant('DirEnum::' . $addressfield); } @@ -1167,7 +1086,7 @@ class UFBF_SubAdminArea extends UFBF_Index $flags = UFC_Address::FLAG_ANY; } - return new UFC_AddressField($this->val, UFC_AddressField::FIELD_SUBADMAREA, UFC_Address::TYPE_ANY, $flags); + return new UFC_AddressComponent($this->val, $this->envfield, UFC_Address::TYPE_NON_HQ, $flags); } public function getEnvFieldNames() diff --git a/templates/search/adv.form.tpl b/templates/search/adv.form.tpl index 4d47703..6596881 100644 --- a/templates/search/adv.form.tpl +++ b/templates/search/adv.form.tpl @@ -404,8 +404,8 @@ function cleanForm(f) { Géographie - Ville ou code postal - + Ville + Pays @@ -416,18 +416,6 @@ function cleanForm(f) { {icon name="table" title="Tous les pays"} - - Région, province, état… - - - - - - Département, comté… - - - -