/**
  * Produces  a .dot file for the given modules as a string
  * @param array $modules of string the modules
  */
 public function dot($modules)
 {
     $mod_factory = I2CE_ModuleFactory::instance();
     $nodes = array();
     $paths = array();
     $scheme_details = $this->getSchemeDetails('dot');
     $config = I2CE::getConfig();
     if (array_key_exists('colors', $scheme_details) && is_array($scheme_details['colors'])) {
         $mod_groups = $scheme_details['colors'];
     } else {
         $mod_groups = array();
     }
     $node_groups = array();
     $config = I2Ce::getConfig();
     $mod_config = $config->config->data;
     foreach ($modules as $module) {
         if (!$mod_config->is_parent($module)) {
             continue;
         }
         $color = 'ivory3';
         foreach ($mod_groups as $m_module => $m_color) {
             if (strpos($module, $m_module) !== false) {
                 $color = $m_color;
                 break;
             }
         }
         $className = $mod_factory->getClassName($module);
         if ($className) {
             $className = ' (' . $className . ')';
         }
         $mod_data = array();
         foreach (array('displayName') as $key) {
             if (!$mod_config->is_scalar("{$module}/{$key}")) {
                 continue;
             }
             $mod_data[] = $mod_config->{$module}->{$key};
         }
         foreach ($mod_data as &$d) {
             $d = '<tr><td ALIGN=\'LEFT\'>' . $d . '</td></tr>';
         }
         $label = '<table border=\'0\' cellborder=\'0\'><tr><td BGCOLOR=\'white\' BORDER=\'1\'>' . $module . $className . '</td></tr>' . implode('', $mod_data) . '</table>';
         if (!array_key_exists($color, $node_groups) || !is_array($node_groups[$color])) {
             $node_groups[$color] = array();
         }
         $node_groups[$color][$module] = "\"{$module}\" [style=filled fillcolor = {$color}   label =<{$label}> shape = \"Mrecord\"   ];";
         if ($mod_config->is_parent("{$module}/requirement")) {
             $requirements = array_intersect($modules, $mod_config->getKeys("{$module}/requirement"));
         } else {
             $requirements = array();
         }
         if ($mod_config->is_parent("{$module}/conflict")) {
             $conflicts = array_intersect($modules, $mod_config->getKeys("{$module}/conflict"));
         } else {
             $conflicts = array();
         }
         if ($mod_config->is_parent("{$module}/enable")) {
             $enabled = array_intersect($modules, $mod_config->getKeys("{$module}/enable"));
         } else {
             $enabled = array();
         }
         foreach ($requirements as $req) {
             $paths[] = "\"{$module}\" -> \"{$req}\";";
         }
         foreach ($enabled as $end) {
             $paths[] = "\"{$module}\" -> \"{$end}\" [color=forestgreen];";
         }
         foreach ($conflicts as $con) {
             $paths[] = "\"{$module}\" -> \"{$con}\" [color=yellow];";
         }
     }
     $config = I2CE::getConfig();
     $module = $config->config->site->module;
     if (!$module) {
         I2CE::raiseError("No site module");
         return $graph;
     }
     if (array_key_exists('graph_options', $scheme_details) && is_array($scheme_details['graph_options'])) {
         $graph_options = $scheme_details['graph_options'];
     } else {
         $graph_options = array();
     }
     if (!array_key_exists('label', $graph_options) || !$graph_options['label'] || $graph_options['label'] == "''" || $graph_options['label'] == '""') {
         $title = 'Module Documentor';
         $version = '';
         $u_version = '';
         if ($config->setIfIsSet($title, "/config/data/{$module}/displayName")) {
             $title = str_ireplace('Demonstration', '', $title);
             $title = str_ireplace('Demo', '', $title);
             $title = trim($title);
             if ($config->setIfIsSet($version, "/config/data/{$module}/version")) {
                 $title .= ' - ' . $version;
                 $u_version = '_' . strtr($version, '.', '_');
             }
         }
         $graph_options['label'] = '"' . $title . '"';
     }
     $bgcolor = 'white';
     if (array_key_exists('bgcolor', $graph_options)) {
         $bgcolor = $graph_options['bgcolor'];
     }
     $graph_details = "graph [";
     foreach ($graph_options as $key => $val) {
         $graph_details .= "\n\t\t" . $key . '=' . $val;
     }
     $graph_details .= "\n\t];\n\tratio = auto;\n";
     foreach ($node_groups as $colors => $ns) {
         foreach ($ns as $n) {
             $nodes[] = $n;
         }
     }
     $graph = "digraph g {\n\t{$graph_details}\n\t" . implode("\n\t", $nodes) . implode("\n\t", $paths) . "\n}\n";
     $dot = trim(`which dot`);
     $unflatten = trim(`which unflatten`);
     if (!$dot || !$unflatten) {
         I2CE::raiseError("the dot utility was not found on your system.  cannot create the imate. try sudo apt-get install dot");
         return $graph;
     }
     $output_file = '/tmp/modules_' . $module . $u_version . '.gif';
     $dot = "{$unflatten} -f -l 2 -c 2 | {$dot} -T gif ";
     $composite = trim(`which composite`);
     $composite = false;
     if ($composite) {
         $watermark_file = I2CE::getFileSearch()->search('IMAGES', 'module_documentor_legend.gif');
         $watermark = '';
         if ($watermark_file) {
             $bgcolor_change = '';
             if (strtolower($bgcolor) != 'white') {
                 $bgcolor_change = "-fuzz 5% -fill {$bgcolor} -opaque white";
             }
             $watermark = "  |{$composite} gif:-  -gravity SouthEast  {$bgcolor_change} {$watermark_file} ";
         }
         $exec = $dot . $watermark . $output_file;
     } else {
         I2CE::raiseError("Imagemagick utitilies were not found on your system.  cannot watermark the file. try sudo apt-get isntall imagemagick");
         $exec = $dot . '-o ' . $output_file;
     }
     I2CE::raiseError("Attempting to execute:\n\t" . $exec);
     $proc = popen($exec, "w");
     if (!is_resource($proc)) {
         I2CE::raiseError("Could not start execute");
     } else {
         fwrite($proc, $graph);
         fclose($proc);
     }
     return $graph;
 }
 protected function actionRolesSave()
 {
     if (count($this->request_remainder) == 0) {
         //adding new role
         if (!$this->post_exists('role_short_name')) {
             $this->userMessage("No role short name set", 'notice', false);
             return;
         }
         $role = $this->post('role_short_name');
         if (array_key_exists($role, self::$fixed_roles)) {
             $this->userMessage("Invalid Role {$role} short name  specified", 'notice', false);
             return;
         }
         if (!$role || !I2CE_MagicDataNode::checkKey($role) || I2CE::getConfig()->is_parent("/I2CE/formsData/forms/role/{$role}")) {
             $this->userMessage("Bad role short name {$role}", 'notice', false);
             return;
         }
         if (!$this->post_exists('role_name') || !$this->post('role_name')) {
             $this->userMessage("No role display name set", 'notice', false);
             return;
         }
         //we are good to go.
         I2CE::getConfig()->I2CE->formsData->forms->role->{$role}->fields->name = $this->post('role_name');
         I2CE::getConfig()->I2CE->formsData->forms->role->{$role}->last_modified = I2CE_Date::now(I2CE_Date::DATE_TIME)->dbFormat();
     } else {
         if (count($this->request_remainder) == 1) {
             $role = $this->request_remainder[0];
             if (!$role || array_key_exists($role, self::$fixed_roles)) {
                 $this->userMessage("Invalid Role {$role} specified", 'notice', false);
                 return;
             }
             $roleBaseConfig = I2CE::getConfig()->traverse("/I2CE/formsData/forms/role/", false);
             if (!$roleBaseConfig instanceof I2CE_MagicDataNode) {
                 $this->userMessage("System Error", 'notice', false);
                 return;
             }
             $roleConfig = $roleBaseConfig->traverse("{$role}/fields", false);
             if (!$roleConfig instanceof I2CE_MagicDataNode) {
                 $this->userMessage("Invalid Role {$role} specified", 'notice', false);
                 return;
             }
             $post = $this->post();
             if (!array_key_exists('role_name', $post) || !$post['role_name']) {
                 $this->userMessage("No role display name set", 'notice', false);
                 return;
             }
             if ($roleConfig->is_translatable("name")) {
                 $locale = I2CE_Locales::getPreferredLocale();
                 $roleConfig->setTranslation($locale, $post['role_name'], "name");
                 if ($locale == I2CE_Locales::DEFAULT_LOCALE) {
                     $roleConfig->name = $post['role_name'];
                 }
             } else {
                 $roleConfig->name = $post['role_name'];
             }
             $roleBaseConfig->{$role}->last_modified = I2CE_Date::now(I2CE_Date::DATE_TIME)->dbFormat();
             if (array_key_exists('homepage', $post) && !is_array($post['homepage'])) {
                 $roleConfig->homepage = $post['homepage'];
             }
             if (array_key_exists('role_roles', $post) && is_array($post['role_roles'])) {
                 //make sure the roles are valid.
                 $roles = $post['role_roles'];
                 foreach ($roles as $i => $r) {
                     if (!$roleBaseConfig->is_parent("{$r}") || array_key_exists($r, self::$fixed_roles)) {
                         unset($roles[$i]);
                     }
                 }
                 $roles[] = 'admin';
                 //make sure that admin inherits this role.
                 $trickleConfig = $roleConfig->traverse("trickle_up", true, false);
                 $trickleConfig->erase();
                 $roleConfig->traverse('trickle_up', true, false);
                 //recreate what we just erased
                 $roleConfig->trickle_up = implode(',', $roles);
             }
             if (array_key_exists('role_tasks', $post) && is_array($post['role_tasks'])) {
                 $taskConfig = I2Ce::getConfig()->I2CE->tasks->role_trickle_down;
                 if (isset($taskConfig, $role)) {
                     $taskConfig->{$role}->erase();
                     $taskConfig->traverse($role, true, false);
                 }
                 $taskConfig->{$role} = $post['role_tasks'];
             }
         }
     }
     $this->setRedirect('tasks-roles/roles');
 }