[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
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 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |