diff --git a/autoloads/eztemplateautoload.php b/autoloads/eztemplateautoload.php index a647ed9..8bc68b9 100644 --- a/autoloads/eztemplateautoload.php +++ b/autoloads/eztemplateautoload.php @@ -7,6 +7,5 @@ $eZTemplateOperatorArray[] = array( 'script' => eZExtension::baseDirectory() . '/region/autoloads/region.php', 'class' => 'Region', - 'operator_names' => array( 'language_uri', 'region_languages', 'regions', 'in_region' ) ); - + 'operator_names' => array( 'language_uri', 'region_languages', 'regions', 'in_region', 'canonical_url', 'canonical_language_url', 'detected_region', 'detected_locale' ) ); ?> diff --git a/autoloads/region.php b/autoloads/region.php index 9ec899c..746b445 100644 --- a/autoloads/region.php +++ b/autoloads/region.php @@ -14,7 +14,7 @@ function Region() */ function operatorList() { - return array( 'region_languages', 'regions', 'language_uri', 'in_region' ); + return array( 'region_languages', 'regions', 'language_uri', 'in_region', 'canonical_url', 'canonical_language_url', 'detected_region', 'detected_locale' ); } /*! \return true to tell the template engine that the parameter list exists per operator type, @@ -23,8 +23,8 @@ function operatorList() function namedParameterPerOperator() { return true; - } - + } + /*! See eZTemplateOperator::namedParameterList */ @@ -42,10 +42,14 @@ function namedParameterList() 'regions' => array( 'siteaccessname' => array( 'type' => 'string', 'required' => true, 'default' => false ) ), - 'in_region' => array( 'region' => array( 'type' => 'string', - 'required' => true, - 'default' => false ) ), - ); + 'in_region' => array( 'region' => array( 'type' => 'string', + 'required' => true, + 'default' => false ) ), + 'canonical_url' => array(), + 'canonical_language_url' => array(), + 'detected_region' => array(), + 'detected_locale' => array() + ); } /*! @@ -53,6 +57,10 @@ function namedParameterList() */ function modify( &$tpl, &$operatorName, &$operatorParameters, &$rootNamespace, &$currentNamespace, &$operatorValue, &$namedParameters ) { + $moduleResult = $tpl->hasVariable( 'module_result' ) ? $tpl->variable( 'module_result' ) : array(); + $contentInfo = isset( $moduleResult['content_info'] ) ? $moduleResult['content_info'] : array(); + $currentNodeId = isset( $moduleResult['node_id'] ) ? (int) $moduleResult['node_id'] : 0; + switch ( $operatorName ) { case 'language_uri': @@ -76,24 +84,93 @@ function modify( &$tpl, &$operatorName, &$operatorParameters, &$rootNamespace, & case 'in_region': $regionini = eZINI::instance( 'region.ini' ); $regions = $regionini->variableArray('Regions', 'RegionCountryList'); - + $ip = ( array_key_exists( 'TESTIP', $_GET ) and ezxISO3166::validip( $_GET['TESTIP'] ) ) ? new ezxISO3166( $_GET['TESTIP']) : new ezxISO3166(); $ccode = ( array_key_exists( 'country', $_GET ) ) ? strtoupper($_GET['country']) : $ip->getCCfromIP(); eZDebug::writeDebug( $regions, 'Regions' ); eZDebug::writeDebug( $ccode, 'Country code' ); - + // CHECK THAT THE REGION EXISTS IN THE REGION GROUP if ( in_array( $ccode, $regions[$namedParameters['region']] ) && array_key_exists($namedParameters['region'], $regions) ) { $operatorValue = true; break; } - + $operatorValue = false; break; + case 'canonical_url': + if( + isset( $contentInfo['main_node_url_alias'] ) + && $contentInfo['main_node_url_alias'] + ) { + $operatorValue = $contentInfo['main_node_url_alias']; + } + break; + case 'canonical_language_url': + $return = array(); + + $node = eZContentObjectTreeNode::fetch( $currentNodeId ); + $object = false; + if( $node instanceof eZContentObjectTreeNode ) { + $object = $node->attribute( 'object' ); + } + + $translatedURLs = ezpLanguageSwitcher::setupTranslationSAList( $currentNodeId ); + $localeCountries = eZINI::instance( 'region.ini' )->variable( 'Regions', 'LocaleCountryList' ); + foreach( $translatedURLs as $sa => $translation ) { + $ini = eZSiteAccess::getIni( $sa ); + $localeCode = $ini->variable( 'RegionalSettings', 'Locale' ); + $locale = new eZLocale( $localeCode ); + if( isset( $localeCountries[ $localeCode ] ) && $localeCode != 'eng-US' ) { + $tmp = explode( '-', strtolower( $locale->attribute( 'http_locale_code' ) ) ); + $countryCode = $tmp[0]; + $languages = explode( ';', strtolower( $localeCountries[ $localeCode ] ) ); + foreach( $languages as $language ) { + $return[] = array( + 'language' => $countryCode . '-' . $language, + 'url' => $translation['url'], + 'siteaccess' => $sa + ); + } + } else { + $return[] = array( + 'language' => strtolower( $locale->attribute( 'http_locale_code' ) ), + 'url' => $translation['url'], + 'siteaccess' => $sa + ); + } + } + + $operatorValue = $return; + break; + case 'detected_region': + $operatorValue = eZINI::instance( 'site.ini' )->variable('SiteSettings','DefaultAccess'); + $systemIdentifiedRegion = ezxRegion::getRegionData(ezxISO3166::getRealIpAddr()); + $preferredRegion = $systemIdentifiedRegion['preferred_region']; + + if(array_key_exists('preferred_regions',$systemIdentifiedRegion)) { + $preferredRegion = empty($preferredRegion) ? 'eng-US' : $preferredRegion; + $systemIdentifiedSiteAccess = $systemIdentifiedRegion['preferred_regions'][$preferredRegion][0]; + + $countryNames = eZINI::instance( 'site.ini' )->variable( 'RegionalSettings', 'TranslationSA' ); + $operatorValue = array_key_exists($systemIdentifiedSiteAccess, $countryNames) ? $countryNames[$systemIdentifiedSiteAccess] : 'United States'; + } + break; + case 'detected_locale': + $operatorValue = eZINI::instance( 'site.ini' )->variable('SiteSettings','DefaultAccess'); + $systemIdentifiedRegion = ezxRegion::getRegionData(ezxISO3166::getRealIpAddr()); + $preferredRegion = $systemIdentifiedRegion['preferred_region']; + if(array_key_exists('preferred_regions',$systemIdentifiedRegion)) { + $preferredRegion = empty($preferredRegion) ? 'eng-US' : $preferredRegion; + + $operatorValue = $preferredRegion; + } + break; + } - - + + } } ?> diff --git a/classes/ezi18noperator.php b/classes/ezi18noperator.php new file mode 100644 index 0000000..0b29ae2 --- /dev/null +++ b/classes/ezi18noperator.php @@ -0,0 +1,184 @@ +Operators = array( $name, $extensionName, $dynamicName ); + $this->Name = $name; + $this->ExtensionName = $extensionName; + // d18n is a i18n alias for use with dynamic variables as input + // where you don't want ezlupdate to pick up the string + $this->DynamicName = $dynamicName; + } + + /*! + Returns the operators in this class. + */ + function operatorList() + { + return $this->Operators; + } + + /*! + \return true to tell the template engine that the parameter list exists per operator type. + */ + function namedParameterPerOperator() + { + return true; + } + + /*! + See eZTemplateOperator::namedParameterList() + */ + function namedParameterList() + { + $def = array( $this->Name => array( 'context' => array( 'type' => 'string', + 'required' => false, + 'default' => false ), + 'comment' => array( 'type' => 'string', + 'required' => false, + 'default' => '' ), + 'arguments' => array( 'type' => 'hash', + 'required' => false, + 'default' => false ), + 'locale' => array( 'type' => 'array', + 'required' => false, + 'default' => false ) ), + $this->ExtensionName => array( 'extension' => array( 'type' => 'string', + 'required' => true, + 'default' => false ), + 'context' => array( 'type' => 'string', + 'required' => false, + 'default' => false ), + 'comment' => array( 'type' => 'string', + 'required' => false, + 'default' => '' ), + 'arguments' => array( 'type' => 'hash', + 'required' => false, + 'default' => false ) ) ); + $def[ $this->DynamicName ] = $def[ $this->Name ]; + return $def; + } + + function operatorTemplateHints() + { + $def = array( $this->Name => array( 'input' => true, + 'output' => true, + 'parameters' => true, + 'element-transformation' => true, + 'transform-parameters' => true, + 'input-as-parameter' => 'always', + 'element-transformation-func' => 'i18nTrans') ); + $def[ $this->DynamicName ] = $def[ $this->Name ]; + return $def; + } + + function i18nTrans( $operatorName, &$node, $tpl, &$resourceData, + $element, $lastElement, $elementList, $elementTree, &$parameters ) + { + // i18n( $input, $context, $comment, $arguments ) + // Check if if the three first parameters are constants, if not we cannot compile it + foreach ( array_slice( $parameters, 0, 3 ) as $parameter ) + { + if ( $parameter !== null && + !eZTemplateNodeTool::isConstantElement( $parameter ) ) + { + return false; + } + } + $value = eZTemplateNodeTool::elementConstantValue( $parameters[0] ); + + $numParameters = count ( $parameters ); + $context = ( $numParameters > 1 ) ? eZTemplateNodeTool::elementConstantValue( $parameters[1] ) : null; + $comment = ( $numParameters > 2 ) ? eZTemplateNodeTool::elementConstantValue( $parameters[2] ) : null; + $locale = ( $numParameters > 4 ) ? eZTemplateNodeTool::elementConstantValue( $parameters[4] ) : null; + + if ( $numParameters < 4 ) + { + return array ( eZTemplateNodeTool::createStringElement( ezpI18n::tr( $context, $value, $comment, null ) ) ); + } + + $values = array(); + + $ini = eZINI::instance(); + if ( $ini->variable( 'RegionalSettings', 'TextTranslation' ) != 'disabled' ) + { + $language = ( $locale != null ) ? eZLocale::instance($locale)->localeFullCode() : eZLocale::instance()->localeFullCode(); + if ( $language != "eng-GB" ) // eng-GB does not need translation + { + $file = 'translation.ts'; + $ini = eZINI::instance(); + $useCache = $ini->variable( 'RegionalSettings', 'TranslationCache' ) != 'disabled'; + eZTSTranslator::initialize( $context, $language, $file, $useCache ); + + $man = eZTranslatorManager::instance(); + $newValue = $man->translate( $context, $value, $comment ); + if ( $newValue ) + { + $value = $newValue; + } + } + } + + $values[] = array( eZTemplateNodeTool::createStringElement( $value ) ); + $values[] = $parameters[3]; + + $code = '%tmp1% = array();' . "\n" . + 'foreach ( %2% as %tmp2% => %tmp3% )' . "\n" . + '{' . "\n" . + ' if ( is_int( %tmp2% ) )' . "\n" . + ' %tmp1%[\'%\' . ( (%tmp2%%9) + 1 )] = %tmp3%;' . "\n" . + ' else' . "\n" . + ' %tmp1%[%tmp2%] = %tmp3%;' . "\n" . + '}' . "\n" . + '%output% = strtr( %1%, %tmp1% );' . "\n"; + + return array( eZTemplateNodeTool::createCodePieceElement( $code, $values, false, 3 ) ); + } + + function modify( $tpl, $operatorName, $operatorParameters, $rootNamespace, $currentNamespace, &$value, &$namedParameters, $placement ) + { + switch ( $operatorName ) + { + case $this->Name: + case $this->DynamicName: + { + $context = $namedParameters['context']; + $comment = $namedParameters['comment']; + $arguments = $namedParameters['arguments']; + $locale = $namedParameters['locale']; + $value = ezpI18n::tr( $context, $value, $comment, $arguments, $locale ); + } break; + case $this->ExtensionName: + { + $extension = $namedParameters['extension']; + $context = $namedParameters['context']; + $comment = $namedParameters['comment']; + $arguments = $namedParameters['arguments']; + $value = ezpI18n::tr( $context, $value, $comment, $arguments ); + } break; + } + } + + /// \privatesection + public $Operators; + public $Name; + public $ExtensionName; +} + +?> diff --git a/classes/ezpi18n.php b/classes/ezpi18n.php new file mode 100644 index 0000000..42abcee --- /dev/null +++ b/classes/ezpi18n.php @@ -0,0 +1,148 @@ + $argumentItem ) + { + if ( is_int( $argumentKey ) ) + $replaceList['%' . ( ($argumentKey%9) + 1 )] = $argumentItem; + else + $replaceList[$argumentKey] = $argumentItem; + } + $text = strtr( $text, $replaceList ); + } + return $text; + } + + /** + * Enabled if the site.ini settings RegionalSettings/TextTranslation is set to disabled + * + * @return bool + */ + protected static function isEnabled() + { + if ( self::$isEnabled === null ) + { + $ini = eZINI::instance(); + $useTextTranslation = $ini->variable( 'RegionalSettings', 'TextTranslation' ) != 'disabled'; + self::$isEnabled = $useTextTranslation || eZTranslatorManager::dynamicTranslationsEnabled(); + } + return self::$isEnabled; + } + + /** + * Resets the state ezpI18n class. + */ + public static function reset() + { + self::$isEnabled = null; + } + + /** + * Translates the source \a $source with context \a $context and optional comment \a $comment + * and returns the translation if translations are enabled. + * Uses {@link ezpI18n::translateText()} + * + * Example: + * translate( 'content/view', 'There are %count nodes in this list out of %total total nodes.', 'Children view of nodes for whole site', array( '%count' => $c, '%total' => $t ) ); + * + * @param string $context + * @param string $source + * @param string|null $comment + * @param array|null $arguments + * @return string + */ + public static function tr( $context, $source, $comment = null, $arguments = null, $locale = null, $useCache = true ) + { + if ( self::isEnabled() ) + { + return self::translateText( $context, $source, $comment, $arguments, $locale, $useCache); + } + return self::insertArguments( $source, $arguments ); + } + + /** + * Translates the source \a $source with context \a $context and optional comment \a $comment + * and returns the translation if locale code is not eng-GB. + * Uses {@link eZTranslatorMananger::translate()} to do the actual translation + * + * Example: + * translateText( 'content/view', 'There are %count nodes in this list out of %total total nodes.', 'Children view of nodes for whole site', array( '%count' => $c, '%total' => $t ) ); + * + * @param string $context + * @param string $source + * @param string|null $comment + * @param array|null $arguments + * @return string + */ + protected static function translateText( $context, $source, $comment = null, $arguments = null, $locale = null, $useCache = null ) + { + $localeCode = ($locale !== null) ? eZLocale::instance($locale)->localeFullCode() : eZLocale::instance()->localeFullCode(); + if ( $localeCode == 'eng-GB' ) + { + // we don't have ts-file for 'eng-GB'. + return self::insertArguments( $source, $arguments ); + } + + $ini = eZINI::instance(); + if ($useCache === null) { + $useCache = $ini->variable( 'RegionalSettings', 'TranslationCache' ) != 'disabled'; + } + eZTSTranslator::initialize( $context, $localeCode, 'translation.ts', $useCache ); + + // Bork translation: Makes it easy to see what is not translated. + // If no translation is found in the eZTSTranslator, a Bork translation will be returned. + // Bork is different than, but similar to, eng-GB, and is enclosed in square brackets []. + $developmentMode = $ini->variable( 'RegionalSettings', 'DevelopmentMode' ) != 'disabled'; + if ( $developmentMode ) + { + eZBorkTranslator::initialize(); + } + + $man = eZTranslatorManager::instance(); + $trans = $man->translate( $context, $source, $comment ); + if ( $trans !== null ) { + return self::insertArguments( $trans, $arguments ); + } + + if ( $comment != null and strlen( $comment ) > 0 ) + eZDebug::writeDebug( "Missing translation for message in context: '$context' with comment: '$comment'. The untranslated message is: '$source'", __METHOD__ ); + else + eZDebug::writeDebug( "Missing translation for message in context: '$context'. The untranslated message is: '$source'", __METHOD__ ); + + return self::insertArguments( $source, $arguments ); + } +} + +?> diff --git a/classes/ezplanguageswitcher.php b/classes/ezplanguageswitcher.php index ecb854a..d2021f6 100644 --- a/classes/ezplanguageswitcher.php +++ b/classes/ezplanguageswitcher.php @@ -78,12 +78,11 @@ protected function isUrlPointingToModule( $url ) { // Grab the first URL element, representing the possible module name $urlElements = explode( '/', $url ); - $moduleName = $urlElements[0]; // Look up for a match in the module list $moduleIni = eZINI::instance( 'module.ini' ); $availableModules = $moduleIni->variable( 'ModuleSettings', 'ModuleList' ); - return in_array( $moduleName, $availableModules, true ); + return in_array( $urlElements[0], $availableModules, true ) || in_array( $urlElements[1], $availableModules, true ); } /** @@ -121,21 +120,44 @@ public function destinationUrl() { $nodeId = eZURLAliasML::fetchNodeIDByPath( $this->origUrl ); } - + $saIni = $this->getSiteAccessIni(); $siteLanguageList = $saIni->variable( 'RegionalSettings', 'SiteLanguageList' ); if( count( $siteLanguageList ) === 0 ) { - $siteLanguageList = array( eZINI::instance()->variable( 'RegionalSettings', 'ContentObjectLocale' ) ); + $siteLanguageList = array( $saIni->variable( 'RegionalSettings', 'ContentObjectLocale' ) ); } foreach ($siteLanguageList as $siteLanguage) { - $destinationElement = eZURLAliasML::fetchByAction( 'eznode', $nodeId, true, false ); + $destinationElement = eZURLAliasML::fetchByAction( 'eznode', $nodeId, $siteLanguage, false ); if ( !empty( $destinationElement ) || ( isset( $destinationElement[0] ) && ( $destinationElement[0] instanceof eZURLAliasML ) ) ) { break; } } + if( + count( $saIni->variable( 'RegionalSettings', 'SiteLanguageList' ) ) === 0 + && count( $destinationElement ) === 0 + ) { + $siteLanguageList = array( eZINI::instance()->variable( 'RegionalSettings', 'ContentObjectLocale' ) ); + $destinationElement = eZURLAliasML::fetchByAction( 'eznode', $nodeId, true, false ); + if( count( $destinationElement ) > 1 ) { + $node = eZContentObjectTreeNode::fetch( $nodeId ); + $object = $node->attribute( 'object' ); + $mask = $object->attribute( 'initial_language_id' ); +/* + $lang = eZContentLanguage::fetchByLocale( $siteLanguageList[0] ); + $mask = (int) $lang->attribute( 'id' ); +*/ + foreach( $destinationElement as $el ) { + if( ( $mask & (int) $el->attribute( 'lang_mask' ) ) > 0 ) { + $destinationElement[0] = $el; + break; + } + } + } + } + if ( empty( $destinationElement ) || ( !isset( $destinationElement[0] ) && !( $destinationElement[0] instanceof eZURLAliasML ) ) ) { // If the return of fetchByAction is empty, it can mean a couple @@ -243,21 +265,49 @@ public static function setupTranslationSAList( $url = null ) return array(); } + $regionIni = eZINI::instance( 'region.ini' ); + $directURL = in_array( + $regionIni->variable( 'Settings', 'DirectURL' ), + array( 'yes', 'true', 'enabled' ) + ); $ret = array(); $translationSiteAccesses = $ini->variable( 'RegionalSettings', 'TranslationSA' ); + eZDebug::writeDebug($directURL,'directURL'); foreach ( $translationSiteAccesses as $siteAccessName => $translationName ) { - $switchLanguageLink = "/switchlanguage/to/{$siteAccessName}/"; - if ( $url !== null && ( is_string( $url ) || is_numeric( $url ) ) ) - { - $switchLanguageLink .= $url; + if( $directURL ) { + $langSwitch = self::getLangSwitcher(); + $langSwitch->setOrigUrl( $url ); + $langSwitch->setDestinationSiteAccess( $siteAccessName ); + $langSwitch->process(); + $switchLanguageLink = $langSwitch->destinationUrl(); + } else { + $switchLanguageLink = "/switchlanguage/to/{$siteAccessName}/"; + if ( $url !== null && ( is_string( $url ) || is_numeric( $url ) ) ) + { + $switchLanguageLink .= $url; + } } $ret[$siteAccessName] = array( 'url' => $switchLanguageLink, - 'text' => $translationName + 'text' => $translationName, + 'locale' => eZSiteAccess::getIni( $siteAccessName )->variable( 'RegionalSettings', 'ContentObjectLocale' ) ); } return $ret; } + + public static function getLangSwitcher() { + $handlerOptions = new ezpExtensionOptions(); + $handlerOptions->iniFile = 'site.ini'; + $handlerOptions->iniSection = 'RegionalSettings'; + $handlerOptions->iniVariable = 'LanguageSwitcherClass'; + $handlerOptions->handlerParams = array(); + return eZExtension::getHandlerClass( $handlerOptions ); + } + + public function setOrigUrl( $url ) { + $this->origUrl = $url; + } } ?> \ No newline at end of file diff --git a/classes/ezxISO3166.php b/classes/ezxISO3166.php index 54118d7..1c7693e 100644 --- a/classes/ezxISO3166.php +++ b/classes/ezxISO3166.php @@ -19,12 +19,16 @@ static function validip( $ip ) $reserved_ips = array( array( '0.0.0.0' , - '2.255.255.255' + '0.255.255.255' ) , array( '10.0.0.0' , '10.255.255.255' ) , + array( + '100.64.0.0' , + '100.127.255.255' + ) , array( '127.0.0.0' , '127.255.255.255' @@ -37,16 +41,40 @@ static function validip( $ip ) '172.16.0.0' , '172.31.255.255' ) , + array( + '192.0.0.0' , + '192.0.0.7' + ) , array( '192.0.2.0' , '192.0.2.255' ) , + array( + '192.88.99.0' , + '192.88.99.255' + ) , array( '192.168.0.0' , '192.168.255.255' ) , + array( + '198.18.0.0' , + '198.19.255.255' + ) , + array( + '198.51.100.0' , + '198.51.100.255' + ) , + array( + '203.0.113.0' , + '203.0.113.255' + ) , + array( + '224.0.0.0' , + '239.255.255.255' + ) , array( - '255.255.255.0' , + '240.0.0.0' , '255.255.255.255' ) ); diff --git a/classes/ezxregion.php b/classes/ezxregion.php index b5b90ca..37521c4 100644 --- a/classes/ezxregion.php +++ b/classes/ezxregion.php @@ -3,176 +3,6 @@ class ezxRegion { - /** - * Returns Region information for the current user/ip... - * - * @return array Returns an array with keys - */ - static function load( $SessionName, $redirectRoot = false, $url_excludes = array() ) - { - if ( eZSys::isShellExecution() ) - { - return; - } - if ( self::isBot() ) - { - return; - } - $urlCfg = new ezcUrlConfiguration(); - $urlCfg->script = 'index.php'; - $url = new ezcUrl( ezcUrlTools::getCurrentUrl(), $urlCfg ); - eZDebug::writeDebug($url,'url object'); - //exit(); - $params = $url->getParams(); - - eZDebug::writeDebug($params, 'params'); - - $url_excludes = array_merge( $url_excludes, eZINI::instance( 'region.ini' )->variable( 'Settings', 'URLExcludes' ) ); - # Checking for excluded URLs - $current_url = implode( '/', $params ); - if ( count( $url_excludes ) > 0 ) - { - foreach ( $url_excludes as $exclude ) - { - if ( preg_match( '#^([^/]*/){0,1}' . $exclude . '#', $current_url ) ) - { - return; - } - } - } - - if ( ! is_array( $SessionName ) && $SessionName == '' ) - { - $SessionName = 'eZSESSID'; - } - $foundSessionName = false; - if ( is_array( $SessionName ) ) - { - eZDebug::writeDebug('isArray','Session Name'); - foreach ( $SessionName as $name ) - { - foreach ( $_COOKIE as $cookieName => $cookieValue ) - { - if ( strpos( $cookieName, $SessionName ) !== false ) - { - $foundSessionName = true; - } - } - - if ( $foundSessionName ) - { - if ( $redirectRoot and array_key_exists( 'EZREGION', $_COOKIE ) and - is_array( $params ) and count( $params ) == 0 and - file_exists( 'settings/siteaccess/' . $_COOKIE['EZREGION'] ) ) - { - $redirectWithCookie = true; - } - else - { - eZDebug::writeDebug('no cookies', 'Redirect'); - return; - } - } - } - } - else - { - eZDebug::writeDebug('isNotArray', 'Session Name'); - foreach ( $_COOKIE as $cookieName => $cookieValue ) - { - if ( strpos( $cookieName, $SessionName ) !== false ) - { - $foundSessionName = true; - } - } - - if ( $foundSessionName ) - { - if ( $redirectRoot and array_key_exists( 'EZREGION', $_COOKIE ) and - is_array( $params ) && count( $params ) == 0 and - file_exists( 'settings/siteaccess/' . $_COOKIE['EZREGION'] ) ) - { - $redirectWithCookie = true; - } - else - { - eZDebug::writeDebug('redirect', 'no cookies'); - return; - } - } - } - - if ( isset( $params[0] ) and file_exists( 'settings/siteaccess/' . $params[0] ) ) - { - eZDebug::writeDebug('exists', 'Params & siteaccess'); - $siteaccess = $params[0]; - if ( array_key_exists( 'EZREGION', $_COOKIE ) and - $_COOKIE['EZREGION'] === $siteaccess ) - { - return; - } - } - else - { - eZDebug::writeDebug('Params & siteaccess', 'non-existant'); - if ( isset( $redirectWithCookie ) && $redirectWithCookie === true ) - { - $siteaccess = $_COOKIE['EZREGION']; - } - else - { - $siteaccess = false; - } - } - - if ( isset( $params[0] ) and $params[0] == 'ezinfo' and isset( $params[1] ) and $params[1] == 'is_alive' ) - { - return; - } - if ( ( isset( $params[0] ) and - $params[0] == 'region' and $params[1] == 'index' ) or - ( $siteaccess and isset( $params[1] ) and - $params[1] == 'region' and isset( $params[1] ) and - $params[2] == 'index' ) ) - { - return; - } - if ( $siteaccess ) - { - $paramnew = array( - $siteaccess , - 'region' , - 'index' , - $siteaccess - ); - } - else - { - $paramnew = array( - 'region' , - 'index' - ); - } - $query = $url->getQuery(); - $params = $url->path; - if ( $siteaccess ) - { - array_shift( $params ); - } - - if ( count( $params ) ) - { - $query['URL'] = join( '/', $params ); - } - setcookie( "COOKIETEST", 1, time() + 3600 * 24 * 365, '/' ); - $query['COOKIETEST'] = 1; - - $url->setQuery( $query ); - $url->params = $paramnew; - header( 'Location: ' . $url->buildUrl() ); - eZExecution::cleanExit(); - } - static function isBot() { $bot_list = array( @@ -318,14 +148,14 @@ static function getRegionData( $address = null, $ccode = null, $lcode = null ) ); } - public static function getRegionURL( $URLPath ) { - if ( array_key_exists( 'EZREGION', $_COOKIE ) ) + public static function getRegionURL( $URLPath, $checkCookie=true ) { +/* if ( array_key_exists( 'EZREGION', $_COOKIE ) && $checkCookie) { eZDebug::writeDebug( $_COOKIE['EZREGION'], 'region cookie'); $selection = $_COOKIE['EZREGION']; } else - { + {*/ $lang = ( isset( $_GET['lang'] ) ) ? $_GET['lang'] : null; if ( array_key_exists( 'TESTIP', $_GET ) and ezxISO3166::validip( $_GET['TESTIP'] ) ) { @@ -336,7 +166,7 @@ public static function getRegionURL( $URLPath ) { elseif ( array_key_exists( 'country', $_GET ) ) { $regiondata = ezxRegion::getRegionData( null , $_GET['country'], $lang); - eZDebug::writeDebug( $_GET['country'], 'TEST IP ADDRESS' ); + eZDebug::writeDebug( $_GET['country'], 'TEST COUNTRY' ); eZDebug::writeDebug( $regiondata, 'TEST REGIONAL DATA' ); } else @@ -344,7 +174,7 @@ public static function getRegionURL( $URLPath ) { $regiondata = ezxRegion::getRegionData( ezxISO3166::getRealIpAddr() ); eZDebug::writeDebug( ezxISO3166::getRealIpAddr(), 'REMOTE IP ADDRESS' ); } - setcookie("EZREGION", $regiondata['preferred_region'], time()+3600*24*365 , '/' ); +// setcookie("EZREGION", $regiondata['preferred_region'], time()+3600*24*365 , '/' ); if ( array_key_exists( 'preferred_region', $regiondata ) ) { @@ -354,7 +184,7 @@ public static function getRegionURL( $URLPath ) { { $selection = false; } - } +// } $siteini = eZINI::instance( "site.ini"); $destinationSiteAccess = $siteini->variable('RegionalSettings', 'LanguageSA'); @@ -384,9 +214,14 @@ public static function getRegionURL( $URLPath ) { public static function requestInput( $uri ) { $mathType = (int) $GLOBALS['eZCurrentAccess']['type']; + //Check region only if this cookie is not set + // self::checkRegion(); // MFH: why do this check? + + $ini = eZINI::instance( 'site.ini' ); + if( count( $GLOBALS['eZCurrentAccess']['uri_part'] ) == 0 - && $GLOBALS['eZCurrentAccess']['name'] == eZINI::instance( 'site.ini' )->variable( 'SiteSettings', 'DefaultAccess' ) + && $GLOBALS['eZCurrentAccess']['name'] == $ini->variable( 'SiteSettings', 'DefaultAccess' ) ) { $p = array( 'Parameters' => array( $uri->uriString() ), @@ -397,5 +232,57 @@ public static function requestInput( $uri ) { header( 'Location: ' . $url ); eZExecution::cleanExit(); } +/* else { + $currentRegion = eZINI::instance( 'site.ini' )->variable( 'RegionalSettings', 'Locale' ); + setcookie( 'EZREGION', $currentRegion, time()+3600*24*365 , '/' ); + }*/ } -} \ No newline at end of file + + public static function checkRegion($forceCheck = false) { + + $result = array( + 'RegionWarning' => false, + 'RedirectSiteAccess' => false, + 'PreferredRegion' => false + ); + + $ignoreCheck = false; + $tempUrl = $GLOBALS['eZURIRequestInstance']->OriginalURI; + + if (!$forceCheck) { + $nodeId = eZURLAliasML::fetchNodeIDByPath( $tempUrl ); + + //Check the region only for site pages + if(!$nodeId) { + $ignoreCheck = true; + } + } + + if (!$ignoreCheck) { + + $siteAccessRequested = $GLOBALS['eZCurrentAccess']['name']; + $systemIdentifiedRegion = self::getRegionData(ezxISO3166::getRealIpAddr()); + $preferredRegion = $systemIdentifiedRegion['preferred_region']; + $systemIdentifiedSiteAccess = $systemIdentifiedRegion['preferred_regions'][$preferredRegion][0]; + + + if ($systemIdentifiedSiteAccess != $siteAccessRequested) { + $result['RegionWarning'] = true; + + //Get system identified SA path for URL + $ezURIInstance = $GLOBALS['eZURIRequestInstance']; + $originalUri = $ezURIInstance->OriginalURI; + $listOfTranslationsForURL = ezpLanguageSwitcher::setupTranslationSAList($originalUri); + + $systemIdentifiedURL = $listOfTranslationsForURL[$systemIdentifiedSiteAccess]['url']; + + $result['RedirectSiteAccess'] = $systemIdentifiedSiteAccess; + $result['PreferredRegion'] = $preferredRegion; + + } + } + + return $result; + + } +} diff --git a/design/standard/javascript/region.js b/design/standard/javascript/region.js new file mode 100644 index 0000000..a70b7bd --- /dev/null +++ b/design/standard/javascript/region.js @@ -0,0 +1,101 @@ +// Query current region via AJAX +$(document).ready(function() { + + $(".languages-nav-holder a").click(function() { + setRegionWarningShownFlag(); + }); + + if (isCheckForThisRegionRequired(siteAccessBaseUrl) && !hasRegionWarningBeenShown()) { + checkRegion(); + } + + + function hasRegionWarningBeenShown() { + var regionWarningShown = sessionStorage.getItem("regionWarningShown"); + + if (regionWarningShown == null || regionWarningShown == 'false') { + return false; + } else { + return true; + } + } + + function setRegionWarningShownFlag() { + sessionStorage.setItem('regionWarningShown', 'true'); + } + + function setAlreadyCheckedForRegion(siteAccessBaseUrl) { + var previouslyCheckedSiteAccess = sessionStorage.setItem("lastRegionChecked", siteAccessBaseUrl); + } + + + function isCheckForThisRegionRequired(siteAccessBaseUrl) { + // prevent repeated region checking by storing the last siteaccess checked and only checking if this siteaccess doesn't match that one + var previouslyCheckedSiteAccess = sessionStorage.getItem("lastRegionChecked"); + + if (previouslyCheckedSiteAccess == null) { + // no previous siteaccess check, continue + return true; + } + + if (previouslyCheckedSiteAccess != siteAccessBaseUrl) { + return true; + } else { + return false; + } + } + + function checkRegion() { + + $.ajax({ + url: regionCheckUrl, + cache: false, + method: 'get', + dataType: 'json', + data: { href: window.location.href } + }) + .done( function(result) { + //console.log("/region/check AJAX returned. Result: " + JSON.stringify(result)); + + if(result != null) { + var response = result; + if (typeof response == 'object') { + + setAlreadyCheckedForRegion(siteAccessBaseUrl); + + var redirectTo = response.redirectTo; + if (redirectTo != null) { + + // replace text copy in dialog with content from target (detected) language + + setRegionWarningShownFlag(); // region warning has been shown, do not show again. + + $("#select-your-region-prompt").text(response.selectYourRegionPrompt); + + $(document).on('click touchstart', '.ui-dialog-buttonset button:first', function (e) { + e.preventDefault(); + location.href = response.redirectTo; + $("#dialog-confirm").dialog("close"); + }); + $(document).on('click touchstart', '.ui-dialog-buttonset button:eq(1)', function (e) { + e.preventDefault(); + $("#dialog-confirm").dialog("close"); + }); + + $("#dialog-confirm").dialog({ + resizable: false, + height: 340, + width: 400, + modal: true, + buttons: [{text: response.goToDetectedRegionPrompt}, {text: response.continueToRegionPrompt}] + }); + } + } + } + }); + } + +}); + + + diff --git a/design/standard/templates/region_alert.tpl b/design/standard/templates/region_alert.tpl new file mode 100644 index 0000000..249c144 --- /dev/null +++ b/design/standard/templates/region_alert.tpl @@ -0,0 +1,8 @@ + + +
diff --git a/doc/README b/doc/README index 8cde71d..5a68590 100644 --- a/doc/README +++ b/doc/README @@ -1,16 +1,19 @@ REGION EXTENSION -================ - -Region extension =============================================================================== + Original Author: Bj?rn Dieding, http://www.xrow.com -Additions by: Geoff Bentley, Serhey Dolgushev +Additions by: Geoff Bentley, Serhey Dolgushev, Raghu Dontikurthi The region extension redirects a user to a siteaccess based on his ip address. This can be done in the background (the ip address is checked in the database) automatically, or the user can choose a country siteaccess in a specific pagelayout. +Features +-------- + * Multi-country regions + * Region alert (when the region detected differs from the current region) + This extension includes GeoLite data created by MaxMind, available from http://maxmind.com/ @@ -65,4 +68,16 @@ Template operators - otherwise returns false - works with 'TESTIP' and 'country' GET variables listed above, for testing purposes +Region alert +============ +This feature pops up a jQueryUI dialog when the region a user is visiting does not match their geo-detected region. They are offered the choice of continuing to the selected region or going to their geo-detected region. + +To install: +1. Uncomment jquery and jqueryUI in settings/design.ini.append.php or ensure these are available on the pages you want to apply this to. +2. Add {include uri="design:region_alert.tpl"} to your footer tpl or on the pages you want to apply it to. +3. Add the following to settings/override/site.ini.append.php: + + [RoleSettings] + PolicyOmitList[]=region/check + ?> diff --git a/modules/region/module.php b/modules/region/module.php index b4b0903..0533de8 100644 --- a/modules/region/module.php +++ b/modules/region/module.php @@ -1,12 +1,23 @@ "Language selector", - "variable_params" => true, - "function" => array( - "script" => "index.php", - "params" => array( ) ) ); + "variable_params" => true ); $ViewList = array(); $ViewList["index"] = array( "script" => "index.php"); +$ViewList["check"] = array( + "functions" => array( 'regioncheck' ), + "script" => "regioncheck.php"); + +$ViewList["foruserip"] = array( + "functions" => array( 'foruserip' ), + "script" => "userregion.php"); + +$FunctionList = array( + 'regioncheck' => array(), + 'foruserip' => array() +); + + ?> diff --git a/modules/region/regioncheck.php b/modules/region/regioncheck.php new file mode 100644 index 0000000..a8f371e --- /dev/null +++ b/modules/region/regioncheck.php @@ -0,0 +1,59 @@ + null, + "version" => 1 +); + +$regionCheckResult = ezxRegion::checkRegion(true); + +//Check for 'region mismatch' session variable +if ($regionCheckResult['RegionWarning']) { + + $href = $_GET['href']; + if (!$href) { + return; + } + + $targetSiteaccess = $regionCheckResult['RedirectSiteAccess']; + $currentSiteaccess = $GLOBALS['eZCurrentAccess']['name']; + + $urlPath = preg_replace("/http(s?):\/\/[^\/]*/", "", $href); // remove the http:// and port + $urlPathFragments = array_filter(explode('/', $urlPath)); + $urlPathFragments = array_slice($urlPathFragments, 1); // remove the siteaccess name + $urlPath = implode('/', $urlPathFragments); // recombine to form a path without server & siteaccess + + $redirectURL = ezxRegion::getRegionURL('/', false) . $urlPath; + + if ($targetSiteaccess != $currentSiteaccess) { + $result['redirectTo'] = $redirectURL; + $result['currentSiteaccess'] = $currentSiteaccess; + $result['targetSiteaccess'] = $targetSiteaccess; + + // grab translations for dialog fields (for detected locale) + $detectedLocale = $regionCheckResult['PreferredRegion']; + + $countryNames = eZINI::instance( 'site.ini' )->variable( 'RegionalSettings', 'TranslationSA' ); + $preferredRegionName = $countryNames[$targetSiteaccess]; + $currentRegionName = $countryNames[$currentSiteaccess]; + + $result['goToDetectedRegionPrompt'] = regionCheckI18NLookup('Go to our %region site', array('%region' => $preferredRegionName), $detectedLocale); + $result['continueToRegionPrompt'] = regionCheckI18NLookup('Continue to our %region site', array('%region' => $currentRegionName), $detectedLocale); + $result['selectYourRegionPrompt'] = regionCheckI18NLookup('Select your region', null, $detectedLocale); + } +} + +function regionCheckI18NLookup($i18NKey, $arguments, $locale) { + + $value = ezpI18n::tr( 'region', $i18NKey, false, $arguments, $locale, false ); + return $value; + +} + +header('Content-Type: application/json'); +$resultJson = json_encode($result); +print_r($resultJson); + +eZExecution::cleanExit(); diff --git a/modules/region/userregion.php b/modules/region/userregion.php new file mode 100644 index 0000000..b4bab8d --- /dev/null +++ b/modules/region/userregion.php @@ -0,0 +1,13 @@ + diff --git a/settings/region.ini b/settings/region.ini index 7080d41..88bce51 100644 --- a/settings/region.ini +++ b/settings/region.ini @@ -4,6 +4,7 @@ SetCurrency=disabled #If the Country Code is not in the IP database use this default code #format is ISO3166-alpha2, e.g. us, gb or de DefaultCountryCode=gb +DirectURL=enabled #Array of URLs to exclude from the region functionality #URLExcludes[]=ezwebin_site_admin URLExcludes[] diff --git a/translations/chi-CN/translation.ts b/translations/chi-CN/translation.ts new file mode 100644 index 0000000..6c30a9f --- /dev/null +++ b/translations/chi-CN/translation.ts @@ -0,0 +1,19 @@ + + +