[TYPO3-core] RFC: fix feature request #568

Wolfgang Klinger wolfgang at stufenlos.net
Thu Feb 2 10:48:37 CET 2006


 *hiya!*

 On Wed, 25 Jan 2006, Bernhard Kraft wrote the following:
> I discussed this with Michael and I (we) are ok with this. Better one hook class
> for a single class when it makes sense (like in this case).
> 
> It came out that it would be the best to move the one "device_class" hook up like
> you did but add another hook (yes ! 2 hooks right beneath each other) below the
> original one but the second one using the "shared" hook class.
> 
> Mark the old one as "deprecated" and state that it will be removed soon. Somebody (Wolfgang, me?)
> should check a complete mirror of TER (when TER2 is here and load doesn't get to high by that)
> for uses of this hook and inform the extension authors.

 See attachment, I hope it's ok now.


 kind regards
 Wolfgang

-------------- next part --------------
--- TYPO3core/t3lib/class.t3lib_matchcondition.php	2006-02-02 08:40:53.000000000 +0100
+++ TYPO3core_testing/t3lib/class.t3lib_matchcondition.php	2006-02-02 10:39:20.000000000 +0100
@@ -80,6 +80,62 @@
 
 	var $altRootLine=array();
 
+	var $hookObjectsArr = array();
+
+	function __construct() {
+		global $TYPO3_CONF_VARS;
+
+		// usage (ext_localconf.php): 
+		// $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php'][] = 'EXT:my_ext/class.browserinfo.php:MyBrowserInfoClass';
+		if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php'])) {
+			foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php'] as $classRef) {
+				$this->hookObjectsArr[] = &t3lib_div::getUserObj($classRef, '');
+			}
+		}
+	}
+
+	function t3lib_matchCondition() {
+		$this->__construct();
+	}
+	
+	function match($condition_line) {
+		if ($this->matchAll) {
+			return true;
+		}
+		if (count($this->matchAlternative))	{
+			return in_array($condition_line, $this->matchAlternative);
+		}
+
+		// Getting the value from inside of the wrapping 
+		// square brackets of the condition line:
+		$insideSqrBrackets = substr(trim($condition_line), 1, strlen($condition_line) - 2);
+
+		// The "weak" operator "||" (OR) takes precedence:
+		// backwards compatible, [XYZ][ZYX] does still work as OR
+		$orParts = preg_split('/\]\s*(\|\|){0,1}\s*\[/',$insideSqrBrackets);
+		foreach($orParts as $partString) {
+			$matches = false;
+
+			// Splits by the "&&" (AND) operator:
+			$andParts = preg_split('/\]\s*&&\s*\[/',$partString);
+			foreach($andParts as $condStr) {
+				$matches = $this->evalConditionStr($condStr);
+				// only true AND true = true
+				if (false === $matches) {
+					break;
+				}
+			}
+
+			// true OR false = true
+			if (true === $matches) {
+				break;
+			}
+		}
+
+		return $matches;
+	}
+
+
 	/**
 	 * Evaluates a TypoScript condition given as input, eg. "[browser=net][...(other conditions)...]"
 	 *
@@ -88,29 +144,19 @@
 	 * @see t3lib_tsparser::parse()
 	 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=292&cHash=c6c7d43d2f
 	 */
