CompileMenu($oMenu, $sResultFile, $sRelativeDir, $oP);
}
catch (ssDOMFormatException $e)
{
$sClass = $oClass->getAttribute("name");
throw new Exception("Failed to process class '$sClass', from '$sModuleRootDir': ".$e->getMessage());
}
}
}
}
if (count($aResultFiles))
{
$oP->add('Files
');
foreach ($aResultFiles as $sModuleName => $sFile)
{
$oP->add(''.$sFile.'
');
$oP->add('');
$oP->add(highlight_file($sFile, true));
$oP->add('
');
}
}
$oP->output();
//$this->oFactory->Dump();
}
/**
* Helper to copy the module files to the exploitation environment
* Returns true if successfull
*/
protected function CopyDirectory($sSource, $sDest)
{
if (is_dir($sSource))
{
if (!is_dir($sDest))
{
mkdir($sDest);
}
$aFiles = scandir($sSource);
if(sizeof($aFiles) > 0 )
{
foreach($aFiles as $sFile)
{
if ($sFile == '.' || $sFile == '..' || $sFile == '.svn')
{
// Skip
continue;
}
if (is_dir($sSource.'/'.$sFile))
{
$this->CopyDirectory($sSource.'/'.$sFile, $sDest.'/'.$sFile);
}
else
{
copy($sSource.'/'.$sFile, $sDest.'/'.$sFile);
}
}
}
return true;
}
elseif (is_file($sSource))
{
return copy($sSource, $sDest);
}
else
{
return false;
}
}
/**
* 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;
if ($oDOMNode->hasChildNodes())
{
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 = '';
if ($oNode->hasChildNodes())
{
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
*
* - value
-
*
- value
-
*
* where value can be the either a text or an array of items... recursively
* Returns a PHP array
*/
protected function GetNodeAsArrayOfItems($oNode)
{
$oItems = $this->GetOptionalElement($oNode, 'items');
if ($oItems)
{
$res = array();
if ($oItems->hasChildNodes())
{
foreach($oItems->childNodes as $oItem)
{
// When an attribute is msising
if ($oItem->hasAttributes() && $oItem->hasAttribute('key'))
{
$key = $oItem->getAttribute('key');
$res[$key] = $this->GetNodeAsArrayOfItems($oItem);
}
else
{
$res[] = $this->GetNodeAsArrayOfItems($oItem);
}
}
}
}
else
{
$res = $this->GetNodeText($oNode);
}
return $res;
}
/**
* Helper to format the flags for an attribute, in a given state
* @param object $oAttNode DOM node containing the information to build the flags
* Returns string PHP flags, based on the OPT_ATT_ constants, or empty (meaning 0, can be omitted)
*/
protected function FlagsToPHP($oAttNode)
{
static $aNodeAttributeToFlag = array(
'mandatory' => 'OPT_ATT_MANDATORY',
'read_only' => 'OPT_ATT_READONLY',
'must_prompt' => 'OPT_ATT_MUSTPROMPT',
'must_change' => 'OPT_ATT_MUSTCHANGE',
'hidden' => 'OPT_ATT_HIDDEN',
);
$aFlags = array();
foreach ($aNodeAttributeToFlag as $sNodeAttribute => $sFlag)
{
$bFlag = ($oAttNode->GetAttribute($sNodeAttribute) == '1');
if ($bFlag)
{
$aFlags[] = $sFlag;
}
}
$sRes = implode(' | ', $aFlags);
return $sRes;
}
/**
* Format a path (file or url) as an absolute path or relative to the module or the app
*/
protected function PathToPHP($sPath, $sModuleRelativeDir, $bIsUrl = false)
{
if (substr($sPath, 0, 2) == '$$')
{
// Absolute
$sPHP = "'".addslashes(substr($sPath, 2))."'";
}
elseif (substr($sPath, 0, 1) == '$')
{
// Relative to the application
if ($bIsUrl)
{
$sPHP = "utils::GetAbsoluteUrlAppRoot().'".addslashes(substr($sPath, 1))."'";
}
else
{
$sPHP = "APPROOT.'".addslashes(substr($sPath, 1))."'";
}
}
else
{
// Relative to the module
if ($bIsUrl)
{
$sPHP = "utils::GetAbsoluteUrlAppRoot().'".addslashes($sModuleRelativeDir.''.$sPath)."'";
}
else
{
$sPHP = "dirname(__FILE__).'/$sPath'";
}
}
return $sPHP;
}
protected function CompileClass($oClass, $sResFile, $sModuleRelativeDir, $oP)
{
$sClass = $oClass->getAttribute('name');
$oProperties = $this->GetUniqueElement($oClass, 'properties');
// Class caracteristics
//
$aClassParams = array();
$aClassParams['category'] = "'".$oClass->getAttribute('category')."'";
$aClassParams['key_type'] = "'autoincrement'";
$oNaming = $this->GetUniqueElement($oProperties, 'naming');
$oNameAttributes = $this->GetUniqueElement($oNaming, 'attributes');
$oAttributes = $oNameAttributes->getElementsByTagName('attribute');
$aNameAttCodes = array();
foreach($oAttributes as $oAttribute)
{
$aNameAttCodes[] = $oAttribute->getAttribute('name');
}
if (count($aNameAttCodes) > 1)
{
// New style...
$sNameAttCode = "array('".implode("', '", $aNameAttCodes)."')";
}
elseif (count($aNameAttCodes) == 1)
{
// New style...
$sNameAttCode = "'$aNameAttCodes[0]'";
}
else
{
$sNameAttCode = "''";
}
$aClassParams['name_attcode'] = $sNameAttCode;
$oLifecycle = $this->GetOptionalElement($oClass, 'lifecycle');
if ($oLifecycle)
{
$sStateAttCode = $oLifecycle->getAttribute('attribute');
}
else
{
$sStateAttCode = "";
}
$aClassParams['state_attcode'] = "'$sStateAttCode'";
$oReconciliation = $this->GetUniqueElement($oProperties, 'reconciliation');
$oReconcAttributes = $oReconciliation->getElementsByTagName('attribute');
$aReconcAttCodes = array();
foreach($oReconcAttributes as $oAttribute)
{
$aReconcAttCodes[] = $oAttribute->getAttribute('name');
}
$sReconcKeys = "array('".implode("', '", $aReconcAttCodes)."')";
$aClassParams['reconc_keys'] = $sReconcKeys;
$aClassParams['db_table'] = "'".$oClass->getAttribute('db_table')."'";
$aClassParams['db_key_field'] = "'".$oClass->getAttribute('db_key_field')."'";
$aClassParams['db_finalclass_field'] = "'".$oClass->getAttribute('db_final_class_field')."'";
$oDisplayTemplate = $this->GetOptionalElement($oProperties, 'display_template');
if ($oDisplayTemplate && (strlen($oDisplayTemplate->textContent) > 0))
{
$sDisplayTemplate = $sModuleRelativeDir.'/'.$oDisplayTemplate->textContent;
$aClassParams['display_template'] = "utils::GetAbsoluteUrlModulesRoot().'$sDisplayTemplate'";
}
$oIcon = $this->GetOptionalElement($oProperties, 'icon');
if ($oIcon && (strlen($oIcon->textContent) > 0))
{
$sIcon = $sModuleRelativeDir.'/'.$oIcon->textContent;
$aClassParams['icon'] = "utils::GetAbsoluteUrlModulesRoot().'$sIcon'";
}
$oOrder = $this->GetOptionalElement($oProperties, 'order');
if ($oOrder)
{
$oColumnsNode = $this->GetUniqueElement($oOrder, 'columns');
$oColumns = $oColumnsNode->getElementsByTagName('column');
$aSortColumns = array();
foreach($oColumns as $oColumn)
{
$aSortColumns[] = "'".$oColumn->getAttribute('name')."' => ".(($oColumn->getAttribute('ascending') == 'true') ? 'true' : 'false');
}
if (count($aSortColumns) > 0)
{
$aClassParams['order_by_default'] = "array(".implode(", ", $aSortColumns).")";
}
}
// Finalize class params declaration
//
$aClassParamsPHP = array();
foreach($aClassParams as $sKey => $sPHPValue)
{
$aClassParamsPHP[] = " '$sKey' => $sPHPValue,";
}
$sClassParams = implode("\n", $aClassParamsPHP);
// Comment on top of the class declaration
//
$oComment = $this->GetOptionalElement($oProperties, 'comment');
if ($oComment)
{
$sCodeComment = $oComment->textContent;
}
else
{
$sCodeComment = '';
}
// Fields
//
$sAttributes = '';
foreach($this->oFactory->ListFields($oClass) as $oField)
{
// $oField
$sAttCode = $oField->getAttribute('name');
$sAttType = 'Attribute'.$oField->getAttribute('type');
$aDependencies = array();
$oDependencies = $this->GetOptionalElement($oField, 'dependencies');
if (!is_null($oDependencies))
{
$oDepNodes = $oDependencies->getElementsByTagName('attribute');
foreach($oDepNodes as $oDepAttribute)
{
$aDependencies[] = "'".$oDepAttribute->getAttribute('name')."'";
}
}
$sDependencies = 'array('.implode(', ', $aDependencies).')';
$aParameters = array();
if ($sAttType == 'AttributeLinkedSetIndirect')
{
$aParameters['linked_class'] = "'".$oField->getAttribute('linked_class')."'";
$aParameters['ext_key_to_me'] = "'".$oField->getAttribute('ext_key_to_me')."'";
$aParameters['ext_key_to_remote'] = "'".$oField->getAttribute('ext_key_to_remote')."'";
// todo - utile ?
$aParameters['allowed_values'] = 'null';
$aParameters['count_min'] = $oField->getAttribute('count_min');
$aParameters['count_max'] = $oField->getAttribute('count_max');
$aParameters['depends_on'] = $sDependencies;
}
elseif ($sAttType == 'AttributeLinkedSet')
{
$aParameters['linked_class'] = "'".$oField->getAttribute('linked_class')."'";
$aParameters['ext_key_to_me'] = "'".$oField->getAttribute('ext_key_to_me')."'";
// todo - utile ?
$aParameters['allowed_values'] = 'null';
$aParameters['count_min'] = $oField->getAttribute('count_min');
$aParameters['count_max'] = $oField->getAttribute('count_max');
$aParameters['depends_on'] = $sDependencies;
}
elseif ($sAttType == 'AttributeExternalKey')
{
$aParameters['targetclass'] = "'".$oField->getAttribute('target_class')."'";
// todo = v�rifier l'utilit�
$aParameters['jointype'] = 'null';
if (($sOql = $oField->getAttribute('filter')) != '')
{
$sEscapedOql = addslashes($sOql);
$aParameters['allowed_values'] = "new ValueSetObjects('$sEscapedOql')"; // or "new ValueSetObjects('SELECT xxxx')"
}
else
{
$aParameters['allowed_values'] = 'null'; // or "new ValueSetObjects('SELECT xxxx')"
}
$aParameters['sql'] = "'".$oField->getAttribute('sql')."'";
$aParameters['is_null_allowed'] = $oField->getAttribute('is_null_allowed') == 'true' ? 'true' : 'false';
$aParameters['on_target_delete'] = $oField->getAttribute('on_target_delete');
$aParameters['depends_on'] = $sDependencies;
}
elseif ($sAttType == 'AttributeHierarchicalKey')
{
if (($sOql = $oField->getAttribute('filter')) != '')
{
$sEscapedOql = addslashes($sOql);
$aParameters['allowed_values'] = "new ValueSetObjects('$sEscapedOql')"; // or "new ValueSetObjects('SELECT xxxx')"
}
else
{
$aParameters['allowed_values'] = 'null'; // or "new ValueSetObjects('SELECT xxxx')"
}
$aParameters['sql'] = "'".$oField->getAttribute('sql')."'";
$aParameters['is_null_allowed'] = $oField->getAttribute('is_null_allowed') == 'true' ? 'true' : 'false';
$aParameters['on_target_delete'] = $oField->getAttribute('on_target_delete');
$aParameters['depends_on'] = $sDependencies;
}
elseif ($sAttType == 'AttributeExternalField')
{
$aParameters['allowed_values'] = 'null';
$aParameters['extkey_attcode'] = "'".$oField->getAttribute('extkey_attcode')."'";
$aParameters['target_attcode'] = "'".$oField->getAttribute('target_attcode')."'";
}
elseif ($sAttType == 'AttributeURL')
{
$aParameters['target'] = "'".$oField->getAttribute('target')."'";
$aParameters['allowed_values'] = 'null';
$aParameters['sql'] = "'".$oField->getAttribute('sql')."'";
$aParameters['default_value'] = "'".$oField->getAttribute('default_value')."'";
$aParameters['is_null_allowed'] = $oField->getAttribute('is_null_allowed') == 'true' ? 'true' : 'false';
$aParameters['depends_on'] = $sDependencies;
}
elseif ($sAttType == 'AttributeEnum')
{
$oValues = $this->GetUniqueElement($oField, 'values');
$oValueNodes = $oValues->getElementsByTagName('value');
$aValues = array();
foreach($oValueNodes as $oValue)
{
// new style... $aValues[] = "'".addslashes($oValue->textContent)."'";
$aValues[] = $oValue->textContent;
}
// new style... $sValues = 'array('.implode(', ', $aValues).')';
$sValues = '"'.implode(',', $aValues).'"';
$aParameters['allowed_values'] = "new ValueSetEnum($sValues)";
$aParameters['sql'] = "'".$oField->getAttribute('sql')."'";
$aParameters['default_value'] = "'".$oField->getAttribute('default_value')."'";
$aParameters['is_null_allowed'] = $oField->getAttribute('is_null_allowed') == 'true' ? 'true' : 'false';
$aParameters['depends_on'] = $sDependencies;
}
elseif ($sAttType == 'AttributeBlob')
{
$aParameters['depends_on'] = $sDependencies;
}
else
{
$aParameters['allowed_values'] = 'null'; // or "new ValueSetEnum('SELECT xxxx')"
$aParameters['sql'] = "'".$oField->getAttribute('sql')."'";
$aParameters['default_value'] = "'".$oField->getAttribute('default_value')."'";
$aParameters['is_null_allowed'] = $oField->getAttribute('is_null_allowed') == 'true' ? 'true' : 'false';
$aParameters['depends_on'] = $sDependencies;
if ($sValidationPattern = $oField->getAttribute('validation_pattern'))
{
$aParameters['validation_pattern'] = '"'.addslashes($sValidationPattern).'"';
}
}
$aParams = array();
foreach($aParameters as $sKey => $sValue)
{
$aParams[] = '"'.$sKey.'"=>'.$sValue;
}
$sParams = implode(', ', $aParams);
$sAttributes .= " MetaModel::Init_AddAttribute(new $sAttType(\"$sAttCode\", array($sParams)));\n";
}
// Lifecycle
//
$sLifecycle = '';
if ($oLifecycle)
{
$sLifecycle .= "\t\t// Lifecycle (status attribute: $sStateAttCode)\n";
$sLifecycle .= "\t\t//\n";
$oStimuli = $this->GetUniqueElement($oLifecycle, 'stimuli');
foreach ($oStimuli->getElementsByTagName('stimulus') as $oStimulus)
{
$sStimulus = $oStimulus->getAttribute('name');
$sStimulusClass = $oStimulus->getAttribute('type');
$sLifecycle .= " MetaModel::Init_DefineStimulus(new ".$sStimulusClass."(\"".$sStimulus."\", array()));\n";
}
$oStates = $this->GetUniqueElement($oLifecycle, 'states');
foreach ($oStates->getElementsByTagName('state') as $oState)
{
$sState = $oState->getAttribute('name');
$sLifecycle .= " MetaModel::Init_DefineState(\n";
$sLifecycle .= " \"".$sState."\",\n";
$sLifecycle .= " array(\n";
$sLifecycle .= " \"attribute_inherit\" => '',\n";
$sLifecycle .= " \"attribute_list\" => array(\n";
$oFlags = $this->GetUniqueElement($oState, 'flags');
foreach ($oFlags->getElementsByTagName('attribute') as $oAttributeNode)
{
$sFlags = $this->FlagsToPHP($oAttributeNode);
if (strlen($sFlags) > 0)
{
$sAttCode = $oAttributeNode->GetAttribute('name');
$sLifecycle .= " '$sAttCode' => $sFlags,\n";
}
}
$sLifecycle .= " ),\n";
$sLifecycle .= " )\n";
$sLifecycle .= " );\n";
$oTransitions = $this->GetUniqueElement($oState, 'transitions');
foreach ($oTransitions->getElementsByTagName('transition') as $oTransition)
{
$sStimulus = $oTransition->getAttribute('stimulus');
$sTargetState = $oTransition->getAttribute('target');
$oActions = $this->GetUniqueElement($oTransition, 'actions');
$aVerbs = array();
foreach ($oActions->getElementsByTagName('action') as $oAction)
{
$sVerb = $oAction->getAttribute('verb');
$aVerbs[] = "'$sVerb'";
}
$sActions = implode(', ', $aVerbs);
$sLifecycle .= " MetaModel::Init_DefineTransition(\"$sState\", \"$sStimulus\", array(\"target_state\"=>\"$sTargetState\", \"actions\"=>array($sActions), \"user_restriction\"=>null));\n";
}
}
}
// ZLists
//
$aListRef = array(
'details' => 'details',
'standard_search' => 'search',
'list' => 'list'
);
$oPresentation = $this->GetUniqueElement($oClass, 'presentation');
$sZlists = '';
foreach ($aListRef as $sListCode => $sListTag)
{
$oListNode = $this->GetOptionalElement($oPresentation, $sListTag);
if ($oListNode)
{
$aAttributes = $this->GetNodeAsArrayOfItems($oListNode);
$sZAttributes = var_export($aAttributes, true);
$sZlists .= " MetaModel::Init_SetZListItems('$sListCode', $sZAttributes);\n";
}
}
// Methods
$sMethods = "";
$oMethods = $this->GetUniqueElement($oClass, 'methods');
foreach($oMethods->getElementsByTagName('method') as $oMethod)
{
$sMethodCode = $this->GetNodeText($oMethod);
$oMethodComment = $this->GetOptionalElement($oMethod, 'comment');
if ($oMethodComment)
{
$sMethods .= "\n\t".$oMethodComment->textContent."\n".$sMethodCode."\n";
}
else
{
$sMethods .= "\n\n".$sMethodCode."\n";
}
}
// Let's make the whole class declaration
//
$sPHP = "\n\n$sCodeComment\n";
if ($oClass->getAttribute('abstract') == 'true')
{
$sPHP .= 'abstract class '.$oClass->getAttribute('name');
}
else
{
$sPHP .= 'class '.$oClass->getAttribute('name');
}
$sPHP .= " extends ".$oClass->getAttribute('parent')."\n";
$sPHP .=
<<getAttribute("id");
$sMenuClass = $oMenu->getAttribute("type");
$oParent = $this->GetOptionalElement($oMenu, 'parent');
if ($oParent)
{
$sParent = $oParent->GetAttribute('value');
$sParentSpec = "\$__comp_menus__['$sParent']->GetIndex()";
}
else
{
$sParentSpec = '-1';
}
$fRank = $this->GetUniqueElement($oMenu, 'rank')->GetAttribute('value');
switch($sMenuClass)
{
case 'WebPageMenuNode':
$sUrl = $this->GetUniqueElement($oMenu, 'url')->GetAttribute('value');
$sUrlSpec = $this->PathToPHP($sUrl, $sModuleRelativeDir, true /* Url */);
$sNewMenu = "new WebPageMenuNode('$sMenuId', $sUrlSpec, $sParentSpec, $fRank);";
break;
case 'TemplateMenuNode':
$sTemplateFile = $this->GetUniqueElement($oMenu, 'template_file')->GetAttribute('value');
$sTemplateSpec = $this->PathToPHP($sTemplateFile, $sModuleRelativeDir);
$sNewMenu = "new TemplateMenuNode('$sMenuId', $sTemplateSpec, $sParentSpec, $fRank);";
break;
case 'OQLMenuNode':
$sOQL = $this->GetUniqueElement($oMenu, 'oql')->GetAttribute('value');
$bSearch = ($this->GetUniqueElement($oMenu, 'do_search')->GetAttribute('value') == '1') ? 'true' : 'false';
$sNewMenu = "new OQLMenuNode('$sMenuId', '$sOQL', $sParentSpec, $fRank, $bSearch);";
break;
case 'NewObjectMenuNode':
$sClass = $this->GetUniqueElement($oMenu, 'class')->GetAttribute('value');
$sNewMenu = "new NewObjectMenuNode('$sMenuId', '$sClass', $sParentSpec, $fRank);";
break;
case 'SearchMenuNode':
$sClass = $this->GetUniqueElement($oMenu, 'class')->GetAttribute('value');
$sNewMenu = "new SearchMenuNode('$sMenuId', '$sClass', $sParentSpec, $fRank);";
break;
case 'MenuGroup':
default:
if ($oEnableClass = $this->GetOptionalElement($oMenu, 'enable_class'))
{
$sEnableClass = $oEnableClass->GetAttribute('value');
$sEnableAction = $this->GetUniqueElement($oMenu, 'enable_action')->GetAttribute('value');
$sEnablePermission = $this->GetUniqueElement($oMenu, 'enable_permission')->GetAttribute('value');
$sEnableStimulus = $this->GetUniqueElement($oMenu, 'enable_stimulus')->GetAttribute('value');
if (strlen($sEnableStimulus) > 0)
{
$sNewMenu = "new MenuGroup('$sMenuId', $fRank, '$sEnableClass', $sEnableAction, $sEnablePermission, '$sEnableStimulus');";
}
else
{
$sNewMenu = "new MenuGroup('$sMenuId', $fRank, '$sEnableClass', $sEnableAction, $sEnablePermission);";
}
//$sNewMenu = "new MenuGroup('$sMenuId', $fRank, '$sEnableClass', UR_ACTION_MODIFY, UR_ALLOWED_YES|UR_ALLOWED_DEPENDS);";
}
else
{
$sNewMenu = "new MenuGroup('$sMenuId', $fRank);";
}
}
$sIndent = ' ';
$sPHPMenu = "\$__comp_menus__['$sMenuId'] = $sNewMenu";
$oAdminOnly = $this->GetOptionalElement($oMenu, 'enable_admin_only');
if ($oAdminOnly && $oAdminOnly->GetAttribute('value') == '1')
{
$sPHP = $sIndent."if (UserRights::IsAdministrator())\n";
$sPHP .= $sIndent."{\n";
$sPHP .= $sIndent." $sPHPMenu\n";
$sPHP .= $sIndent."}\n";
}
else
{
$sPHP = $sIndent."$sPHPMenu\n";
}
file_put_contents($sResFile, $sPHP, FILE_APPEND);
}
}
?>