Exemplo n.º 1
0
 /**
  * drawRequirementsGraph Will draw a requirement graph if PEAR::Image_GraphViz is installed
  *
  * @param boolean $pInstallVersion Use the actual installed version instead of the version that will be in bitweaver after the upgrade
  * @param string $pFormat dot output format
  * @param string $pCommand dot or neato
  * @access public
  * @return boolean TRUE on success, FALSE on failure - mErrors will contain reason for failure
  */
 function drawRequirementsGraph($pInstallVersion = FALSE, $pFormat = 'png', $pCommand = 'dot')
 {
     global $gBitSmarty, $gBitThemes;
     // only do this if we can load PEAR GraphViz interface
     if (@(include_once 'Image/GraphViz.php')) {
         ksort($this->mPackages);
         $deps = $this->calculateRequirements($pInstallVersion);
         $delKeys = $matches = array();
         // crazy manipulation of hash to remove duplicate version matches.
         // we do this that we can use double headed arrows in the graph below.
         foreach ($deps as $key => $req) {
             foreach ($deps as $k => $d) {
                 if ($req['requires'] == $d['package'] && $req['package'] == $d['requires'] && $req['result'] == 'ok' && $d['result'] == 'ok') {
                     $deps[$key]['dir'] = 'both';
                     $matches[$key] = $k;
                 }
             }
         }
         // get duplicates
         foreach ($matches as $key => $match) {
             unset($delKeys[$match]);
             $delKeys[$key] = $match;
         }
         // remove dupes from hash
         foreach ($delKeys as $key) {
             unset($deps[$key]);
         }
         // start drawing stuff
         $graph = new Image_GraphViz(TRUE, $gBitThemes->getGraphvizGraphAttributes(), 'Requirements', TRUE);
         $fromattributes = $toattributes = $gBitThemes->getGraphvizNodeAttributes();
         foreach ($deps as $node) {
             //$fromNode = ucfirst( $node['package'] )."\n".$node['package_version'];
             //$toNode   = ucfirst( $node['requires'] )."\n".$node['required_version']['min'];
             $fromNode = ucfirst($node['package']);
             $toNode = ucfirst($node['requires']);
             switch ($node['result']) {
                 case 'max_dep':
                     $edgecolor = 'chocolate3';
                     $label = 'Maximum version\\nexceeded';
                     $toNode .= "\n" . $node['required_version']['min'] . " - " . $node['required_version']['max'];
                     $toattributes['fillcolor'] = 'khaki';
                     break;
                 case 'min_dep':
                     $edgecolor = 'crimson';
                     $label = 'Minimum version\\nnot met';
                     $toNode .= "\n" . $node['required_version']['min'];
                     if (!empty($node['required_version']['max'])) {
                         $toNode .= " - " . $node['required_version']['max'];
                     }
                     $toattributes['fillcolor'] = 'pink';
                     break;
                 case 'missing':
                     $edgecolor = 'crimson';
                     $label = 'Not installed\\nor activated';
                     $toNode .= "\n" . $node['required_version']['min'];
                     if (!empty($node['required_version']['max'])) {
                         $toNode .= " - " . $node['required_version']['max'];
                     }
                     $toattributes['fillcolor'] = 'pink';
                     break;
                 default:
                     $edgecolor = '';
                     $label = '';
                     $toattributes['fillcolor'] = 'white';
                     break;
             }
             $fromattributes['URL'] = "http://www.bitweaver.org/wiki/" . ucfirst($node['package']) . "Package";
             $graph->addNode($fromNode, $fromattributes);
             $toattributes['URL'] = "http://www.bitweaver.org/wiki/" . ucfirst($node['requires']) . "Package";
             $graph->addNode($toNode, $toattributes);
             $graph->addEdge(array($fromNode => $toNode), $gBitThemes->getGraphvizEdgeAttributes(array('dir' => !empty($node['dir']) ? $node['dir'] : '', 'color' => $edgecolor, 'fontcolor' => $edgecolor, 'label' => $label)));
         }
         if (preg_match("#(png|gif|jpe?g|bmp|svg|tif)#i", $pFormat)) {
             $graph->image($pFormat, $pCommand);
         } else {
             return $graph->fetch($pFormat, $pCommand);
         }
     } else {
         return FALSE;
     }
 }
 /**
  * This method returns a list of absolute paths containing the location of
  * images that inlustrate a specific workflow. Such images are generated
  * each workflow specification.
  * If any requested image is not present or if it's older than the
  * workflow's configuration file, all images for such workflow are
  * generated.
  *
  * @warning This method requires GraphViz.
  *
  * @param string $workflowName Workflow name to look for.
  * @return string[string] Returns a list of paths containing these keys:
  * WKFL_AFIELD_FILE, WKFL_AFIELD_THUMB (these are defined constants).
  */
 public function graphPath($workflowName)
 {
     //
     // Defautl values.
     $out = false;
     //
     // Checking and including library.
     if (@(require_once 'Image/GraphViz.php')) {
         //
         // Checking required directories permissions.
         $this->checkGraphsDirectories();
         //
         // Global dependencies.
         global $WKFLDefaults;
         //
         // Default values.
         $generateIt = false;
         //
         // Retrieving the workflow.
         $workflow = $this->getWorkflow($workflowName);
         //
         // Guessing paths.
         $graphPath = Sanitizer::DirPath("{$WKFLDefaults[WKFL_DEFAULTS_GRAPHS_PATH]}/{$workflowName}.png");
         $graphThumbPath = Sanitizer::DirPath("{$WKFLDefaults[WKFL_DEFAULTS_GRAPHS_PATH]}/{$workflowName}-256px.png");
         //
         // Checking paths existence.
         if (!$generateIt && (!is_file($graphPath) || !is_file($graphThumbPath))) {
             $generateIt = true;
         }
         //
         // Checking paths' last modification dates.
         if (!$generateIt) {
             $workflowTime = filemtime($workflow->path());
             $generateIt = filemtime($graphPath) < $workflowTime || filemtime($graphThumbPath) < $workflowTime;
         }
         //
         // Do these images have to be generated?
         if ($generateIt) {
             //
             // Logging pre-generation information.
             $this->_log->log(LGGR_LOG_LEVEL_INFO, "Gereating graph for '{$workflowName}'.");
             $this->_log->log(LGGR_LOG_LEVEL_DEBUG, "Workflow '{$workflowName}' graph path: '{$graphPath}'");
             $this->_log->log(LGGR_LOG_LEVEL_DEBUG, "                           thumb path: '{$graphThumbPath}'");
             //
             // Creating an image.
             $graph = new \Image_GraphViz();
             //
             // Addind begining node.
             $graph->addNode('BEGIN', ['shape' => 'circle', 'label' => '', 'color' => 'black']);
             //
             // Configuration shortcut.
             $workflowConfig = $workflow->config();
             //
             // Creating a squared node for each step.
             foreach ($workflowConfig->steps as $stepName => $step) {
                 $graph->addNode($stepName, array('label' => $stepName, 'shape' => 'box'));
             }
             //
             // Addind ending node.
             $graph->addNode('END', ['shape' => 'circle', 'label' => '', 'color' => 'black', 'style' => 'filled']);
             //
             // Linking the beginning node to the first step.
             $graph->addEdge(['BEGIN' => $workflowConfig->startsAt]);
             //
             // Linking all steps based on connections
             // confiugrations.
             foreach ($workflowConfig->steps as $stepName => $step) {
                 //
                 // Checking each connection for current
                 // step.
                 foreach ($step->connections as $connName => $conn) {
                     //
                     // Checking if this connection
                     // either changes the flow status
                     // or sets the next step.
                     if (isset($conn->status)) {
                         //
                         // Checking what change is taking.
                         switch ($conn->status) {
                             case WKFL_ITEM_FLOW_STATUS_FAILED:
                             case WKFL_ITEM_FLOW_STATUS_DONE:
                                 //
                                 // These statuses link to the end.
                                 $graph->addEdge([$stepName => 'END'], ['label' => $connName, 'fontcolor' => 'brown', 'color' => 'brown']);
                                 break;
                             case WKFL_ITEM_FLOW_STATUS_WAIT:
                                 //
                                 // Basic attributes for each link.
                                 $attrs = ['label' => "{$connName}\n[wait]", 'color' => 'orange', 'fontcolor' => 'orange', 'style' => 'dashed'];
                                 //
                                 // Checking if this waiting has some extra
                                 // configuration.
                                 if (isset($conn->wait)) {
                                     //
                                     // This status creates a vitual node
                                     // representing the waiting step.
                                     $nodeName = "wait_{$stepName}";
                                     $graph->addNode($nodeName, ['shape' => 'box', 'label' => "wait:{$stepName}", 'fontcolor' => 'orange', 'color' => 'orange']);
                                     //
                                     // Linking the current step to this
                                     // virtual node.
                                     $graph->addEdge([$stepName => $nodeName], $attrs);
                                     //
                                     // Linking the virtual node to the current
                                     // one for less attempts than a limit.
                                     $attrs['label'] = "{$connName}\n[wait<={$conn->wait->attempts}]";
                                     $graph->addEdge([$nodeName => $stepName], $attrs);
                                     //
                                     // Linking the virtual node something else
                                     // for more attempts than a limit.
                                     $attrs['label'] = "{$connName}\n[wait>{$conn->wait->attempts}]";
                                     if (isset($conn->wait->status)) {
                                         //
                                         // Linking to the end.
                                         $graph->addEdge([$nodeName => 'END'], $attrs);
                                     } elseif (isset($conn->wait->step)) {
                                         //
                                         // Linking to another step.
                                         $graph->addEdge([$nodeName => $conn->wait->step], $attrs);
                                     }
                                 } else {
                                     $nextStep = isset($conn->step) ? $conn->step : $stepName;
                                     $graph->addEdge([$stepName => $nextStep], $attrs);
                                 }
                                 break;
                         }
                     } elseif (isset($conn->step)) {
                         //
                         // Linking this step to
                         // the next one.
                         $graph->addEdge([$stepName => $conn->step], ['label' => $connName, 'fontcolor' => 'darkgreen', 'color' => 'darkgreen']);
                     }
                 }
             }
             //
             // Saving the generated graphic in two locations,
             // one for the actual image and other for 256
             // pixels thumbnail.
             file_put_contents($graphPath, $graph->fetch('png'));
             file_put_contents($graphThumbPath, $graph->fetch('png'));
             //
             // Croping thumbnail.
             self::CropImage($graphThumbPath, 256);
         }
         //
         // Building the returning information.
         $out = array(WKFL_AFIELD_FILE => $graphPath, WKFL_AFIELD_THUMB => $graphThumbPath);
     } else {
         //
         // Logging the error of not having the proper library.
         $this->_log->log(LGGR_LOG_LEVEL_ERROR, "Pear GraphViz plugin hasn't been installed.");
     }
     return $out;
 }