-	function match($string)	{
+	function evalConditionStr($string)	{
 		if ( !is_array( $this->altRootLine ) ) {
 			$this->altRootLine = array();
 		}
-
-		if ($this->matchAll)	return true;
-		if (count($this->matchAlternative))	{
-			return in_array($string,$this->matchAlternative);
-		}
-
-		if (!$this->browserInfoArray)	{
-			$this->browserInfoArray = $this->browserInfo(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
+		list($key, $value) = explode('=', $string, 2);
+		$key = trim($key);
+		if (stristr(',browser,version,system,useragent,', ",$key,")) {
+			$browserInfo = $this->browserInfo(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
 		}
-		$browserInfo = $this->browserInfoArray;
-		$string = trim($string);
-		$string = substr($string,1,strlen($string)-2);
-		$parts = explode('][',$string);
-		foreach ($parts as $val)	{
-			$pcs = explode('=',$val,2);
-			$switchKey = trim($pcs[0]);
-			switch($switchKey)	{
+		$value = trim($value);
+		switch ($key) {
 				case 'browser':
-					$values = explode(',',$pcs[1]);
+				$values = explode(',',$value);
 					while(list(,$test)=each($values))	{
 						if (strstr($browserInfo['browser'].$browserInfo['version'],trim($test)))	{
 							return true;
@@ -118,10 +164,10 @@
 					}
 				break;
 				case 'version':
-					$values = explode(',',$pcs[1]);
+				$values = explode(',',$value);
 					while(list(,$test)=each($values))	{
 						$test = trim($test);
-						if ($test)	{
+					if (strlen($test)) {
 							if (strcspn($test,'=<>')==0)	{
 								switch(substr($test,0,1))	{
 									case '=':
@@ -141,38 +187,38 @@
 					}
 				break;
 				case 'system':
-					$values = explode(',',$pcs[1]);
+				$values = explode(',',$value);
 					while(list(,$test)=each($values))	{
 						$test = trim($test);
-						if ($test)	{
+					if (strlen($test)) {
 							if (strpos(' '.$browserInfo['system'],$test)==1)	{return true;}
 						}
 					}
 				break;
 				case 'device':
-					$values = explode(',',$pcs[1]);
+				$values = explode(',',$value);
 					if (!isset($this->deviceInfo))	{
 						$this->deviceInfo = $this->whichDevice(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
 					}
 					while(list(,$test)=each($values))	{
 						$test = trim($test);
-						if ($test)	{
+					if (strlen($test)) {
 							if ($this->deviceInfo==$test)	{return true;}
 						}
 					}
 				break;
 				case 'useragent':
-					$test = trim($pcs[1]);
-					if ($test)	{
+				$test = trim($value);
+				if (strlen($test)) {
 						return $this->matchWild($browserInfo['useragent'],$test);
 					}
 				break;
 				case 'language':
-					$values = explode(',',$pcs[1]);
+				$values = explode(',',$value);
 					while(list(,$test)=each($values))	{
 						$test = trim($test);
-						if ($test)	{
-							if (ereg('^\*.+\*$',$test))	{
+					if (strlen($test)) {
+						if (preg_match('/^\*.+\*$/',$test))	{
 								$allLanguages = split('[,;]',t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE'));
 								if (in_array(substr($test,1,-1), $allLanguages))	{return true;}
 							} else {
@@ -182,10 +228,10 @@
 					}
 				break;
 				case 'IP':
-					if (t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $pcs[1]))	{return true;}
+				if (t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $value))	{return true;}
 				break;
 				case 'hostname':
-					if (t3lib_div::cmpFQDN(t3lib_div::getIndpEnv('REMOTE_ADDR'), $pcs[1]))  {return true;}
+				if (t3lib_div::cmpFQDN(t3lib_div::getIndpEnv('REMOTE_ADDR'), $value))  {return true;}
 				break;
 					// hour, minute, dayofweek, dayofmonth, month
 				case 'hour':
@@ -194,7 +240,7 @@
 				case 'dayofmonth':
 				case 'month':
 					$theEvalTime = $GLOBALS['SIM_EXEC_TIME'];	// In order to simulate time properly in templates.
-					switch($switchKey)	{
+				switch($key) {
 						case 'hour':		$theTestValue = date('H',$theEvalTime);	break;
 						case 'minute':		$theTestValue = date('i',$theEvalTime);	break;
 						case 'dayofweek':	$theTestValue = date('w',$theEvalTime);	break;
@@ -203,22 +249,22 @@
 					}
 					$theTestValue = intval($theTestValue);
 						// comp
-					$values = explode(',',$pcs[1]);
+				$values = explode(',',$value);
 					reset($values);
 					while(list(,$test)=each($values))	{
 						$test = trim($test);
 						if (t3lib_div::testInt($test))	{$test='='.$test;}
-						if ($test)	{
+					if (strlen($test)) {
 							if ($this->testNumber($test,$theTestValue)) {return true;}
 						}
 					}
 				break;
 				case 'usergroup':
 					if ($GLOBALS['TSFE']->gr_list!='0,-1')	{		// '0,-1' is the default usergroups when not logged in!
-						$values = explode(',',$pcs[1]);
+					$values = explode(',',$value);
 						while(list(,$test)=each($values))	{
 							$test = trim($test);
-							if ($test)	{
+						if (strlen($test)) {
 								if ($test=='*' || t3lib_div::inList($GLOBALS['TSFE']->gr_list,$test))	{return true;}
 							}
 						}
@@ -226,20 +272,20 @@
 				break;
 				case 'loginUser':
 					if ($GLOBALS['TSFE']->loginUser)	{
-						$values = explode(',',$pcs[1]);
+					$values = explode(',',$value);
 						while(list(,$test)=each($values))	{
 							$test = trim($test);
-							if ($test)	{
+						if (strlen($test)) {
 								if ($test=='*' || !strcmp($GLOBALS['TSFE']->fe_user->user['uid'],$test))	{return true;}
 							}
 						}
 					}
 				break;
 				case 'globalVar':
-					$values = explode(',',$pcs[1]);
+				$values = explode(',',$value);
 					while(list(,$test)=each($values))	{
 						$test = trim($test);
-						if ($test)	{
+					if (strlen($test)) {
 							$point = strcspn($test,'=<>');
 							$theVarName = substr($test,0,$point);
 							$nv = $this->getGP_ENV_TSFE(trim($theVarName));
@@ -250,10 +296,10 @@
 					}
 				break;
 				case 'globalString':
-					$values = explode(',',$pcs[1]);
+				$values = explode(',',$value);
 					while(list(,$test)=each($values))	{
 						$test = trim($test);
-						if ($test)	{
+					if (strlen($test)) {
 							$point = strcspn($test,'=');
 							$theVarName = substr($test,0,$point);
 							$nv = $this->getGP_ENV_TSFE(trim($theVarName));
@@ -264,7 +310,7 @@
 					}
 				break;
 				case 'treeLevel':
-					$values = explode(',',$pcs[1]);
+				$values = explode(',',$value);
 					$theRootLine = is_array($GLOBALS['TSFE']->tmpl->rootLine) ? $GLOBALS['TSFE']->tmpl->rootLine : $this->altRootLine;
 					$theRLC = count($theRootLine)-1;
 					while(list(,$test)=each($values))	{
@@ -274,8 +320,8 @@
 				break;
 				case 'PIDupinRootline':
 				case 'PIDinRootline':
-					$values = explode(',',$pcs[1]);
-					if (($switchKey=='PIDinRootline') || (!in_array($GLOBALS['TSFE']->id,$values))) {
+				$values = explode(',',$value);
+				if (($key=='PIDinRootline') || (!in_array($GLOBALS['TSFE']->id,$values))) {
 						$theRootLine = is_array($GLOBALS['TSFE']->tmpl->rootLine) ? $GLOBALS['TSFE']->tmpl->rootLine : $this->altRootLine;
 						reset($values);
 						while(list(,$test)=each($values))	{
@@ -288,10 +334,10 @@
 					}
 				break;
 				case 'compatVersion':
-					{ return t3lib_div::compat_version($pcs[1]); }
+				{ return t3lib_div::compat_version($value); }
 				break;
 				case 'userFunc':
-					$values = split('\(|\)',$pcs[1]);
+				$values = split('\(|\)',$value);
 					$funcName=trim($values[0]);
 					$funcValue = t3lib_div::trimExplode(',',$values[1]);
 					$pre = $GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['userFuncClassPrefix'];
@@ -307,7 +353,9 @@
 					}
 				break;
 			}
-		}
+		
+
+		return false;
 	}
 
 	/**
@@ -330,6 +378,8 @@
 				if (trim(substr($test,1))==$value)	return true;
 			break;
 		}
+
+		return false;
 	}
 
 	/**
@@ -347,6 +397,8 @@
 
 			if (preg_match($regex, $haystack, $res)) return true;
 		}
+
+		return false;
 	}
 
 	/**
@@ -358,6 +410,24 @@
 	 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=296&cHash=a8ae66c7d6
 	 */
 	function whichDevice($useragent)	{
+		foreach($this->hookObjectsArr as $hookObj)	{
+			if (method_exists($hookObj, 'whichDevice')) {
+				$result = $hookObj->whichDevice($useragent);
+				if (strlen($result)) {
+					return $result;
+				}
+			}
+		}
+
+		// #XXX deprecated, see above
+		if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['devices_class']))	{
+			foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['devices_class'] as $_classRef)	{
+				$_procObj = &t3lib_div::getUserObj($_classRef);
+				return $_procObj->whichDevice_ext($useragent);
+			}
+		}
+		//
+
 		$agent=strtolower(trim($useragent));
 			// pda
 		if(	strstr($agent, 'avantgo'))	{
@@ -397,19 +467,11 @@
 			return 'robot';
 		}
 
-			// Hook for extending device recognition capabilities:
-		if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['devices_class']))	{
-			foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['devices_class'] as $_classRef)	{
-				$_procObj = &t3lib_div::getUserObj($_classRef);
-				return $_procObj->whichDevice_ext($useragent);
-			}
-		}
-
 	}
 
 	/**
 	 * Generates an array with abstracted browser information
-	 * In the function match() this method is called and the result stored in $this->browserInfoArray
+	 * This method is used in the function match() in this class
 	 *
 	 * @param	string		The useragent string, t3lib_div::getIndpEnv('HTTP_USER_AGENT')
 	 * @return	array		Contains keys "browser", "version", "system"
@@ -417,6 +479,15 @@
 	 * @see match()
 	 */
 	function browserInfo($useragent)	{
+		foreach($this->hookObjectsArr as $hookObj)	{
+			if (method_exists($hookObj, 'browserInfo')) {
+				$result = $hookObj->browserInfo($useragent);
+				if (strlen($result)) {
+					return $result;
+				}
+			}
+		}
+
 		$useragent = trim($useragent);
 		$browserInfo=Array();
 		$browserInfo['useragent']=$useragent;
@@ -521,7 +592,7 @@
 	 * @return	double		Returns double value, eg. "7.32"
 	 */
 	function browserInfo_version($tmp)	{
-		return doubleval(ereg_replace('^[^0-9]*','',$tmp));
+		return doubleval(preg_replace('/^[^0-9]*/','',$tmp));
 	}
 
 	/**



More information about the TYPO3-team-core mailing list