[ Index ]
 

Code source de eGroupWare 1.2.106-2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/workflow/inc/engine/src/ProcessManager/ -> ProcessManager.php (source)

   1  <?php
   2  require_once(GALAXIA_LIBRARY.SEP.'src'.SEP.'ProcessManager'.SEP.'BaseManager.php');
   3  //!! ProcessManager
   4  //! A class to maniplate processes.
   5  /*!
   6    This class is used to add,remove,modify and list
   7    processes.
   8    Most of the methods acts directly in database level, bypassing Project object methods.
   9    TODO: fix multiple non checked fopen ==> infinite loops if problems with filesystem
  10  */
  11  class ProcessManager extends BaseManager {
  12    var $parser;
  13    var $tree;
  14    var $current;
  15    var $buffer;
  16    var $Process;
  17    var $activity_manager; 
  18    var $role_manager;
  19    
  20    /*!
  21      Constructor takes a PEAR::Db object to be used
  22      to manipulate roles in the database.
  23    */
  24    function ProcessManager(&$db) 
  25    {
  26      parent::BaseManager($db);
  27      $this->child_name = 'ProcessManager';
  28      require_once(GALAXIA_LIBRARY.SEP.'src'.SEP.'ProcessManager'.SEP.'ActivityManager.php');
  29      // $this->activity_manager is not set here to avoid objects loading object A loading object B loading object A, etc
  30      //$this->role_manager will only be loaded when needed as well
  31    }
  32  
  33    /*!
  34    * Collect errors from all linked objects which could have been used by this object
  35    * Each child class should instantiate this function with her linked objetcs, calling get_error(true)
  36    * for example if you had a $this->process_manager created in the constructor you shoudl call
  37    * $this->error[] = $this->process_manager->get_error(false, $debug);
  38    * @param $debug is false by default, if true debug messages can be added to 'normal' messages
  39    * @param $prefix is a string appended to the debug message
  40    */
  41    function collect_errors($debug=false, $prefix = '')
  42    {
  43      parent::collect_errors($debug, $prefix);
  44      if (isset($this->activity_manager)) $this->error[] = $this->activity_manager->get_error(false, $debug, $prefix);
  45      if (isset($this->role_manager)) $this->error[] = $this->role_manager->get_error(false, $debug, $prefix);
  46    }
  47  
  48    /*!
  49      Sets a process as active
  50    */
  51    function activate_process($pId)
  52    {
  53      $query = 'update '.GALAXIA_TABLE_PREFIX.'processes set wf_is_active=? where wf_p_id=?';
  54      $this->query($query, array('y',$pId));  
  55      $msg = sprintf(tra('Process %d has been activated'),$pId);
  56      $this->notify_all(3,$msg);
  57      $this->error[] = $msg;
  58    }
  59    
  60    /*!
  61      De-activates a process
  62    */
  63    function deactivate_process($pId)
  64    {
  65      $query = 'update '.GALAXIA_TABLE_PREFIX.'processes set wf_is_active=? where wf_p_id=?';
  66      $this->query($query, array('n',$pId));  
  67      $msg = sprintf(tra('Process %d has been deactivated'),$pId);
  68      $this->notify_all(3,$msg);
  69      $this->error[] = $msg;
  70    }
  71    
  72    /*!
  73      Creates an XML representation of a process.
  74    */
  75    function serialize_process($pId)
  76    {
  77      if (!(isset($this->activity_manager)))  $this->activity_manager =& new ActivityManager($this->db);
  78      // <process>
  79      $out = '<process>'."\n";
  80      //we retrieve config values with the others process data
  81      $proc_info =& $this->get_process($pId, true);
  82      $wf_procname = $proc_info['wf_normalized_name'];
  83      $out.= '  <name>'.htmlspecialchars($proc_info['wf_name']).'</name>'."\n";
  84      $out.= '  <isValid>'.htmlspecialchars($proc_info['wf_is_valid']).'</isValid>'."\n";
  85      $out.= '  <version>'.htmlspecialchars($proc_info['wf_version']).'</version>'."\n";
  86      $out.= '  <isActive>'.htmlspecialchars($proc_info['wf_is_active']).'</isActive>'."\n";
  87      $out.='   <description>'.htmlspecialchars($proc_info['wf_description']).'</description>'."\n";
  88      $out.= '  <lastModif>'.date("d/m/Y [h:i:s]",$proc_info['wf_last_modif']).'</lastModif>'."\n";
  89  
  90      //Shared code
  91      $out.= '  <sharedCode><![CDATA[';
  92      $fp=fopen(GALAXIA_PROCESSES.SEP."$wf_procname".SEP."code".SEP."shared.php","r");
  93      while(!feof($fp)) {
  94        $line=fread($fp,8192);
  95        $out.=$line;
  96      }
  97      fclose($fp);
  98      $out.= '  ]]></sharedCode>'."\n";
  99  
 100      //Loop on config values
 101      $out.='  <configs>'."\n";
 102      foreach($proc_info['config'] as $res) {      
 103        $name = $res['wf_config_name'];
 104        $value_int = $res['wf_config_value_int'];
 105        $value = $res['wf_config_value'];
 106        $out.='    <config>'."\n";
 107        $out.='      <wf_config_name>'.htmlspecialchars($name).'</wf_config_name>'."\n";
 108        $out.='      <wf_config_value>'.htmlspecialchars($value).'</wf_config_value>'."\n";
 109        $out.='      <wf_config_value_int>'.htmlspecialchars($value_int).'</wf_config_value_int>'."\n";
 110        $out.='    </config>'."\n";
 111      }
 112      $out.='  </configs>'."\n";
 113  
 114      // Now loop over activities
 115      $query = "select * from ".GALAXIA_TABLE_PREFIX."activities where wf_p_id=$pId";
 116      $result = $this->query($query);
 117      $out.='  <activities>'."\n";
 118      while($res = $result->fetchRow()) {      
 119        $name = $res['wf_normalized_name'];
 120        $out.='    <activity>'."\n";
 121        $out.='      <name>'.htmlspecialchars($res['wf_name']).'</name>'."\n";
 122        $out.='      <type>'.htmlspecialchars($res['wf_type']).'</type>'."\n";
 123        $out.='      <description>'.htmlspecialchars($res['wf_description']).'</description>'."\n";
 124        $out.='      <lastModif>'.date("d/m/Y [h:i:s]",$res['wf_last_modif']).'</lastModif>'."\n";
 125        $out.='      <isInteractive>'.$res['wf_is_interactive'].'</isInteractive>'."\n";
 126        $out.='      <isAutoRouted>'.$res['wf_is_autorouted'].'</isAutoRouted>'."\n";
 127        $out.='      <roles>'."\n";
 128        //loop on activity roles
 129        $actid = $res['wf_activity_id'];
 130        $roles =& $this->activity_manager->get_activity_roles($actid);
 131        foreach($roles as $role) {
 132          if ($role['wf_readonly'])
 133          {
 134            $out.='        <role readonly="true">'.htmlspecialchars($role['wf_name']).'</role>'."\n";
 135          }
 136          else
 137          {
 138            $out.='        <role>'.htmlspecialchars($role['wf_name']).'</role>'."\n";
 139          }
 140        }  
 141        $out.='      </roles>'."\n";
 142        $out.='      <agents>'."\n";
 143        //loop on activity agents
 144        $agents =& $this->activity_manager->get_activity_agents($actid);
 145        foreach($agents as $agent) {
 146          $out.='        <agent>'."\n";
 147          $out.='           <agent_type>'.htmlspecialchars($agent['wf_agent_type']).'</agent_type>'."\n";
 148          //loop on agent datas
 149          $agent_data =& $this->activity_manager->get_activity_agent_data($actid,$agent['wf_agent_type']);
 150          $out.='           <agent_datas>'."\n";
 151          foreach($agent_data as $key => $value)
 152          {
 153            if (!($key=='wf_agent_id'))
 154            {
 155              $out.='               <agent_data>'."\n";
 156              $out.='                   <name>'.htmlspecialchars($key).'</name>'."\n";
 157              $out.='                   <value>'.htmlspecialchars($value).'</value>'."\n";
 158              $out.='               </agent_data>'."\n";
 159            }
 160          }
 161          $out.='           </agent_datas>'."\n";
 162          $out.='        </agent>'."\n";
 163        }  
 164        $out.='      </agents>'."\n";
 165  
 166        //the code
 167        $out.='      <code><![CDATA[';
 168        $fp=fopen(GALAXIA_PROCESSES.SEP."$wf_procname".SEP."code".SEP."activities".SEP."$name.php","r");
 169        while(!feof($fp)) {
 170          $line=fread($fp,8192);
 171          $out.=$line;
 172        }
 173        fclose($fp);
 174        $out.='      ]]></code>';
 175        if($res['wf_is_interactive']=='y') {
 176          $out.='      <template><![CDATA[';
 177          $fp=fopen(GALAXIA_PROCESSES.SEP."$wf_procname".SEP."code".SEP."templates".SEP."$name.tpl","r");
 178          while(!feof($fp)) {
 179            $line=fread($fp,8192);
 180            $out.=$line;
 181          }
 182          fclose($fp);
 183          $out.='      ]]></template>';
 184        }
 185        $out.='    </activity>'."\n";    
 186      }
 187      $out.='  </activities>'."\n";
 188      $out.='  <transitions>'."\n";
 189      //loop on transitions
 190      $transitions = $this->activity_manager->get_process_transitions($pId);
 191      foreach($transitions as $tran) {
 192        $out.='     <transition>'."\n";
 193        $out.='       <from>'.htmlspecialchars($tran['wf_act_from_name']).'</from>'."\n";
 194        $out.='       <to>'.htmlspecialchars($tran['wf_act_to_name']).'</to>'."\n";
 195        $out.='     </transition>'."\n";
 196      }     
 197      $out.='  </transitions>'."\n";
 198      $out.= '</process>'."\n";
 199      //$fp = fopen(GALAXIA_PROCESSES."/$wf_procname/$wf_procname.xml","w");
 200      //fwrite($fp,$out);
 201      //fclose($fp);
 202      return $out;
 203    }
 204    
 205    /*!
 206      Creates  a process PHP data structure from its XML 
 207      representation
 208    */
 209    function unserialize_process(&$xml) 
 210    {
 211      // Create SAX parser assign this object as base for handlers
 212      // handlers are private methods defined below.
 213      // keep contexts and parse
 214      $this->parser = xml_parser_create(); 
 215      xml_parser_set_option($this->parser,XML_OPTION_CASE_FOLDING,0);
 216      //xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE, 1);
 217      xml_set_object($this->parser, $this);
 218      xml_set_element_handler($this->parser, '_start_element_handler', '_end_element_handler');
 219      xml_set_character_data_handler($this->parser, '_data_handler'); 
 220      $aux=Array(
 221        'name'=>'root',
 222        'children'=>Array(),
 223        'parent' => 0,
 224        'data'=>'', 
 225        'attribs'    => Array(),
 226      );
 227      $this->tree[0]=$aux;
 228      $this->current=0;
 229      
 230      
 231      if (!xml_parse($this->parser, $xml, true)) {
 232         $error = sprintf("XML error: %s at line %d",
 233                      xml_error_string(xml_get_error_code($this->parser)),
 234                      xml_get_current_line_number($this->parser));
 235         trigger_error($error,E_USER_WARNING);
 236         $this->error[] = $error;
 237      }
 238      xml_parser_free($this->parser);   
 239      // Now that we have the tree we can do interesting things
 240      
 241      $process=Array();
 242      $activities=Array();
 243      $transitions=Array();
 244      for($i=0;$i<count($this->tree[1]['children']);$i++) {
 245        // Process attributes
 246        $z=$this->tree[1]['children'][$i];
 247        $name = trim($this->tree[$z]['name']);
 248        
 249        //config values
 250        if ($name=='configs') {
 251          for($j=0;$j<count($this->tree[$z]['children']);$j++) {
 252            $z2 = $this->tree[$z]['children'][$j];
 253            // this is a config $name = $this->tree[$z2]['name'];
 254            $aux = Array();
 255            if($this->tree[$z2]['name']=='config') {
 256              for($k=0;$k<count($this->tree[$z2]['children']);$k++) {
 257                $z3 = $this->tree[$z2]['children'][$k];
 258                $name = trim($this->tree[$z3]['name']);
 259                $value= trim($this->tree[$z3]['data']);
 260                $aux[$name]=$value;
 261              }
 262              $configs[]=$aux;
 263            }
 264          }      
 265        }
 266        //activities
 267        elseif($name=='activities') {
 268          for($j=0;$j<count($this->tree[$z]['children']);$j++) {
 269            $z2 = $this->tree[$z]['children'][$j];
 270            // this is an activity $name = $this->tree[$z2]['name'];
 271            $aux = Array();
 272            if($this->tree[$z2]['name']=='activity') {
 273              for($k=0;$k<count($this->tree[$z2]['children']);$k++) {
 274                $z3 = $this->tree[$z2]['children'][$k];
 275                $name = trim($this->tree[$z3]['name']);
 276                $value= trim($this->tree[$z3]['data']);
 277                if($name=='roles') {
 278                  $roles=Array();
 279                  for($l=0;$l<count($this->tree[$z3]['children']);$l++) {
 280                    $z4 = $this->tree[$z3]['children'][$l];
 281                    $name = trim($this->tree[$z4]['name']);
 282                    $data = trim($this->tree[$z4]['data']);
 283                    $attribs = $this->tree[$z4]['attribs'];
 284                    $readonly = false;
 285                    if ( (isset($attribs['readonly'])) && ($attribs['readonly']))
 286                    {
 287                      //role in read-only
 288                      $readonly = true;
 289                    }
 290                    $roles[]=array(
 291                      'name'     => $data,
 292                      'readonly'    => $readonly,
 293                    );
 294                  }
 295                } 
 296                elseif ($name=='agents') 
 297                {
 298                  $agents=Array();
 299                  for($l=0;$l<count($this->tree[$z3]['children']);$l++) 
 300                  {
 301                    $z4 = $this->tree[$z3]['children'][$l];
 302                    //$name is agent
 303                    $name = trim($this->tree[$z4]['name']);
 304                    if ($name = 'agent')
 305                    {
 306                      $agent = array();
 307                      for($m=0;$m<count($this->tree[$z4]['children']);$m++)
 308                      {
 309                        $z5 = $this->tree[$z4]['children'][$m];
 310                        //$name is agent_type or agent_datas
 311                        $name = trim($this->tree[$z5]['name']);
 312                        // data will be the agent_type or an array for agent_datas
 313                        $data = trim($this->tree[$z5]['data']);
 314                        if ($name=='agent_type') 
 315                        {
 316                          $agent['wf_agent_type']=$data;
 317                        } 
 318                        elseif ($name=='agent_datas') 
 319                        {
 320                          for($n=0;$n<count($this->tree[$z5]['children']);$n++)
 321                          {
 322                            $z6 = $this->tree[$z5]['children'][$n];
 323                            //$name is agent_data $val is an array
 324                            $name = trim($this->tree[$z6]['name']);
 325                            $val = trim($this->tree[$z6]['data']);
 326                            if ($name=='agent_data')
 327                            {
 328                              for($o=0;$o<count($this->tree[$z6]['children']);$o++)
 329                              {
 330                                $z7 = $this->tree[$z6]['children'][$o];
 331                                //$name is agent_data $val is 'name' or 'value'
 332                                $name = trim($this->tree[$z7]['name']);
 333                                $content = trim($this->tree[$z7]['data']);
 334                                //echo "<br>z7 name $name content: $content";
 335                                if ($name=='name')
 336                                {
 337                                  $agent_data_name = $content;
 338                                }
 339                                elseif ($name=='value')
 340                                {
 341                                  $agent_data_value =& $content;
 342                                }
 343                              }
 344                              //echo "<br>associate $agent_data_name to $agent_data_value <hr>";
 345                              $agent[$agent_data_name] = $agent_data_value;
 346                            }
 347                          }
 348                        }
 349                      }
 350                      $agents[]=$agent;
 351                    }
 352                  }
 353                } else {
 354                  $aux[$name]=$value;
 355                  //print("$name:$value<br/>");
 356                }
 357              }
 358              $aux['agents']=$agents;
 359              $aux['roles']=$roles;
 360              $activities[]=$aux;
 361            }
 362          }
 363        } elseif($name=='transitions') {
 364          for($j=0;$j<count($this->tree[$z]['children']);$j++) {
 365            $z2 = $this->tree[$z]['children'][$j];
 366            // this is an activity $name = $this->tree[$z2]['name'];
 367            $aux=Array();
 368            if($this->tree[$z2]['name']=='transition') {
 369              for($k=0;$k<count($this->tree[$z2]['children']);$k++) {
 370                $z3 = $this->tree[$z2]['children'][$k];
 371                $name = trim($this->tree[$z3]['name']);
 372                $value= trim($this->tree[$z3]['data']);
 373                if($name == 'from' || $name == 'to') {
 374                  $aux[$name]=$value;
 375                }
 376              }
 377            }
 378            $transitions[] = $aux;
 379          }
 380        } else {
 381          $value = trim($this->tree[$z]['data']);
 382          //print("$name is $value<br/>");
 383          $process[$name]=$value;
 384        }
 385      }
 386      $process['configs']=$configs;
 387      $process['activities']=$activities;
 388      $process['transitions']=$transitions;
 389      return $process;
 390    }
 391  
 392    /*!
 393     Creates a process from the process data structure, if you want to 
 394     convert an XML to a process then use first unserialize_process
 395     and then this method.
 396     return true if everything seems ok
 397    */
 398    function import_process(&$data)
 399    {
 400      //Now the show begins
 401      if (!(isset($this->activity_manager)))  $this->activity_manager =& new ActivityManager($this->db);
 402      if (!(isset($this->role_manager))) $this->role_manager = new RoleManager($this->db);
 403      // First create the process. Always inactive and inactive first, compilation will set theses informations later.
 404      $vars = Array(
 405        'wf_name' => $data['name'],
 406        'wf_version' => $data['version'],
 407        'wf_description' => $data['description'],
 408        'wf_last_modif' => $data['lastModif'],
 409        'wf_is_active' => false,
 410        'wf_is_valid' => false,
 411        'config' => $data['configs'],
 412      );
 413  
 414      if ($this->process_name_exists($vars['wf_name'], $vars['wf_version']))
 415      {
 416        $msg = sprintf(tra('Process %s %s already exists, the import process was aborted'),$vars['wf_name'],$vars['wf_version']);
 417        $this->notify_all(2,$msg);
 418        $this->error[] = $msg;
 419        return false;
 420      }
 421      $pid = $this->replace_process(0,$vars,false);
 422      //Put the shared code 
 423      $proc_info = $this->get_process($pid);
 424      $wf_procname = $proc_info['wf_normalized_name'];
 425      $fp = fopen(GALAXIA_PROCESSES.SEP.$wf_procname.SEP.'code'.SEP.'shared.php',"w");
 426      fwrite($fp, $data['sharedCode']);
 427      fclose($fp);
 428      $actids = Array();
 429      
 430      // Foreach activity create activities
 431      foreach($data['activities'] as $activity) {
 432          
 433        $vars = Array(
 434          'wf_name' => $activity['name'],
 435          'wf_description' => $activity['description'],
 436          'wf_type' => $activity['type'],
 437          'wf_last_modif' => $activity['lastModif'],
 438          'wf_is_interactive' => $activity['isInteractive'],
 439          'wf_is_autorouted' => $activity['isAutoRouted']
 440        );    
 441        $actname=$this->activity_manager->_normalize_name($activity['name']);
 442        //this is calling the activity compilation
 443        $actid = $this->activity_manager->replace_activity($pid,0,$vars);
 444        
 445        $fp = fopen(GALAXIA_PROCESSES.SEP.$wf_procname.SEP.'code'.SEP.'activities'.SEP.$actname.'.php',"w");
 446        fwrite($fp, $activity['code']);
 447        fclose($fp);
 448        if($activity['isInteractive']=='y') {
 449          $fp = fopen(GALAXIA_PROCESSES.SEP.$wf_procname.SEP.'code'.SEP.'templates'.SEP.$actname.'.tpl',"w");
 450          fwrite($fp,$activity['template']);
 451          fclose($fp);
 452        }
 453        $actids[$activity['name']] = $this->activity_manager->_get_activity_id_by_name($pid, $activity['name']);
 454        $actname = $this->activity_manager->_normalize_name($activity['name']);
 455        $now = date("U");
 456        //roles
 457        if( is_array($activity['roles']) && count($activity['roles']) > 0 )
 458        {
 459            foreach($activity['roles'] as $role) 
 460            {
 461              $rolename = $role['name'];
 462              $vars = Array(
 463                'wf_name' => $rolename,
 464                'wf_description' => $rolename,
 465                'wf_last_modif' => $now,
 466              );
 467              if(!$this->role_manager->role_name_exists($pid,$rolename)) {
 468                $rid=$this->role_manager->replace_role($pid,0,$vars);
 469              } else {
 470                $rid = $this->role_manager->get_role_id($pid,$rolename);
 471              }
 472              if($actid && $rid) {
 473                $this->activity_manager->add_activity_role($actid,$rid,$role['readonly']);
 474              }
 475            }
 476        }
 477        //agents
 478        if( is_array($activity['agents']) && count($activity['agents']) > 0 )
 479        {
 480          foreach($activity['agents'] as $agent)
 481          {
 482              if (empty($agent['wf_agent_type']))
 483              {
 484                $this->error[] = lang('empty agent type');
 485              }
 486              else
 487              {
 488                //create a new agent of the same type for the new activity
 489                $agentid = $this->activity_manager->add_activity_agent($actid,$agent['wf_agent_type']);
 490                //save values of this new agent
 491                $bindvars = Array();
 492                $query = 'update '.GALAXIA_TABLE_PREFIX.'agent_'.$agent['wf_agent_type'].'
 493                          set ';
 494                //we wont need the old type anymore
 495                unset($agent['wf_agent_type']);
 496                $countfields = 0;
 497                foreach ($agent as $key => $value)
 498                {
 499                  if ($key)
 500                  {
 501                    $countfields++;
 502                    $query .= "$key = ? ,";
 503                    $bindvars[] = $value;
 504                  }
 505                }
 506                $query = substr($query,'0',-1);
 507                $query .= ' where wf_agent_id = ?';
 508                $bindvars[] = $agentid;
 509                if ($countfields) $this->query($query, $bindvars);
 510              }
 511          }
 512        }
 513      }
 514      //transitions
 515      foreach($data['transitions'] as $tran) 
 516      {
 517        $this->activity_manager->add_transition($pid,$actids[$tran['from']],$actids[$tran['to']]);  
 518      }
 519  
 520      // create a graph for the new process
 521      $this->activity_manager->build_process_graph($pid);
 522      //Test the final process
 523      $this->activity_manager->validate_process_activities($pid);
 524  
 525      $msg = sprintf(tra('Process %s %s imported'),$proc_info['wf_name'],$proc_info['wf_version']);
 526      $this->notify_all(2,$msg);
 527      $this->error[] = $msg;
 528      return true;
 529    }
 530  
 531    /*!
 532     Creates a new process based on an existing process
 533     changing the process version. By default the process
 534     is created as an unactive process and the version is
 535     by default a minor version of the process.
 536     */
 537    function new_process_version($pId, $minor=true)
 538    {
 539      if (!(isset($this->activity_manager)))  $this->activity_manager =& new ActivityManager($this->db);
 540      $oldpid = $pId;
 541      //retrieve process info with config rows
 542      $proc_info = $this->get_process($pId, true);
 543      if(!($proc_info) || (count($proc_info)==0)) return false;
 544      $name = $proc_info['wf_name'];
 545  
 546      // Now update the version
 547      $version = $this->_new_version($proc_info['wf_version'],$minor);
 548      while($this->getOne('select count(*) from '.GALAXIA_TABLE_PREFIX.'processes where wf_name=? and wf_version=?',array($name,$version))) 
 549      {
 550        $version = $this->_new_version($version,$minor);
 551      }
 552      $oldname = $proc_info['wf_normalized_name'];
 553  
 554      // Make new versions unactive
 555      $proc_info['wf_version'] = $version;
 556      $proc_info['wf_is_active'] = 'n';
 557      // create a new process, but don't create start/end activities
 558      $pid = $this->replace_process(0, $proc_info, false);
 559      if (!pid) return false;
 560  
 561      //Since we are copying a process we should copy
 562      //the old directory structure to the new directory
 563      //oldname was saved a few lines before
 564      $newname = $this->_get_normalized_name($pid);
 565      $this->_rec_copy(GALAXIA_PROCESSES.SEP.$oldname.SEP.'code',GALAXIA_PROCESSES.SEP.$newname.SEP.'code');
 566      // And here copy all the activities & so
 567      $query = 'select * from '.GALAXIA_TABLE_PREFIX.'activities where wf_p_id=?';
 568      $result = $this->query($query, array($oldpid));
 569      $newaid = array();
 570      while($res = $result->fetchRow()) {    
 571        $oldaid = $res['wf_activity_id'];
 572        // the false tell the am not to create activities source files
 573        $newaid[$oldaid] = $this->activity_manager->replace_activity($pid,0,$res, false);
 574      }
 575      // create transitions
 576      $query = 'select * from '.GALAXIA_TABLE_PREFIX.'transitions where wf_p_id=?';
 577      $result = $this->query($query, array($oldpid));
 578  
 579      while($res = $result->fetchRow()) { 
 580        if (empty($newaid[$res['wf_act_from_id']]) || empty($newaid[$res['wf_act_to_id']])) {
 581          continue;
 582        }
 583        $this->activity_manager->add_transition($pid,$newaid[$res['wf_act_from_id']],$newaid[$res['wf_act_to_id']]);
 584      }
 585      // create roles
 586      if (!(isset($this->role_manager))) $this->role_manager = new RoleManager($this->db);
 587      $query = 'select * from '.GALAXIA_TABLE_PREFIX.'roles where wf_p_id=?';
 588      $result = $this->query($query, array($oldpid));
 589      $newrid = array();
 590      while($res = $result->fetchRow()) {
 591        if(!$this->role_manager->role_name_exists($pid,$res['wf_name'])) {
 592          $rid=$this->role_manager->replace_role($pid,0,$res);
 593        } else {
 594          $rid = $this->role_manager->get_role_id($pid,$res['wf_name']);
 595        }
 596        $newrid[$res['wf_role_id']] = $rid;
 597      }
 598      // map users to roles
 599      if (count($newrid) > 0) {
 600        $query = 'select * from '.GALAXIA_TABLE_PREFIX.'user_roles where wf_p_id=?';
 601        $result = $this->query($query, array($oldpid));
 602        while($res = $result->fetchRow()) {
 603          if (empty($newrid[$res['wf_role_id']])) {
 604            continue;
 605          }
 606          $this->role_manager->map_user_to_role($pid,$res['wf_user'],$newrid[$res['wf_role_id']], $res['wf_account_type']);
 607        }
 608      }
 609      // add roles to activities
 610      if (count($newaid) > 0 && count($newrid ) > 0) {
 611        $query = 'select * from '.GALAXIA_TABLE_PREFIX.'activity_roles where wf_activity_id in (' . join(', ',array_keys($newaid)) . ')';
 612        $result = $this->query($query);
 613        while($res = $result->fetchRow()) {
 614          if (empty($newaid[$res['wf_activity_id']]) || empty($newrid[$res['wf_role_id']])) {
 615            continue;
 616          }
 617          $this->activity_manager->add_activity_role($newaid[$res['wf_activity_id']],$newrid[$res['wf_role_id']], $res['wf_readonly']);
 618        }
 619      }
 620  
 621      //create agents
 622      //get the list of agents used by the old process
 623      $query = 'select gaa.* from '.GALAXIA_TABLE_PREFIX.'activity_agents gaa
 624                  INNER JOIN '.GALAXIA_TABLE_PREFIX.'activities gac ON gaa.wf_activity_id = gac.wf_activity_id
 625                  where gac.wf_p_id=?';
 626      $result = $this->query($query, array($oldpid));
 627      if (!(empty($result)))
 628      {
 629        while ($res = $result->fetchRow()) 
 630        {
 631            //create a new agent of the same type for the new activity
 632            $agentid = $this->activity_manager->add_activity_agent($newaid[$res['wf_activity_id']],$res['wf_agent_type']);
 633            //save values of this new agents, taking the old ones, we make a simple copy
 634            $old_activity_agent_data =& $this->activity_manager->get_activity_agent_data($res['wf_activity_id'],$res['wf_agent_type']);
 635            //we wont need the old id and type
 636            unset($old_activity_agent_data['wf_agent_id']);
 637            unset($old_activity_agent_data['wf_agent_type']);
 638            $bindvars = Array();
 639            $query = 'update '.GALAXIA_TABLE_PREFIX.'agent_'.$res['wf_agent_type'].'
 640                        set ';
 641            $countfields = 0;
 642            foreach ($old_activity_agent_data as $key => $value)
 643            {
 644              if ($key)
 645              {
 646                $countfields++;
 647                $query .= "$key = ? ,";
 648                $bindvars[] = $value;
 649              }
 650            }
 651            $query = substr($query,'0',-1);
 652            $query .= ' where wf_agent_id = ?';
 653            $bindvars[] = $agentid;
 654            if ($countfields) $this->query($query, $bindvars);
 655        }
 656      }
 657  
 658      // create a graph for the new process
 659      $this->activity_manager->build_process_graph($pid);
 660      
 661      return $pid;
 662    }
 663    
 664    /*!
 665     This function can be used to check if a process name exists, note that
 666     this is NOT used by replace_process since that function can be used to
 667     create new versions of an existing process. The application must use this
 668     method to ensure that processes have unique names.
 669    */
 670    function process_name_exists($name,$version)
 671    {
 672      $name = addslashes($this->_normalize_name($name,$version));
 673      return $this->getOne('select count(*) from '.GALAXIA_TABLE_PREFIX.'processes where wf_normalized_name=?',array($name));
 674    }
 675    
 676    
 677    /*!
 678      Gets a process by pId. Fields are returned as an associative array. 
 679      If withConfig is set (false by default), the configuration options are returned as well
 680      the ['config'] key is then an array containing the config data with type distinction
 681    */
 682    function get_process($pId, $withConfig=false)
 683    {
 684      $query = 'select * from '.GALAXIA_TABLE_PREFIX.'processes where wf_p_id=?';
 685      $result = $this->query($query, array($pId));
 686      if((empty($result)) || (!$result->numRows())) return false;
 687      $res = $result->fetchRow();
 688      if ($withConfig)
 689      {
 690        // by setting true we force this function to keep type distinction on config values
 691        $res['config'] = $this->getConfigValues($res['wf_p_id'], true);
 692      }
 693      return $res;
 694    }
 695    
 696    /*!
 697     Lists processes (all processes)
 698    */
 699    function list_processes($offset,$maxRecords,$sort_mode,$find,$where='')
 700    {
 701      $sort_mode = $this->convert_sortmode($sort_mode);
 702      if($find) {
 703        $findesc = '%'.$find.'%';
 704        $mid=' where ((wf_name like ?) or (wf_description like ?))';
 705        $bindvars = array($findesc,$findesc);
 706      } else {
 707        $mid='';
 708        $bindvars = array();
 709      }
 710      if($where) {
 711        if($mid) {
 712          $mid.= " and ($where) ";
 713        } else {
 714          $mid.= " where ($where) ";
 715        }
 716      }
 717      $query = 'select * from '.GALAXIA_TABLE_PREFIX."processes $mid";
 718      $query_cant = 'select count(*) from '.GALAXIA_TABLE_PREFIX."processes $mid";
 719      $result = $this->query($query,$bindvars,$maxRecords,$offset, true, $sort_mode);
 720      $cant = $this->getOne($query_cant,$bindvars);
 721      $ret = Array();
 722      if (isset($result))
 723      {
 724        while($res = $result->fetchRow()) 
 725        {
 726          $ret[] = $res;
 727        }
 728      }
 729      $retval = Array();
 730      $retval['data'] = $ret;
 731      $retval['cant'] = $cant;
 732      return $retval;
 733    }
 734    
 735    /*!
 736     Marks a process as an invalid process
 737    */
 738    function invalidate_process($pid)
 739    {
 740      $query = 'update '.GALAXIA_TABLE_PREFIX.'processes set wf_is_valid=? where wf_p_id=?';
 741      $this->query($query, array('n',$pid));
 742    }
 743    
 744    /*! 
 745      Removes a process by pId
 746    */
 747    function remove_process($pId)
 748    {
 749      if (!(isset($this->activity_manager)))  $this->activity_manager =& new ActivityManager($this->db);
 750      $this->deactivate_process($pId);
 751      $name = $this->_get_normalized_name($pId);
 752      
 753      // start a transaction
 754      $this->db->StartTrans();
 755      
 756      // Remove process activities
 757      $query = 'select wf_activity_id from '.GALAXIA_TABLE_PREFIX.'activities where wf_p_id=?';
 758      $result = $this->query($query, array($pId));
 759      while($res = $result->fetchRow()) {
 760        //we add a false parameter to prevent the ActivityManager from opening a new transaction
 761        $this->activity_manager->remove_activity($pId,$res['wf_activity_id'], false);
 762      }
 763  
 764      // Remove process roles
 765      $query = 'delete from '.GALAXIA_TABLE_PREFIX.'roles where wf_p_id=?';
 766      $this->query($query, array($pId));
 767      $query = 'delete from '.GALAXIA_TABLE_PREFIX.'user_roles where wf_p_id=?';
 768      $this->query($query, array($pId));
 769  
 770      // Remove process instances
 771      $query = 'delete from '.GALAXIA_TABLE_PREFIX.'instances where wf_p_id=?';
 772      $this->query($query, array($pId));
 773      
 774      // Remove the directory structure
 775      if (!empty($name) && is_dir(GALAXIA_PROCESSES.SEP.$name)) {
 776        $this->_remove_directory(GALAXIA_PROCESSES.SEP.$name,true);
 777      }
 778      if (GALAXIA_TEMPLATES && !empty($name) && is_dir(GALAXIA_TEMPLATES.SEP.$name)) {
 779        $this->_remove_directory(GALAXIA_TEMPLATES.SEP.$name,true);
 780      }
 781      
 782      // Remove configuration data
 783      $query = 'delete from '.GALAXIA_TABLE_PREFIX.'process_config where wf_p_id=?';
 784      $this->query($query, array($pId));
 785      
 786      // And finally remove the proc
 787      $query = 'delete from '.GALAXIA_TABLE_PREFIX.'processes where wf_p_id=?';
 788      $this->query($query, array($pId));
 789      $msg = sprintf(tra('Process %s removed'),$name);
 790      $this->notify_all(5,$msg);
 791      $this->error[] = $msg;
 792      
 793      // perform commit (return true) or Rollback (return false)
 794      return $this->db->CompleteTrans();
 795      
 796    }
 797    
 798    /*!
 799      Updates or inserts a new process in the database, $vars is an associative
 800      array containing the fields to update or to insert as needed.
 801      Configuration options should be in an array associated with the 'config' key
 802      this config array should contain 'wf_config_name', 'wf_config_value' and 'wf_config_value_int' keys.
 803      $pId is the processI. If $pId is 0 then we create a new process, else we are in edit mode.
 804      if $create is true start and end activities will be created (when importing use $create=false).
 805    */
 806    function replace_process($pId, &$vars, $create = true)
 807    {
 808      if (!(isset($this->activity_manager)))  $this->activity_manager =& new ActivityManager($this->db);
 809      $TABLE_NAME = GALAXIA_TABLE_PREFIX.'processes';
 810      $now = date("U");
 811      $vars['wf_last_modif']=$now;
 812      $vars['wf_normalized_name'] = $this->_normalize_name($vars['wf_name'],$vars['wf_version']);
 813      $config_array = array();
 814      
 815      foreach($vars as $key=>$value)
 816      {
 817        if ($key=='config')
 818        {
 819          $config_array_init =& $value; 
 820          // rebuild a nice config_array with type of config and value
 821          if( is_array($config_array_init) && count($config_array_init) > 0 )
 822      {
 823              foreach($config_array_init as $config)
 824              {
 825                if (isset($config['wf_config_value_int']) && (!($config['wf_config_value_int']=='')))
 826                {
 827                  $config_array[$config['wf_config_name']] = array('int' => $config['wf_config_value_int']);
 828                }
 829                else
 830                {
 831                  if (isset($config['wf_config_value'])) 
 832                  {
 833                    $config_array[$config['wf_config_name']] = array('text' => $config['wf_config_value']);
 834                  }
 835                }
 836              }
 837          }
 838      //no need to keep it in the vars array, this array is used in queries
 839      unset($vars['config']);
 840        }
 841        else // not config, it's just process's fields values
 842        {
 843          $vars[$key]=addslashes($value);
 844        }
 845      }
 846    
 847      if($pId) {
 848        // update mode
 849        $old_proc = $this->get_process($pId);
 850        $first = true;
 851        $query ="update $TABLE_NAME set";
 852        foreach($vars as $key=>$value) {
 853          if(!$first) $query.= ',';
 854          if(!is_numeric($value)||strstr($value,'.')) $value="'".$value."'";
 855          $query.= " $key=$value ";
 856          $first = false;
 857        }
 858        $query .= " where wf_p_id=$pId ";
 859        $this->query($query);
 860        
 861        //set config values
 862        $this->setConfigValues($pId,$config_array);
 863        
 864        // Note that if the name is being changed then
 865        // the directory has to be renamed!
 866        $oldname = $old_proc['wf_normalized_name'];
 867        $newname = $vars['wf_normalized_name'];
 868        if ($newname != $oldname) {
 869            rename(GALAXIA_PROCESSES.SEP."$oldname",GALAXIA_PROCESSES.SEP."$newname");
 870        }
 871        $msg = sprintf(tra('Process %s has been updated'),$vars['wf_name']);     
 872        $this->notify_all(3,$msg);
 873        $this->error[] = $msg;
 874      } else {
 875        unset($vars['wf_p_id']);
 876        // insert mode
 877        $name = $this->_normalize_name($vars['wf_name'],$vars['wf_version']);
 878        $this->_create_directory_structure($name);
 879        $first = true;
 880        $query = "insert into $TABLE_NAME(";
 881        foreach(array_keys($vars) as $key) {
 882          if(!$first) $query.= ','; 
 883          $query.= "$key";
 884          $first = false;
 885        } 
 886        $query .=") values(";
 887        $first = true;
 888        foreach(array_values($vars) as $value) {
 889          if(!$first) $query.= ','; 
 890          if(!is_numeric($value)||strstr($value,'.')) $value="'".$value."'";
 891          $query.= "$value";
 892          $first = false;
 893        } 
 894        $query .=")";
 895        $this->query($query);
 896        //FIXME: this query seems to be quite sure to get a result, I would prefer something
 897        // more sure to get the right result everytime
 898        $pId = $this->getOne("select max(wf_p_id) from $TABLE_NAME where wf_last_modif=$now"); 
 899        
 900        //set config values
 901        $this->setConfigValues($pId,$config_array);
 902        
 903        // Now automatically add a start and end activity 
 904        // unless importing ($create = false)
 905        if($create) {
 906          $vars1 = Array(
 907            'wf_name' => 'start',
 908            'wf_description' => 'default start activity',
 909            'wf_type' => 'start',
 910            'wf_is_interactive' => 'y',
 911            'wf_is_autorouted' => 'y'
 912          );
 913          $vars2 = Array(
 914            'wf_name' => 'end',
 915            'wf_description' => 'default end activity',
 916            'wf_type' => 'end',
 917            'wf_is_interactive' => 'n',
 918            'wf_is_autorouted' => 'y'
 919          );
 920    
 921          $this->activity_manager->replace_activity($pId,0,$vars1);
 922          $this->activity_manager->replace_activity($pId,0,$vars2);
 923        }
 924      $msg = sprintf(tra('Process %s has been created'),$vars['wf_name']);     
 925      $this->notify_all(4,$msg);
 926      $this->error[] = $msg;
 927      }
 928      // Get the id
 929      return $pId;
 930    }
 931     
 932    /*!
 933     \private
 934     Gets the normalized name of a process by pid
 935    */
 936    function _get_normalized_name($pId)
 937    {
 938      $info = $this->get_process($pId);
 939      return $info['wf_normalized_name'];
 940    }
 941     
 942    /*!
 943     \private
 944     Normalizes a process name
 945    */
 946    function _normalize_name($name, $version)
 947    {
 948      $name = $name.'_'.$version;
 949      $name = str_replace(" ","_",$name);
 950      $name = preg_replace("/[^0-9A-Za-z\_]/",'',$name);
 951      return $name;
 952    }
 953     
 954    /*!
 955     \private
 956     Generates a new minor version number
 957    */
 958    function _new_version($version,$minor=true)
 959    {
 960      $parts = explode('.',$version);
 961      if($minor) {
 962        $parts[count($parts)-1]++;
 963      } else {
 964        $parts[0]++;
 965        for ($i = 1; $i < count($parts); $i++) {
 966          $parts[$i] = 0;
 967        }
 968      }
 969      return implode('.',$parts);
 970    }
 971     
 972    /*!
 973     \private
 974     Creates directory structure for process
 975    */
 976    function _create_directory_structure($name)
 977    {
 978      // Create in processes a directory with this name
 979      $path = GALAXIA_PROCESSES.SEP.$name;
 980      if (!file_exists($path)) mkdir($path,0770);
 981      $path = GALAXIA_PROCESSES.SEP.$name.SEP."graph";
 982      if (!file_exists($path)) mkdir($path,0770); 
 983      $path = GALAXIA_PROCESSES.SEP.$name.SEP."code";
 984      if (!file_exists($path)) mkdir($path,0770);
 985      $path = GALAXIA_PROCESSES.SEP.$name.SEP."compiled";
 986      if (!file_exists($path)) mkdir($path,0770);
 987      $path = GALAXIA_PROCESSES.SEP.$name.SEP."code".SEP."activities";
 988      if (!file_exists($path)) mkdir($path,0770);
 989      $path = GALAXIA_PROCESSES.SEP.$name.SEP."code".SEP."templates";
 990      if (!file_exists($path)) mkdir($path,0770);
 991      if (GALAXIA_TEMPLATES) {
 992        $path = GALAXIA_TEMPLATES.SEP.$name;
 993        if (!file_exists($path)) mkdir($path,0770);
 994      }
 995      // Create shared file
 996      $file = GALAXIA_PROCESSES.SEP.$name.SEP."code".SEP."shared.php";
 997      if (!file_exists($file))
 998      {
 999        $fp = fopen(GALAXIA_PROCESSES.SEP.$name.SEP."code".SEP."shared.php","w");
1000        if (!fp) return false;
1001        fwrite($fp,'<'.'?'.'php'."\n".'?'.'>');
1002        fclose($fp);
1003      }
1004    }
1005     
1006    /*!
1007     \private
1008     Removes a directory recursively
1009    */
1010    function _remove_directory($dir,$rec=false)
1011    {
1012      // Prevent a disaster
1013      if(trim($dir) == SEP || trim($dir)=='.' || trim($dir)=='templates' || trim($dir)=='templates'.SEP) return false;
1014      $h = opendir($dir);
1015      while(($file = readdir($h)) != false) {
1016        if(is_file($dir.SEP.$file)) {
1017          @unlink($dir.SEP.$file);
1018        } else {
1019          if($rec && $file != '.' && $file != '..') {
1020            $this->_remove_directory($dir.SEP.$file, true);
1021          }
1022        }
1023      }
1024      closedir($h);   
1025      @rmdir($dir);
1026      @unlink($dir);
1027    }
1028  
1029    function _rec_copy($dir1,$dir2)
1030    {
1031      @mkdir($dir2,0777);
1032      $h = opendir($dir1);
1033      while(($file = readdir($h)) !== false) {
1034        if(is_file($dir1.SEP.$file)) {
1035          copy($dir1.SEP.$file,$dir2.SEP.$file);
1036        } else {
1037          if($file != '.' && $file != '..') {
1038            $this->_rec_copy($dir1.SEP.$file, $dir2.SEP.$file);
1039          }
1040        }
1041      }
1042      closedir($h);   
1043    }
1044  
1045    function _start_element_handler($parser, $element, $attribs)
1046    {
1047      $aux=Array('name'=>$element,
1048                 'data'=>'',
1049                 'parent' => $this->current,
1050                 'children'=>Array(),
1051                 'attribs' => $attribs);
1052                 
1053      $i = count($this->tree);           
1054      $this->tree[$i] = $aux;
1055  
1056      $this->tree[$this->current]['children'][]=$i;
1057      $this->current=$i;
1058    }
1059  
1060  
1061    function _end_element_handler($parser, $element)
1062    {
1063      //when a tag ends put text
1064      $this->tree[$this->current]['data']=$this->buffer;           
1065      $this->buffer='';
1066      $this->current=$this->tree[$this->current]['parent'];
1067    }
1068  
1069  
1070    function _data_handler($parser, $data)
1071    {
1072        $this->buffer .= $data;
1073    }
1074  
1075    //! return an associative array with all config items for the given processId
1076    /*!
1077    *This getConfigValues differs from the Process->getConfigValues because the parameter here
1078    *id just the processId. All config items are returned as a function result. This function
1079    *gets the items defined in process_config table for this process. In fact this admin function bypass
1080    *the process behaviour and is just showing you the basic content of the table.
1081    *If the distinct_type is set the returned array will be:
1082    *    * 0    =>('wf_config_name'=> 'foo')
1083    *          =>('wf_config_value'=>'bar')
1084    *          =>('wf_config_vale_int'=>null)
1085    *    * 1     =>('wf_config_name' => 'toto')
1086    *          =>('wf_config_value'=>'')
1087    *          =>('wf_config_vale_int'=>15)
1088    *if set to false (default) the result array will be (note that this is the default result if having just the $pId):
1089    *    * 'foo'=>'bar'
1090    *    * 'toto'=>15
1091    *If the askProcessObject is set to true (false by default) then the ProcessManager will load a process
1092    *object to run directly Process->getConfigValues($config_ask_array) this let you use this ProcessManager
1093    *getConfigValues the same way you would use $process->getConfigValues, with initialisation of default values.
1094    *you should then call this function this way: $conf_result=$pm->getConfigValues($pId,true,true,$my_conf_array)
1095    */
1096    function getConfigValues($pId, $distinct_types=false, $askProcessObject=false, $config_array=array())
1097    {
1098      if (!$askProcessObject)
1099      {
1100        $query = 'select * from '.GALAXIA_TABLE_PREFIX.'process_config where wf_p_id=?';
1101        $result = $this->query($query, array($pId));
1102        $result_array=array();
1103        while($res = $result->fetchRow())
1104        {
1105          if ( (!$distinct_types) )
1106          {// we want a simple array
1107            if ($res['wf_config_value_int']==null)
1108            {
1109              $result_array[$res['wf_config_name']] = $res['wf_config_value'];
1110              }
1111            else
1112            {
1113              $result_array[$res['wf_config_name']] = $res['wf_config_value_int'];
1114            }
1115          }
1116          else
1117          {// build a more complex result array, which is just the table rows
1118            $result_array[] = $res;
1119          }
1120        }
1121      }
1122      else //we'll load a Process object and let him work for us
1123      {
1124        //Warning: this means you have to include the Process.php from the API
1125        $this->Process =& new Process($this->db);
1126        $this->Process->getProcess($pId);
1127        $result_array = $this->Process->getConfigValues($config_array);
1128        unset ($this->Process);
1129      }
1130      return $result_array;
1131    }
1132    
1133    //! call a process object to save his new config values
1134    /*!
1135    This setConfigValues takes a process Id as first argument and simply call this process's setConfigValues
1136    function. We let the process define the better way to store the data given as second arg.
1137    */
1138    function setConfigValues($pId, &$config_array)
1139    {
1140      //Warning: this means you have to include the Process.php from the API
1141      $this->Process =& new Process($this->db);
1142      $this->Process->getProcess($pId);
1143      $this->Process->setConfigValues($config_array);
1144      unset ($this->Process);
1145    }
1146    
1147    /*!
1148    * @return the avaible agents array.
1149    */
1150    function get_agents()
1151    {
1152      return galaxia_get_agents_list();
1153    }
1154  
1155    /*! get the view activity id avaible for a given process
1156    * @param $pId is the process Id
1157    * @return false if no view activity is avaible for the process, return the activity id if there is one
1158    */
1159    function get_process_view_activity($pId)
1160    {
1161      $mid = 'where gp.wf_p_id=? and ga.wf_type=?';
1162      $bindvars = array($pId,'view');
1163      $query = 'select ga.wf_activity_id
1164          from '.GALAXIA_TABLE_PREFIX.'processes gp
1165      INNER JOIN '.GALAXIA_TABLE_PREFIX."activities ga ON gp.wf_p_id=ga.wf_p_id
1166      $mid";
1167      $result = $this->query($query,$bindvars);
1168      $ret = Array();
1169      $retval = false;
1170      if (!(empty($result)))
1171      {
1172        while($res = $result->fetchRow()) 
1173        {
1174          $retval = $res['wf_activity_id'];
1175        }
1176      }
1177      return $retval;
1178    }
1179  
1180  }
1181  
1182  
1183  ?>


Généré le : Sun Feb 25 17:20:01 2007 par Balluche grâce à PHPXref 0.7