* @package Xmind * @version $Id$ * @link http://www.zentao.net */ class xmind { /** * Add suffix before string. * * @param string $str * @param string $suffix * @access public * @return string */ public function toText($str, $suffix) { if(empty($suffix)) return $str; return $str . '[' . $suffix . ']'; } /** * Create module node. * * @param DOMDocument $xmlDoc * @param array $context * @param DOMElement $productTopics * @param array $moduleTopics * @access public * @return void */ function createModuleTopic($xmlDoc, $context, $productTopics, &$moduleTopics) { $config = $context['config']; $moduleList = $context['moduleList']; $caseModules = array_column($context['caseList'], 'moduleID'); $caseModules = array_filter($caseModules); $caseModules = array_combine($caseModules, $caseModules); foreach($moduleList as $key => $name) { if(!isset($caseModules[$key])) continue; $suffix = $config['module'] . ':' . $key; $moduleTopic = $this->createTopic($xmlDoc, $name, $suffix, array('nodeType' => 'module')); $moduleChildrenTopics = $this->createTopics($xmlDoc); $moduleChildren = $xmlDoc->createElement('children'); $moduleChildren->appendChild($moduleChildrenTopics); $moduleTopic->appendChild($moduleChildren); $productTopics->appendChild($moduleTopic); $moduleTopics[$key] = $moduleChildrenTopics; } } /** * Create scene node. * * @param DOMDocument $xmlDoc * @param array $context * @param DOMElement $productTopics * @param array $moduleTopics * @param array $sceneTopics * @access public * @return void */ function createSceneTopic($xmlDoc, $context, $productTopics, &$moduleTopics, &$sceneTopics) { $config = $context['config']; $topScenes = $context['topScenes']; $caseScenes = array_column($context['caseList'], 'moduleID'); $caseScenes = array_filter($caseScenes); $caseScenes = array_combine($caseScenes, $caseScenes); foreach($topScenes as $key => $scene) { if(!isset($caseScenes[$key])) continue; $suffix = $config['scene'] . ':' . $scene->sceneID; $sceneTopic = $this->createTopic($xmlDoc, $scene->sceneName, $suffix, array('nodeType' => 'scene')); $sceneChildrenTopics = $this->createTopics($xmlDoc); $sceneChildren = $xmlDoc->createElement('children'); $sceneChildren->appendChild($sceneChildrenTopics); $sceneTopic->appendChild($sceneChildren); $this->createNextChildScenesTopic($scene, $sceneTopic, $xmlDoc, $context, $moduleTopics, $sceneTopics); if(isset($moduleTopics[$scene->moduleID])) { $moduleTopic = $moduleTopics[$scene->moduleID]; $moduleTopic->appendChild($sceneTopic); } else { $productTopics->appendChild($sceneTopic); } $sceneTopics[$scene->sceneID] = $sceneChildrenTopics; } } /** * Create next child scene node. * * @param object $parentScene * @param object $parentTopic * @param DOMDocument $xmlDoc * @param array $context * @param array $moduleTopics * @param array $sceneTopics * @access public * @return void */ function createNextChildScenesTopic($parentScene,$parentTopic, $xmlDoc, $context, &$moduleTopics, &$sceneTopics) { $sceneMaps = $context['sceneMaps']; $config = $context['config']; foreach($sceneMaps as $scene) { if($scene->parentID != $parentScene->sceneID) continue; $suffix = $config['scene'] . ':' . $scene->sceneID; $sceneTopic = $this->createTopic($xmlDoc, $scene->sceneName, $suffix, array('nodeType'=>'scene')); $this->createNextChildScenesTopic($scene, $sceneTopic, $xmlDoc, $context, $moduleTopics, $sceneTopics); $sceneChildrenTopics = $this->createTopics($xmlDoc); $sceneChildren = $xmlDoc->createElement('children'); $sceneChildren->appendChild($sceneChildrenTopics); $sceneTopic->appendChild($sceneChildren); $sceneTopics[$scene->sceneID] = $sceneChildrenTopics; } } /** * Create test case node. * * @param DOMDocument $xmlDoc * @param array $context * @param object $productTopic * @param array $moduleTopics * @param array $sceneTopics * @access public * @return void */ function createTestcaseTopic($xmlDoc, $context, $productTopic, &$moduleTopics, &$sceneTopics) { $caseList = $context['caseList']; foreach($caseList as $case) { if(empty($case->testcaseID)) continue; if($case->sceneID && isset($sceneTopics[$case->sceneID])) { $this->createOneTestcaseTopic($case, $xmlDoc, $context, $sceneTopics[$case->sceneID]); } else { if($case->moduleID && isset($moduleTopics[$case->moduleID])) { $this->createOneTestcaseTopic($case, $xmlDoc, $context, $moduleTopics[$case->moduleID]); } else { $this->createOneTestcaseTopic($case, $xmlDoc, $context, $productTopic); } } } } /** * Create one test case node. * * @param object $case * @param DOMDocument $xmlDoc * @param array $context * @param object $parentTopic * @access public * @return void */ function createOneTestcaseTopic($case, $xmlDoc, $context, $parentTopic) { $stepList = $context['stepList']; $config = $context['config']; $suffix = $config['case'] . ':'.$case->testcaseID . ','.$config['pri'] . ':'.$case->pri; $caseTopic = $this->createTopic($xmlDoc, $case->name, $suffix, array('nodeType'=>'testcase')); $caseChildrenTopics = $this->createTopics($xmlDoc); $caseChildren = $xmlDoc->createElement('children'); $caseChildren->appendChild($caseChildrenTopics); $caseTopic->appendChild($caseChildren); $parentTopic->appendChild($caseTopic); $this->createPreconditionTopic($xmlDoc, $config, $caseChildrenTopics, $case->precondition); $topStepList = $this->findTopStepListByCase($case, $stepList); $this->createStepTopic($xmlDoc, $config, $caseChildrenTopics, $stepList, $topStepList); } /** * 生成用例前置条件节点。 * Create precondition node. * * @param DOMDocument $xmlDoc * @param array $config * @param object $parentTopic * @param string $precondition * @access private * @return void */ private function createPreconditionTopic($xmlDoc, $config, $parentTopics, $precondition) { if(empty($precondition)) return false; $preconditionTopic = $this->createTopic($xmlDoc, $precondition, $config['precondition'], array('nodeType' => 'precondition')); $parentTopics->appendChild($preconditionTopic); } /** * 生成用例步骤节点。 * Create step node. * * @param DOMDocument $xmlDoc * @param array $config * @param object $parentTopic * @param array $allSteps * @param array $steps * @access private * @return void */ private function createStepTopic($xmlDoc, $config, $parentTopics, $allSteps, $steps) { foreach($steps as $step) { $subSteps = $this->findSubStepListByStep($step, $allSteps); $suffix = count($subSteps) > 0 ? $config['group'] : ''; $stepTopic = $this->createTopic($xmlDoc, $step->desc, $suffix, array('nodeType' => 'step')); $stepChildrenTopics = $this->createTopics($xmlDoc); $stepChildren = $xmlDoc->createElement('children'); $stepChildren->appendChild($stepChildrenTopics); if($subSteps) { $this->createStepTopic($xmlDoc, $config, $stepChildrenTopics, $allSteps, $subSteps); } else if(!empty($step->expect)) { $expectTopic = $this->createTopic($xmlDoc, $step->expect, '', array('nodeType' => 'expect')); $stepChildrenTopics->appendChild($expectTopic); } $stepTopic->appendChild($stepChildren); $parentTopics->appendChild($stepTopic); } } /** * Find substep list by step. * * @param object $step * @param array $stepList * @access public * @return array */ function findSubStepListByStep($step, $stepList) { $subList = array(); foreach($stepList as $one) { if($one->parentID == $step->stepID) $subList[] = $one; } return $subList; } /** * Find top step list by case. * * @param object $case * @param array $stepList * @access public * @return array */ public function findTopStepListByCase($case, $stepList) { $topList = array(); foreach($stepList as $step) { if($step->parentID == '0' && $step->testcaseID == $case->testcaseID) $topList[] = $step; } return $topList; } /** * Create xmind topic. * * @param DOMDocument $xmlDoc * @param string $text * @param string $suffix * @param array $attrs * @access public * @return object */ public function createTopic($xmlDoc, $text, $suffix = '', $attrs = array()) { $topic = $xmlDoc->createElement('topic'); $titleAttr = $xmlDoc->createElement('title', $this->toText($text, $suffix)); $topic->appendChild($titleAttr); $idAttr = $xmlDoc->createElement('id', uniqid()); $topic->appendChild($idAttr); foreach($attrs as $key => $value) { $attr = $xmlDoc->createAttribute($key); $attrValue = $xmlDoc->createTextNode($value); $attr->appendChild($attrValue); $topic->appendChild($attr); } return $topic; } /** * Get substring between mark1 and mark2 from kw. * * @param string $str * @param string $suffix * @access public * @return string */ function getBetween($kw1, $mark1, $mark2) { $kw = $kw1; $kw = '123' . $kw . '123'; $st = strripos($kw, $mark1); $ed = strripos($kw, $mark2); if(($st == false || $ed == false) || $st >= $ed) return 0; $kw = substr($kw, ($st + 1), ($ed - $st - 1)); return $kw; } /** * Judgment ends with a string. * * @param string $haystack * @param string $needle * @access public * @return string */ function endsWith($haystack, $needle) { return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0; } /** * Create children topics. * * @param DOMDocument $xmlDoc * @access public * @return void */ function createChildrenTopics($xmlDoc) { $topics = $this->createTopics($xmlDoc); $children = $xmlDoc->createElement('children'); $children->appendChild($topics); return $children; } /** * Create topics. * * @param DOMDocument $xmlDoc * @access public * @return void */ public function createTopics($xmlDoc) { $type = $xmlDoc->createAttribute('type'); $type->value = 'attached'; $topics = $xmlDoc->createElement('topics'); $topics->appendChild($type); return $topics; } /** * Init xmap content. * * @param DOMDocument $xmlDoc * @access public * @return void */ public function initXmapContent($xmlDoc) { $xmapContent = $xmlDoc->createElement('xmap-content'); $attrs = array(); $attrs['xmlns'] = "urn:xmind:xmap:xmlns:content:2.0"; $attrs['xmlns:fo'] = "http://www.w3.org/1999/XSL/Format"; $attrs['xmlns:svg'] = "http://www.w3.org/2000/svg"; $attrs['xmlns:xhtml'] = "http://www.w3.org/1999/xhtml"; $attrs['xmlns:xlink'] = "http://www.w3.org/1999/xlink"; foreach($attrs as $key => $value) { $attr = $xmlDoc->createAttribute($key); $attrValue = $xmlDoc->createTextNode($value); $attr->appendChild($attrValue); $xmapContent->appendChild($attr); } return $xmapContent; } }