currentLanguage = $this->Application->Phrases->LanguageId; $this->primaryLanguage = $this->Application->GetDefaultLanguageId(); } /** * Returns countries, that have states * * @return Array */ function getCountriesWithStates() { static $cache = null; if ( !isset($cache) ) { $table_name = $this->Application->getUnitConfig('country-state')->getTableName(); $sql = 'SELECT DISTINCT cname.IsoCode, cid.StateCountryId FROM ' . $table_name . ' cid JOIN ' . $table_name . ' cname ON cname.CountryStateId = cid.StateCountryId WHERE cid.StateCountryId IS NOT NULL'; $cache = $this->Conn->GetCol($sql, 'StateCountryId'); } return $cache; } /** * Checks, that country with given 3symbol ISO code has states * * @param string $country_code * @return bool */ function CountryHasStates($country_code) { return $country_code ? in_array($country_code, $this->getCountriesWithStates()) : false; } /** * Prepares states dropdown based on country selected * * @param kEvent $event * @param string $state_field * @param string $country_field */ function PopulateStates($event, $state_field, $country_field) { /** @var kDBItem $object */ $object = $event->getObject(); $country_iso = $object->GetDBField($country_field); if ( !$country_iso ) { return; } $field_options = $object->GetFieldOptions($state_field); $field_options['options'] = $this->getStates($country_iso); $object->SetFieldOptions($state_field, $field_options, $object->isVirtualField($state_field)); } /** * Returns list of given country states * * @param string $country_iso * @return Array */ public function getStates($country_iso) { $country_id = $this->getCountryStateId($country_iso, DESTINATION_TYPE_COUNTRY); if ( !$country_id ) { return Array (); } $cache_key = 'country_states[%CountryStateSerial%]'; $cache_key .= ':PL=' . $this->primaryLanguage . ':CL=' . $this->currentLanguage . ':ISO=' . $country_iso; $states = $this->Application->getCache($cache_key); if ( $states === false ) { $sql = 'SELECT IF(l' . $this->currentLanguage . '_Name = "", l' . $this->primaryLanguage . '_Name, l' . $this->currentLanguage . '_Name) AS Name, IsoCode FROM ' . $this->Application->getUnitConfig('country-state')->getTableName() . ' WHERE (Type = ' . DESTINATION_TYPE_STATE . ') AND (StateCountryId = ' . $country_id . ') ORDER BY Name ASC'; $states = $this->Conn->GetCol($sql, 'IsoCode'); $this->Application->setCache($cache_key, $states); } return $states; } /** * Returns valid state ISO code for state name and country code passed * * @param string $state_name * @param string $country_iso * @return string */ function getStateIso($state_name, $country_iso) { if ( !$this->CountryHasStates($country_iso) ) { return $state_name; } $table_name = $this->Application->getUnitConfig('country-state')->getTableName(); $country_id = $this->getCountryStateId($country_iso, DESTINATION_TYPE_COUNTRY); $sql = 'SELECT IsoCode FROM ' . $table_name . ' WHERE (Type = ' . DESTINATION_TYPE_STATE . ') AND (StateCountryId = %1$s) AND ( (IsoCode = %2$s) OR (UPPER(l%3$s_Name) = %2$s) OR (UPPER(l%4$s_Name) = %2$s) )'; $state_name = trim(mb_strtoupper($state_name)); $sql = sprintf($sql, $country_id, $this->Conn->qstr($state_name), $this->currentLanguage, $this->primaryLanguage); return $this->Conn->GetOne($sql); } /** * Checks, that entered state matches entered country * * @param kEvent $event * @param string $state_field * @param string $country_field * @param bool $auto_required * @return void */ function CheckStateField($event, $state_field, $country_field, $auto_required = true) { /** @var kDBItem $object */ $object = $event->getObject(); $country_iso = $object->GetDBField($country_field); if ( $auto_required ) { $object->setRequired($state_field, $this->CountryHasStates($country_iso)); } $state = $object->GetDBField($state_field); if ( $country_iso && $state ) { $state_iso = $this->getStateIso($state, $country_iso); if ( $state_iso !== false ) { // replace state name with it's ISO code $object->SetDBField($state_field, $state_iso); } else { // state not found by name -> report error $object->SetError($state_field, 'invalid_state', 'la_invalid_state'); } } } /** * Returns country/state id based on given iso code and it's type * * @param string $iso_code * @param int $type * @return int */ function getCountryStateId($iso_code, $type) { $config = $this->Application->getUnitConfig('country-state'); $cache_key = 'country_state_id[%CountryStateSerial%]:ISO=' . $iso_code . ';Type=' . $type; $id = $this->Application->getCache($cache_key); if ( $id === false ) { $sql = 'SELECT ' . $config->getIDField() . ' FROM ' . $config->getTableName() . ' WHERE (Type = ' . $type . ') AND (IsoCode = ' . $this->Conn->qstr($iso_code) . ')'; $id = (int)$this->Conn->GetOne($sql); $this->Application->setCache($cache_key, $id); } return $id; } /** * Returns 3 symbols ISO code from 2 symbols ISO code or otherwise, when $from_short parameter is used * * @param string $iso_code * @param bool $from_short * @return string */ function getCountryIso($iso_code, $from_short = false) { if ($from_short) { $sql = 'SELECT IsoCode FROM ' . TABLE_PREFIX . 'CountryStates WHERE ShortIsoCode = ' . $this->Conn->qstr($iso_code) . ' AND `Type` = ' . DESTINATION_TYPE_COUNTRY; } else { $sql = 'SELECT ShortIsoCode FROM ' . TABLE_PREFIX . 'CountryStates WHERE IsoCode = ' . $this->Conn->qstr($iso_code) . ' AND `Type` = ' . DESTINATION_TYPE_COUNTRY; } return $this->Conn->GetOne($sql); } }