Procházet zdrojové kódy

New helper class: TemplateString - to allow extended syntaxes such as $this->location_id->org_id->parent_id->name$... to be progressively introduced and replace the heavy ToArgs()

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1645 a333f486-631f-4898-b8df-5754b55c2be0
romainq před 13 roky
rodič
revize
1b0d6a7546

+ 1 - 0
core/cmdbobject.class.inc.php

@@ -76,6 +76,7 @@ require_once('cmdbchangeop.class.inc.php');
 // Romain: temporary moved into application.inc.php (see explanations there)
 //require_once('event.class.inc.php');
 
+require_once('templatestring.class.inc.php');
 require_once('csvparser.class.inc.php');
 require_once('bulkchange.class.inc.php');
 

+ 28 - 0
core/dbobject.class.php

@@ -368,6 +368,34 @@ abstract class DBObject
 
 	public function Get($sAttCode)
 	{
+		if (($iPos = strpos($sAttCode, '->')) === false)
+		{
+			return $this->GetStrict($sAttCode);
+		}
+		else
+		{
+			$sExtKeyAttCode = substr($sAttCode, 0, $iPos);
+			$sRemoteAttCode = substr($sAttCode, $iPos + 2);
+			if (!MetaModel::IsValidAttCode(get_class($this), $sExtKeyAttCode))
+			{
+				throw new CoreException("Unknown external key '$sExtKeyAttCode' for the class ".get_class($this));
+			}
+			$oKeyAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyAttCode);
+			$sRemoteClass = $oKeyAttDef->GetTargetClass();
+			$oRemoteObj = MetaModel::GetObject($sRemoteClass, $this->GetStrict($sExtKeyAttCode), false);
+			if (is_null($oRemoteObj))
+			{
+				return '';
+			}
+			else
+			{
+				return $oRemoteObj->Get($sRemoteAttCode);
+			}
+		}
+	}
+
+	public function GetStrict($sAttCode)
+	{
 		if (!array_key_exists($sAttCode, MetaModel::ListAttributeDefs(get_class($this))))
 		{
 			throw new CoreException("Unknown attribute code '$sAttCode' for the class ".get_class($this));

+ 30 - 2
core/metamodel.class.php

@@ -676,10 +676,38 @@ abstract class MetaModel
 		if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) return false;
 		return (self::$m_aAttribDefs[$sClass][$sAttCode]->IsExternalKey());
 	}
