mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 02:28:44 +02:00
On going implementation of the designer
SVN:trunk[1870]
This commit is contained in:
@@ -108,6 +108,11 @@ class MFModule extends MFItem
|
||||
return $this->sRootDir;
|
||||
}
|
||||
|
||||
public function GetModuleDir()
|
||||
{
|
||||
return basename($this->sRootDir);
|
||||
}
|
||||
|
||||
public function GetDataModelFiles()
|
||||
{
|
||||
return $this->aDataModels;
|
||||
@@ -142,6 +147,11 @@ class MFWorkspace extends MFModule
|
||||
{
|
||||
return $this->sRootDir.'/workspace.xml';
|
||||
}
|
||||
|
||||
public function GetName()
|
||||
{
|
||||
return ''; // The workspace itself has no name so that objects created inside it retain their original module's name
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,7 +340,7 @@ class ModelFactory
|
||||
$sOperation = $aClassData['node']->getAttribute('_operation');
|
||||
switch($sOperation)
|
||||
{
|
||||
case 'created':
|
||||
case 'added':
|
||||
case '':
|
||||
if (in_array($aClassData['parent'], self::$aWellKnownParents))
|
||||
{
|
||||
@@ -353,7 +363,7 @@ class ModelFactory
|
||||
|
||||
case 'modified':
|
||||
unset($aClasses[$sClassName]);
|
||||
$this->AlterClass($aClassData['node'], $sModuleName);
|
||||
$this->AlterClass($sClassName, $aClassData['node']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -367,7 +377,7 @@ class ModelFactory
|
||||
$sOperation = $aClassData['node']->getAttribute('_operation');
|
||||
switch($sOperation)
|
||||
{
|
||||
case 'created':
|
||||
case 'added':
|
||||
case '':
|
||||
// Add the class as a new root class
|
||||
$this->AddClass($aClassData['node'], $sModuleName);
|
||||
@@ -380,7 +390,7 @@ class ModelFactory
|
||||
|
||||
case 'modified':
|
||||
//@@TODO Handle the modification of a class here
|
||||
$this->AlterClass($aClassData['node'], $sModuleName);
|
||||
$this->AlterClass($sClassName, $aClassData['node']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -406,6 +416,17 @@ class ModelFactory
|
||||
return $aModules;
|
||||
}
|
||||
|
||||
|
||||
function GetModule($sModuleName)
|
||||
{
|
||||
foreach(self::$aLoadedModules as $oModule)
|
||||
{
|
||||
if ($oModule->GetName() == $sModuleName) return $oModule;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the class specified by the given node already exists in the loaded DOM
|
||||
* @param DOMNode $oClassNode The node corresponding to the class to load
|
||||
@@ -442,7 +463,7 @@ class ModelFactory
|
||||
* @param string $sModuleName The name of the module in which this class is declared
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function AddClass(DOMNode $oClassNode, $sModuleName)
|
||||
public function AddClass(DOMNode $oClassNode, $sModuleName)
|
||||
{
|
||||
if ($oClassNode->hasAttribute('name'))
|
||||
{
|
||||
@@ -469,7 +490,10 @@ class ModelFactory
|
||||
// The class is a subclass of a class already loaded, add it under
|
||||
self::$aLoadedClasses[$sClassName] = $this->oDOMDocument->ImportNode($oClassNode, true /* bDeep */);
|
||||
self::$aLoadedClasses[$sClassName]->SetAttribute('_operation', 'added');
|
||||
self::$aLoadedClasses[$sClassName]->SetAttribute('_created_in', $sModuleName);
|
||||
if ($sModuleName != '')
|
||||
{
|
||||
self::$aLoadedClasses[$sClassName]->SetAttribute('_created_in', $sModuleName);
|
||||
}
|
||||
self::$aLoadedClasses[$sParentClass]->AppendChild(self::$aLoadedClasses[$sClassName]);
|
||||
$bNothingLoaded = false;
|
||||
}
|
||||
@@ -478,7 +502,10 @@ class ModelFactory
|
||||
// Add the class as a new root class
|
||||
self::$aLoadedClasses[$sClassName] = $this->oDOMDocument->ImportNode($oClassNode, true /* bDeep */);
|
||||
self::$aLoadedClasses[$sClassName]->SetAttribute('_operation', 'added');
|
||||
self::$aLoadedClasses[$sClassName]->SetAttribute('_created_in', $sModuleName);
|
||||
if ($sModuleName != '')
|
||||
{
|
||||
self::$aLoadedClasses[$sClassName]->SetAttribute('_created_in', $sModuleName);
|
||||
}
|
||||
$this->oClasses->AppendChild(self::$aLoadedClasses[$sClassName]);
|
||||
}
|
||||
else
|
||||
@@ -498,82 +525,165 @@ class ModelFactory
|
||||
{
|
||||
throw new Exception("ModelFactory::RemoveClass: Cannot remove the non existing class $sClass");
|
||||
}
|
||||
self::$aLoadedClasses[$sClass]->SetAttribute('_operation', 'removed');
|
||||
|
||||
//TODO: also mark as removed the child classes
|
||||
}
|
||||
|
||||
public function AlterClass(DOMNode $oClassNode, $sModuleName)
|
||||
{
|
||||
if ($oClassNode->hasAttribute('name'))
|
||||
$oClassNode = self::$aLoadedClasses[$sClass];
|
||||
if ($oClassNode->getAttribute('_operation') == 'added')
|
||||
{
|
||||
$sClassName = $oClassNode->GetAttribute('name');
|
||||
$oClassNode->parentNode->RemoveChild($oClassNode);
|
||||
unset(self::$aLoadedClasses[$sClass]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception('ModelFactory::AddClass: Cannot alter a class with no name');
|
||||
self::$aLoadedClasses[$sClass]->SetAttribute('_operation', 'removed');
|
||||
//TODO: also mark as removed the child classes
|
||||
}
|
||||
if (!$this->ClassExists($oClassNode))
|
||||
|
||||
}
|
||||
|
||||
public function AlterClass($sClassName, DOMNode $oClassNode)
|
||||
{
|
||||
$sOriginalName = $sClassName;
|
||||
if ($this->ClassNameExists($sClassName))
|
||||
{
|
||||
throw new Exception("ModelFactory::AddClass: Cannot later the non-existing class $sClassName");
|
||||
$oDestNode = self::$aLoadedClasses[$sClassName];
|
||||
}
|
||||
$this->_priv_AlterNode(self::$aLoadedClasses[$sClassName], $oClassNode);
|
||||
else
|
||||
{
|
||||
$sOriginalName = $oClassNode->getAttribute('_original_name');
|
||||
if ($this->ClassNameExists($sOriginalName))
|
||||
{
|
||||
// Class was renamed !
|
||||
$oDestNode = self::$aLoadedClasses[$sOriginalName];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("ModelFactory::AddClass: Cannot alter the non-existing class $sClassName / $sOriginalName");
|
||||
}
|
||||
}
|
||||
$this->_priv_AlterNode($oDestNode, $oClassNode);
|
||||
$sClassName = $oDestNode->getAttribute('name');
|
||||
if ($sOriginalName != $sClassName)
|
||||
{
|
||||
unset(self::$aLoadedClasses[$sOriginalName]);
|
||||
self::$aLoadedClasses[$sClassName] = $oDestNode;
|
||||
}
|
||||
$this->_priv_SetFlag($oDestNode, 'modified');
|
||||
}
|
||||
|
||||
protected function _priv_AlterNode(DOMNode $oNode, DOMNode $oDeltaNode)
|
||||
{
|
||||
foreach ($oDeltaNode->attributes as $sName => $oAttrNode)
|
||||
{
|
||||
$sCurrentValue = $oNode->getAttribute($sName);
|
||||
$sNewValue = $oAttrNode->value;
|
||||
$oNode->setAttribute($sName, $oAttrNode->value);
|
||||
}
|
||||
|
||||
foreach($oDeltaNode->childNodes as $oChildNode)
|
||||
$aSrcChildNodes = $oNode->childNodes;
|
||||
foreach($oDeltaNode->childNodes as $index => $oChildNode)
|
||||
{
|
||||
$sOperation = $oChildNode->getAttribute('_operation');
|
||||
$sPath = $oChildNode->tagName;
|
||||
$sName = $oChildNode->getAttribute('name');
|
||||
if ($sName != '')
|
||||
if (!$oChildNode instanceof DOMElement)
|
||||
{
|
||||
$sPath .= "[@name='$sName']";
|
||||
// Text or CData nodes are treated by position
|
||||
$sOperation = $oChildNode->parentNode->getAttribute('_operation');
|
||||
switch($sOperation)
|
||||
{
|
||||
case 'removed':
|
||||
// ???
|
||||
break;
|
||||
|
||||
case 'modified':
|
||||
case 'replaced':
|
||||
case 'added':
|
||||
$oNewNode = $this->oDOMDocument->importNode($oChildNode);
|
||||
$oSrcChildNode = $aSrcChildNodes->item($index);
|
||||
if ($oSrcChildNode)
|
||||
{
|
||||
$oNode->replaceChild($oNewNode, $oSrcChildNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oNode->appendChild($oNewNode);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '':
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
switch($sOperation)
|
||||
else
|
||||
{
|
||||
case 'removed':
|
||||
$oToRemove = $this->_priv_GetNodes($sPath, $oNode)->item(0);
|
||||
if ($oToRemove != null)
|
||||
$sOperation = $oChildNode->getAttribute('_operation');
|
||||
$sPath = $oChildNode->tagName;
|
||||
$sName = $oChildNode->getAttribute('name');
|
||||
if ($sName != '')
|
||||
{
|
||||
$this->_priv_SetFlag($oToRemove, 'removed');
|
||||
$sPath .= "[@name='$sName']";
|
||||
}
|
||||
break;
|
||||
|
||||
case 'modified':
|
||||
$oToModify = $this->_priv_GetNodes($sPath, $oNode)->item(0);
|
||||
if ($oToModify != null)
|
||||
switch($sOperation)
|
||||
{
|
||||
$this->_priv_AlterNode($oToModify, $oChildNode);
|
||||
case 'removed':
|
||||
$oToRemove = $this->_priv_GetNodes($sPath, $oNode)->item(0);
|
||||
if ($oToRemove != null)
|
||||
{
|
||||
$this->_priv_SetFlag($oToRemove, 'removed');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'modified':
|
||||
$oToModify = $this->_priv_GetNodes($sPath, $oNode)->item(0);
|
||||
if ($oToModify != null)
|
||||
{
|
||||
$this->_priv_AlterNode($oToModify, $oChildNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Cannot modify the non-existing node '$sPath' in '".$oNode->getNodePath()."'");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'replaced':
|
||||
$oNewNode = $this->oDOMDocument->importNode($oChildNode, true); // Import the node and its child nodes
|
||||
$oToModify = $this->_priv_GetNodes($sPath, $oNode)->item(0);
|
||||
$oNode->replaceChild($oNewNode, $oToModify);
|
||||
break;
|
||||
|
||||
case 'added':
|
||||
$oNewNode = $this->oDOMDocument->importNode($oChildNode);
|
||||
$oNode->appendChild($oNewNode);
|
||||
$this->_priv_SetFlag($oNewNode, 'added');
|
||||
break;
|
||||
|
||||
case '':
|
||||
// Do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Cannot modify the non-existing node '$sPath' in '".$oNode->getNodePath()."'");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'replaced':
|
||||
$oNewNode = $this->oDOMDocument->importNode($oChildNode, true); // Import the node and its child nodes
|
||||
$oToModify = $this->_priv_GetNodes($sPath, $oNode)->item(0);
|
||||
$oNode->replaceChild($oNewNode, $oToModify);
|
||||
break;
|
||||
|
||||
case 'created':
|
||||
$oNewNode = $this->oDOMDocument->importNode($oChildNode);
|
||||
$oNode->appendChild($oNewNode);
|
||||
$this->_priv_SetFlag($oNewNode, 'created');
|
||||
break;
|
||||
|
||||
case '':
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function GetClassXMLTemplate($sName, $sIcon)
|
||||
{
|
||||
return
|
||||
<<<EOF
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<class name="$sName" parent="" db_table="" category="" abstract="" key_type="autoincrement" db_key_field="id" db_final_class_field="finalclass">
|
||||
<properties>
|
||||
<comment/>
|
||||
<naming format=""><attributes/></naming>
|
||||
<reconciliation><attributes/></reconciliation>
|
||||
<display_template/>
|
||||
<icon>$sIcon</icon>
|
||||
</properties>
|
||||
<fields/>
|
||||
<methods/>
|
||||
<presentation>
|
||||
<details><items/></details>
|
||||
<search><items/></search>
|
||||
<list><items/></list>
|
||||
</presentation>
|
||||
</class>
|
||||
EOF
|
||||
;
|
||||
}
|
||||
/**
|
||||
* List all classes from the DOM, for a given module
|
||||
@@ -591,6 +701,22 @@ class ModelFactory
|
||||
return $this->_priv_GetNodes($sXPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all classes from the DOM, for a given module
|
||||
* @param string $sModuleNale
|
||||
* @param bool $bFlattenLayers
|
||||
* @throws Exception
|
||||
*/
|
||||
public function ListAllClasses($bFlattenLayers = true)
|
||||
{
|
||||
$sXPath = "//class";
|
||||
if ($bFlattenLayers)
|
||||
{
|
||||
$sXPath = "//class[@_operation!='removed']";
|
||||
}
|
||||
return $this->_priv_GetNodes($sXPath);
|
||||
}
|
||||
|
||||
public function GetClass($sClassName, $bFlattenLayers = true)
|
||||
{
|
||||
if (!$this->ClassNameExists($sClassName))
|
||||
@@ -609,6 +735,34 @@ class ModelFactory
|
||||
return $oClassNode;
|
||||
}
|
||||
|
||||
public function GetField($sClassName, $sAttCode, $bFlattenLayers = true)
|
||||
{
|
||||
if (!$this->ClassNameExists($sClassName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
$oClassNode = self::$aLoadedClasses[$sClassName];
|
||||
if ($bFlattenLayers)
|
||||
{
|
||||
$sOperation = $oClassNode->getAttribute('_operation');
|
||||
if ($sOperation == 'removed')
|
||||
{
|
||||
$oClassNode = null;
|
||||
}
|
||||
}
|
||||
$sXPath = "fields/field[@name='$sAttCode']";
|
||||
if ($bFlattenLayers)
|
||||
{
|
||||
$sXPath = "fields/field[(@name='$sAttCode' and (not(@_operation) or @_operation!='removed'))]";
|
||||
}
|
||||
$oFieldNode = $this->_priv_GetNodes($sXPath, $oClassNode)->item(0);
|
||||
if (($oFieldNode == null) && ($oClassNode->getAttribute('parent') != ''))
|
||||
{
|
||||
return $this->GetField($oClassNode->getAttribute('parent'), $sAttCode, $bFlattenLayers);
|
||||
}
|
||||
return $oFieldNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* List all classes from the DOM
|
||||
* @param bool $bFlattenLayers
|
||||
@@ -631,7 +785,7 @@ class ModelFactory
|
||||
$this->_priv_AlterField($oNewField, $sFieldType, $sSQL, $defaultValue, $bIsNullAllowed, $aExtraParams);
|
||||
$oFields = $oClassNode->getElementsByTagName('fields')->item(0);
|
||||
$oFields->AppendChild($oNewField);
|
||||
$this->_priv_SetFlag($oNewField, 'created');
|
||||
$this->_priv_SetFlag($oNewField, 'added');
|
||||
}
|
||||
|
||||
public function RemoveField(DOMNode $oClassNode, $sFieldCode)
|
||||
@@ -640,8 +794,16 @@ class ModelFactory
|
||||
$oFieldNodes = $this->_priv_GetNodes($sXPath, $oClassNode);
|
||||
if (is_object($oFieldNodes) && (is_object($oFieldNodes->item(0))))
|
||||
{
|
||||
//@@TODO: if the field was 'created' => then really delete it
|
||||
$this->_priv_SetFlag($oFieldNodes->item(0), 'removed');
|
||||
$oFieldNode = $oFieldNodes->item(0);
|
||||
$sOpCode = $oFieldNode->getAttribute('_operation');
|
||||
if ($oFieldNode->getAttribute('_operation') == 'added')
|
||||
{
|
||||
$oFieldNode->parentNode->removeChild($oFieldNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->_priv_SetFlag($oFieldNode, 'removed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,8 +813,19 @@ class ModelFactory
|
||||
$oFieldNodes = $this->_priv_GetNodes($sXPath, $oClassNode);
|
||||
if (is_object($oFieldNodes) && (is_object($oFieldNodes->item(0))))
|
||||
{
|
||||
//@@TODO: if the field was 'created' => then let it as 'created'
|
||||
$this->_priv_SetFlag($oFieldNodes->item(0), 'modified');
|
||||
$oFieldNode = $oFieldNodes->item(0);
|
||||
//@@TODO: if the field was 'added' => then let it as 'added'
|
||||
$sOpCode = $oFieldNode->getAttribute('_operation');
|
||||
switch($sOpCode)
|
||||
{
|
||||
case 'added':
|
||||
case 'modified':
|
||||
// added or modified, let it as it is
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->_priv_SetFlag($oFieldNodes->item(0), 'modified');
|
||||
}
|
||||
$this->_priv_AlterField($oFieldNodes->item(0), $sFieldType, $sSQL, $defaultValue, $bIsNullAllowed, $aExtraParams);
|
||||
}
|
||||
}
|
||||
@@ -660,14 +833,34 @@ class ModelFactory
|
||||
protected function _priv_AlterField(DOMNode $oFieldNode, $sFieldType, $sSQL, $defaultValue, $bIsNullAllowed, $aExtraParams)
|
||||
{
|
||||
switch($sFieldType)
|
||||
{
|
||||
{
|
||||
case 'Blob':
|
||||
case 'Boolean':
|
||||
case 'CaseLog':
|
||||
case 'Deadline':
|
||||
case 'Duration':
|
||||
case 'EmailAddress':
|
||||
case 'EncryptedString':
|
||||
case 'HTML':
|
||||
case 'IPAddress':
|
||||
case 'LongText':
|
||||
case 'OQL':
|
||||
case 'OneWayPassword':
|
||||
case 'Password':
|
||||
case 'Percentage':
|
||||
case 'String':
|
||||
case 'Text':
|
||||
case 'IPAddress':
|
||||
case 'EmailAddress':
|
||||
case 'Blob':
|
||||
break;
|
||||
|
||||
case 'Text':
|
||||
case 'TemplateHTML':
|
||||
case 'TemplateString':
|
||||
case 'TemplateText':
|
||||
case 'URL':
|
||||
case 'Date':
|
||||
case 'DateTime':
|
||||
case 'Decimal':
|
||||
case 'Integer':
|
||||
break;
|
||||
|
||||
case 'ExternalKey':
|
||||
$this->_priv_AddFieldAttribute($oFieldNode, 'target_class', $aExtraParams);
|
||||
// Fall through
|
||||
@@ -740,7 +933,7 @@ class ModelFactory
|
||||
protected function _priv_SetFieldValues($oFieldNode, $aExtraParams)
|
||||
{
|
||||
$aVals = array_key_exists('values', $aExtraParams) ? $aExtraParams['values'] : '';
|
||||
$oValues = $oFieldNode->getElementByTagName('values')->item(0);
|
||||
$oValues = $oFieldNode->getElementsByTagName('values')->item(0);
|
||||
|
||||
// No dependencies before, and no dependencies to add, exit
|
||||
if (($oValues == null) && ($aVals == '')) return;
|
||||
@@ -756,14 +949,69 @@ class ModelFactory
|
||||
foreach($aVals as $sValue)
|
||||
{
|
||||
$oVal = $this->oDOMDocument->createElement('value', $sValue);
|
||||
$oValues->addChild($oVal);
|
||||
$oValues->appendChild($oVal);
|
||||
}
|
||||
$oFieldNode->addChild($oValues);
|
||||
$oFieldNode->appendChild($oValues);
|
||||
}
|
||||
|
||||
protected function _priv_SetFlag($oNode, $sFlagValue)
|
||||
public function SetPresentation(DOMNode $oClassNode, $sPresentationCode, $aPresentation)
|
||||
{
|
||||
$oNode->setAttribute('_operation', $sFlagValue);
|
||||
$oPresentation = $oClassNode->getElementsByTagName('presentation')->item(0);
|
||||
if (!is_object($oPresentation))
|
||||
{
|
||||
$oPresentation = $this->oDOMDocument->createElement('presentation');
|
||||
$oClassNode->appendChild($oPresentation);
|
||||
}
|
||||
$oZlist = $oPresentation->getElementsByTagName($sPresentationCode)->item(0);
|
||||
if (is_object($oZlist))
|
||||
{
|
||||
// Remove the previous Zlist
|
||||
$oPresentation->removeChild($oZlist);
|
||||
}
|
||||
// Create the ZList anew
|
||||
$oZlist = $this->oDOMDocument->createElement($sPresentationCode);
|
||||
$oPresentation->appendChild($oZlist);
|
||||
$this->AddZListItem($oZlist, $aPresentation);
|
||||
$this->_priv_SetFlag($oZlist, 'replaced');
|
||||
}
|
||||
|
||||
protected function AddZListItem($oXMLNode, $value)
|
||||
{
|
||||
if (is_array($value))
|
||||
{
|
||||
$oXmlItems = $this->oDOMDocument->CreateElement('items');
|
||||
$oXMLNode->appendChild($oXmlItems);
|
||||
|
||||
foreach($value as $key => $item)
|
||||
{
|
||||
$oXmlItem = $this->oDOMDocument->CreateElement('item');
|
||||
$oXmlItems->appendChild($oXmlItem);
|
||||
|
||||
if (is_string($key))
|
||||
{
|
||||
$oXmlItem->SetAttribute('key', $key);
|
||||
}
|
||||
$this->AddZListItem($oXmlItem, $item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oXmlText = $this->oDOMDocument->CreateTextNode((string) $value);
|
||||
$oXMLNode->appendChild($oXmlText);
|
||||
}
|
||||
}
|
||||
|
||||
public function _priv_SetFlag($oNode, $sFlagValue)
|
||||
{
|
||||
$sPreviousFlag = $oNode->getAttribute('_operation');
|
||||
if ($sPreviousFlag == 'added')
|
||||
{
|
||||
// Do nothing ??
|
||||
}
|
||||
else
|
||||
{
|
||||
$oNode->setAttribute('_operation', $sFlagValue);
|
||||
}
|
||||
if ($oNode->tagName != 'class')
|
||||
{
|
||||
$this->_priv_SetFlag($oNode->parentNode, 'modified');
|
||||
@@ -865,7 +1113,21 @@ class ModelFactory
|
||||
$iDepth++;
|
||||
foreach($oNode->childNodes as $oChildNode)
|
||||
{
|
||||
$sOperation = $oChildNode->getAttribute('_operation');
|
||||
$sNodeName = $oChildNode->nodeName;
|
||||
$sNodeValue = $oChildNode->nodeValue;
|
||||
if (!$oChildNode instanceof DOMElement)
|
||||
{
|
||||
$sName = '$$';
|
||||
$sOperation = $oChildNode->parentNode->getAttribute('_operation');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sName = $oChildNode->getAttribute('name');;
|
||||
$sOperation = $oChildNode->getAttribute('_operation');
|
||||
}
|
||||
|
||||
//echo str_repeat('+', $iDepth)." $sNodeName [$sName], operation: $sOperation\n";
|
||||
|
||||
switch($sOperation)
|
||||
{
|
||||
case 'removed':
|
||||
@@ -883,16 +1145,21 @@ class ModelFactory
|
||||
//echo "<p>".str_repeat('+', $iDepth).$oChildNode->getAttribute('name')." was removed...</p>";
|
||||
break;
|
||||
|
||||
case 'modified':
|
||||
case 'created':
|
||||
//echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('name')." was modified...</p>";
|
||||
$oModifiedNode = $oDoc->importNode($oChildNode->cloneNode(false)); // Copies all the node's attributes, but NOT the child nodes
|
||||
$oModifiedNode->removeAttribute('_source');
|
||||
$this->_priv_ImportModifiedChildren($oDoc, $oModifiedNode, $oChildNode);
|
||||
if ($oModifiedNode->tagName == 'class')
|
||||
case 'added':
|
||||
//echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('name')." was created...</p>";
|
||||
$oModifiedNode = $oDoc->importNode($oChildNode, true); // Copies all the node's attributes, and the child nodes as well
|
||||
if ($oChildNode instanceof DOMElement)
|
||||
{
|
||||
// classes are always located under the root node
|
||||
$oDoc->firstChild->appendChild($oModifiedNode);
|
||||
$oModifiedNode->removeAttribute('_source');
|
||||
if ($oModifiedNode->tagName == 'class')
|
||||
{
|
||||
// classes are always located under the root node
|
||||
$oDoc->firstChild->appendChild($oModifiedNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oDestNode->appendChild($oModifiedNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -900,17 +1167,57 @@ class ModelFactory
|
||||
}
|
||||
break;
|
||||
|
||||
case 'replaced':
|
||||
//echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('name')." was replaced...</p>";
|
||||
$oModifiedNode = $oDoc->importNode($oChildNode, true); // Copies all the node's attributes, and the child nodes as well
|
||||
if ($oChildNode instanceof DOMElement)
|
||||
{
|
||||
$oModifiedNode->removeAttribute('_source');
|
||||
}
|
||||
$oDestNode->appendChild($oModifiedNode);
|
||||
break;
|
||||
|
||||
case 'modified':
|
||||
//echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('name')." was modified...</p>";
|
||||
if ($oChildNode instanceof DOMElement)
|
||||
{
|
||||
//echo str_repeat('+', $iDepth)." Copying (NON recursively) the modified node\n";
|
||||
$oModifiedNode = $oDoc->importNode($oChildNode, false); // Copies all the node's attributes, but NOT the child nodes
|
||||
$oModifiedNode->removeAttribute('_source');
|
||||
$this->_priv_ImportModifiedChildren($oDoc, $oModifiedNode, $oChildNode);
|
||||
if ($oModifiedNode->tagName == 'class')
|
||||
{
|
||||
// classes are always located under the root node
|
||||
$oDoc->firstChild->appendChild($oModifiedNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oDestNode->appendChild($oModifiedNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//echo str_repeat('+', $iDepth)." Copying (recursively) the modified node\n";
|
||||
$oModifiedNode = $oDoc->importNode($oChildNode, true); // Copies all the node's attributes, and the child nodes
|
||||
$oDestNode->appendChild($oModifiedNode);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// No change: search if there is not a modified child class
|
||||
$oModifiedNode = $oDoc->importNode($oChildNode->cloneNode(false)); // Copies all the node's attributes, but NOT the child nodes
|
||||
$oModifiedNode->removeAttribute('_source');
|
||||
if ($oChildNode->tagName == 'class')
|
||||
//echo str_repeat('+', $iDepth)." Importing (NON recursively) the modified node\n";
|
||||
if ($oChildNode instanceof DOMElement)
|
||||
{
|
||||
//echo "<p>".str_repeat('+', $iDepth)."Checking if a subclass of ".$oChildNode->getAttribute('name')." was modified...</p>";
|
||||
// classes are always located under the root node
|
||||
$this->_priv_ImportModifiedChildren($oDoc, $oModifiedNode, $oChildNode);
|
||||
$oModifiedNode->removeAttribute('_source');
|
||||
}
|
||||
}
|
||||
if ($oChildNode->tagName == 'class')
|
||||
{
|
||||
//echo "<p>".str_repeat('+', $iDepth)."Checking if a subclass of ".$oChildNode->getAttribute('name')." was modified...</p>";
|
||||
// classes are always located under the root node
|
||||
$this->_priv_ImportModifiedChildren($oDoc, $oModifiedNode, $oChildNode);
|
||||
}
|
||||
}
|
||||
$iDepth--;
|
||||
}
|
||||
@@ -986,4 +1293,91 @@ class ModelFactory
|
||||
public function _priv_SetNodeAttribute(DOMNode $oNode, $sAttributeName, $atttribueValue)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to browse the DOM -could be factorized in ModelFactory
|
||||
* Returns the node directly under the given node, and that is supposed to be always present and unique
|
||||
*/
|
||||
protected function GetUniqueElement($oDOMNode, $sTagName, $bMustExist = true)
|
||||
{
|
||||
$oNode = null;
|
||||
foreach($oDOMNode->childNodes as $oChildNode)
|
||||
{
|
||||
if ($oChildNode->nodeName == $sTagName)
|
||||
{
|
||||
$oNode = $oChildNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($bMustExist && is_null($oNode))
|
||||
{
|
||||
throw new DOMFormatException('Missing unique tag: '.$sTagName);
|
||||
}
|
||||
return $oNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to browse the DOM -could be factorized in ModelFactory
|
||||
* Returns the node directly under the given node, or null is missing
|
||||
*/
|
||||
protected function GetOptionalElement($oDOMNode, $sTagName)
|
||||
{
|
||||
return $this->GetUniqueElement($oDOMNode, $sTagName, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper to browse the DOM -could be factorized in ModelFactory
|
||||
* Returns the TEXT of the given node (possibly from several subnodes)
|
||||
*/
|
||||
protected function GetNodeText($oNode)
|
||||
{
|
||||
$sText = '';
|
||||
foreach($oNode->childNodes as $oChildNode)
|
||||
{
|
||||
if ($oChildNode instanceof DOMCharacterData) // Base class of DOMText and DOMCdataSection
|
||||
{
|
||||
$sText .= $oChildNode->wholeText;
|
||||
}
|
||||
}
|
||||
return $sText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to browse the DOM -could be factorized in ModelFactory
|
||||
* Assumes the given node to be either a text or
|
||||
* <items>
|
||||
* <item [key]="..."]>value<item>
|
||||
* <item [key]="..."]>value<item>
|
||||
* </items>
|
||||
* where value can be the either a text or an array of items... recursively
|
||||
* Returns a PHP array
|
||||
*/
|
||||
public function GetNodeAsArrayOfItems($oNode)
|
||||
{
|
||||
$oItems = $this->GetOptionalElement($oNode, 'items');
|
||||
if ($oItems)
|
||||
{
|
||||
$res = array();
|
||||
foreach($oItems->childNodes as $oItem)
|
||||
{
|
||||
// When an attribute is missing
|
||||
if ($oItem->hasAttribute('key'))
|
||||
{
|
||||
$key = $oItem->getAttribute('key');
|
||||
$res[$key] = $this->GetNodeAsArrayOfItems($oItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
$res[] = $this->GetNodeAsArrayOfItems($oItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$res = $this->GetNodeText($oNode);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user