p("no lifecycle for this class"); } else { $aStates = MetaModel::EnumStates($sClass); $aStimuli = MetaModel::EnumStimuli($sClass); $sDotFileContent .= "digraph finite_state_machine { graph [bgcolor = \"#eeeeee\"]; rankdir=LR; node [ fontname=Verdana style=filled fillcolor=\"#ffffff\" ]; edge [ fontname=Verdana ]; "; $aStatesLinks = array(); foreach ($aStates as $sStateCode => $aStateDef) { $aStatesLinks[$sStateCode] = array('in' => 0, 'out' => 0); } foreach ($aStates as $sStateCode => $aStateDef) { $sStateLabel = MetaModel::GetStateLabel($sClass, $sStateCode); $sStateDescription = MetaModel::GetStateDescription($sClass, $sStateCode); foreach(MetaModel::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef) { $aStatesLinks[$sStateCode]['out']++; $aStatesLinks[$aTransitionDef['target_state']]['in']++; $sStimulusLabel = $aStimuli[$sStimulusCode]->GetLabel(); $sTargetStateLabel = MetaModel::GetStateLabel($sClass, $aTransitionDef['target_state']); $sDotFileContent .= "\t$sStateCode -> {$aTransitionDef['target_state']} [ label=\"".GraphvizEscape($sStimulusLabel)."\"];\n"; } } foreach($aStates as $sStateCode => $aStateDef) { if (($aStatesLinks[$sStateCode]['out'] > 0) || ($aStatesLinks[$sStateCode]['in'] > 0)) { // Show only reachable states $sStateLabel = str_replace(' ', '\n', MetaModel::GetStateLabel($sClass, $sStateCode)); if ( ($aStatesLinks[$sStateCode]['in'] == 0) || ($aStatesLinks[$sStateCode]['out'] == 0)) { // End or Start state, make it look different $sDotFileContent .= "\t$sStateCode [ shape=doublecircle,label=\"".GraphvizEscape($sStateLabel)."\"];\n"; } else { $sDotFileContent .= "\t$sStateCode [ shape=circle,label=\"".GraphvizEscape($sStateLabel)."\"];\n"; } } } $sDotFileContent .= "}\n"; } return $sDotFileContent; } $sClass = utils::ReadParam('class', '', false, 'class'); $oReflection = new ReflectionClass($sClass); $sDeclarationFile = $oReflection->getFileName(); $sModuleDir = dirname($sDeclarationFile); $sImageFilePath = $sModuleDir."/lifecycle/".$sClass.".png"; $sDotExecutable = MetaModel::GetConfig()->Get('graphviz_path'); if (file_exists($sDotExecutable)) { // create the file with Graphviz $sImageFilePath = utils::GetDataPath()."lifecycle/".$sClass.".svg"; if (!is_dir(utils::GetDataPath())) { @mkdir(utils::GetDataPath()); } if (!is_dir(utils::GetDataPath()."lifecycle")) { @mkdir(utils::GetDataPath()."lifecycle"); } $sDotDescription = GraphvizLifecycle($sClass); $sDotFilePath = utils::GetDataPath()."lifecycle/{$sClass}.dot"; $rFile = @fopen($sDotFilePath, "w"); @fwrite($rFile, $sDotDescription); @fclose($rFile); $aOutput = array(); $CommandLine = "\"$sDotExecutable\" -v -Tsvg < \"$sDotFilePath\" -o \"$sImageFilePath\" 2>&1"; exec($CommandLine, $aOutput, $iRetCode); if ($iRetCode != 0) { header('Content-type: text/html'); echo "

Error:

"; echo "

The command:

$CommandLine
returned $iRetCode

"; echo "

The output of the command is:

\n".implode("\n", $aOutput)."

"; echo "
"; echo "

Content of the '".basename($sDotFilePath)."' file:

\n$sDotDescription
"; } else { header('Content-type: image/svg+xml'); header('Content-Disposition: inline; filename="'.$sClass.'.svg"'); readfile($sImageFilePath); } @unlink($sDotFilePath); // Image file is removed as well as there is no cache system yet @unlink($sImageFilePath); } else { header('Content-type: image/png'); header('Content-Disposition: inline; filename="'.$sClass.'.png"'); readfile($sImageFilePath); }