-	final static public function IsValidAttCode($sClass, $sAttCode)
+	final static public function IsValidAttCode($sClass, $sAttCode, $bExtended = false)
 	{
 		if (!array_key_exists($sClass, self::$m_aAttribDefs)) return false;
-		return (array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]));
+
+		if ($bExtended)
+		{
+			if (($iPos = strpos($sAttCode, '->')) === false)
+			{
+				$bRes = array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]);
+			}
+			else
+			{
+				$sExtKeyAttCode = substr($sAttCode, 0, $iPos);
+				$sRemoteAttCode = substr($sAttCode, $iPos + 2);
+				if (MetaModel::IsValidAttCode($sClass, $sExtKeyAttCode))
+				{
+					$oKeyAttDef = MetaModel::GetAttributeDef($sClass, $sExtKeyAttCode);
+					$sRemoteClass = $oKeyAttDef->GetTargetClass();
+					$bRes = MetaModel::IsValidAttCode($sRemoteClass, $sRemoteAttCode, true);
+				}
+				else
+				{
+					$bRes = false;
+				}
+			}
+		}
+		else
+		{
+			$bRes = array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]);
+		}
+		
+		return $bRes;
 	}
 	final static public function IsAttributeOrigin($sClass, $sAttCode)
 	{

+ 177 - 0
core/templatestring.class.inc.php

@@ -0,0 +1,177 @@
+<?php
+// Copyright (C) 2010 Combodo SARL
+//
+//   This program is free software; you can redistribute it and/or modify
+//   it under the terms of the GNU General Public License as published by
+//   the Free Software Foundation; version 3 of the License.
+//
+//   This program is distributed in the hope that it will be useful,
+//   but WITHOUT ANY WARRANTY; without even the implied warranty of
+//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//   GNU General Public License for more details.
+//
+//   You should have received a copy of the GNU General Public License
+//   along with this program; if not, write to the Free Software
+//   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+/**
+ * Simple helper class to interpret and transform a template string
+ *
+ * Usage:
+ *     $oString = new TemplateString("Blah $this->friendlyname$ is in location $this->location_id->name$ ('$this->location_id->org_id->name$)");
+ *     echo $oString->Render(array('this' => $oContact));
+
+ * @author      Erwan Taloc <erwan.taloc@combodo.com>
+ * @author      Romain Quetiez <romain.quetiez@combodo.com>
+ * @author      Denis Flaven <denis.flaven@combodo.com>
+ * @license     http://www.opensource.org/licenses/gpl-3.0.html LGPL
+ */
+
+/**
+ * Helper class
+ */
+class TemplateStringPlaceholder
+{
+	public $sToken;
+	public $sAttCode;
+	public $sFunction;
+	public $sParamName;
+	public $bIsValid;
+
+	public function __construct($sToken)
+	{
+		$this->sToken = $sToken;
+		$this->sAttcode = '';
+		$this->sFunction = '';
+		$this->sParamName = '';
+		$this->bIsValid = false; // Validity may be false in general, but it can work anyway (thanks to specialization) when rendering
+	}
+}
+
+/**
+ * Class TemplateString
+ */
+class TemplateString
+{
+	protected $m_sRaw;
+	protected $m_aPlaceholders;
+	    
+	public function __construct($sRaw)
+	{
+		$this->m_sRaw = $sRaw;
+		$this->m_aPlaceholders = null;
+	}
+	
+	/**
+	* Split the string into placholders
+	* @param Hash $aParamTypes Class of the expected parameters: hash array of '<param_id>' => '<class_name>'
+	* @return void
+	*/	  
+	protected function Analyze($aParamTypes = array())
+	{
+		if (!is_null($this->m_aPlaceholders)) return;
+
+		$this->m_aPlaceholders = array();
+		if (preg_match_all('/\\$([a-z0-9_]+(->[a-z0-9_]+)*)\\$/', $this->m_sRaw, $aMatches))
+		{
+			foreach($aMatches[1] as $sPlaceholder)
+			{
+				$oPlaceholder = new TemplateStringPlaceholder($sPlaceholder);
+				$oPlaceholder->bIsValid = false;
+				foreach ($aParamTypes as $sParamName => $sClass)
+				{
+					$sParamPrefix = $sParamName.'->';
+					if (substr($sPlaceholder, 0, strlen($sParamPrefix)) == $sParamPrefix)
+					{
+						// Todo - detect functions (label...)
+						$oPlaceholder->sFunction = '';
+
+						$oPlaceholder->sParamName = $sParamName;
+						$sAttcode = substr($sPlaceholder, strlen($sParamPrefix));
+						$oPlaceholder->sAttcode = $sAttcode;
+						$oPlaceholder->bIsValid = MetaModel::IsValidAttCode($sClass, $sAttcode, true /* extended */);
+					}
+				}
+
+				$this->m_aPlaceholders[] = $oPlaceholder;
+			}
+		}
+	}
+
+	/**
+	* Return the placeholders (for reporting purposes)
+	* @return void
+	*/	  
+	public function GetPlaceholders()
+	{
+		return $this->m_aPlaceholders;
+	}
+
+	/**
+	* Check the format when possible
+	* @param Hash $aParamTypes Class of the expected parameters: hash array of '<param_id>' => '<class_name>'
+	* @return void
+	*/	  
+	public function IsValid($aParamTypes = array())
+	{
+		$this->Analyze($aParamTypes);
+
+		foreach($this->m_aPlaceholders as $oPlaceholder)
+		{
+			if (!$oPlaceholder->bIsValid)
+			{
+				if (count($aParamTypes) == 0)
+				{
+					return false;
+				}
+				if (array_key_exists($oPlaceholder->sParamName, $aParamTypes))
+				{
+					return false;
+				}
+			}
+		}
+		return true;
+	}
+
+	/**
+	* Apply the given parameters to replace the placeholders
+	* @param Hash $aParamValues Value of the expected parameters: hash array of '<param_id>' => '<value>'
+	* @return void
+	*/	  
+	public function Render($aParamValues = array())
+	{
+		$aParamTypes = array();
+		foreach($aParamValues as $sParamName => $value)
+		{
+			$aParamTypes[$sParamName] = get_class($value);
+		}
+		$this->Analyze($aParamTypes);
+
+		$aSearch = array();
+		$aReplace = array();
+		foreach($this->m_aPlaceholders as $oPlaceholder)
+		{
+			if (array_key_exists($oPlaceholder->sParamName, $aParamValues))
+			{
+				$oRef = $aParamValues[$oPlaceholder->sParamName];
+				try
+				{
+					$value = $oRef->Get($oPlaceholder->sAttcode);
+					$aSearch[] = '$'.$oPlaceholder->sToken.'$';
+					$aReplace[] = $value;
+					$oPlaceholder->bIsValid = true;
+				}
+				catch(Exception $e)
+				{
+					$oPlaceholder->bIsValid = false;
+				}
+			}
+			else
+			{
+				$oPlaceholder->bIsValid = false;
+			}
+		}
+		return str_replace($aSearch, $aReplace, $this->m_sRaw);
+	}
+}
+?>