| Total Complexity | 603 |
| Total Lines | 2623 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like infolog_ui often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use infolog_ui, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 23 | class infolog_ui |
||
| 24 | { |
||
| 25 | var $public_functions = array( |
||
| 26 | 'index' => True, |
||
| 27 | 'edit' => True, |
||
| 28 | 'delete' => True, |
||
| 29 | 'close' => True, |
||
| 30 | 'admin' => True, |
||
| 31 | 'hook_view' => True, |
||
| 32 | 'writeLangFile' => True, |
||
| 33 | 'mail_import' => True |
||
| 34 | ); |
||
| 35 | /** |
||
| 36 | * reference to the infolog preferences of the user |
||
| 37 | * |
||
| 38 | * @var array |
||
| 39 | */ |
||
| 40 | var $prefs; |
||
| 41 | /** |
||
| 42 | * instance of the bo-class |
||
| 43 | * |
||
| 44 | * @var infolog_bo |
||
| 45 | */ |
||
| 46 | var $bo; |
||
| 47 | /** |
||
| 48 | * instance of the etemplate class |
||
| 49 | * |
||
| 50 | * @var Etemplate |
||
| 51 | */ |
||
| 52 | var $tmpl; |
||
| 53 | /** |
||
| 54 | * allowed units and hours per day, can be overwritten by the projectmanager configuration, default all units, 8h |
||
| 55 | * |
||
| 56 | * @var string |
||
| 57 | */ |
||
| 58 | var $duration_format = ','; // comma is necessary! |
||
| 59 | |||
| 60 | var $icons = array( |
||
| 61 | 'type' => array( |
||
| 62 | 'task' => 'task.gif', 'task_alt' => 'Task', |
||
| 63 | 'phone' => 'phone.gif', 'phone_alt' => 'Phonecall', |
||
| 64 | 'note' => 'note.gif', 'note_alt' => 'Note', |
||
| 65 | 'confirm' => 'confirm.gif', 'confirm_alt' => 'Confirmation', |
||
| 66 | 'reject' => 'reject.gif', 'reject_alt' => 'Reject', |
||
| 67 | 'email' => 'email.gif', 'email_alt' => 'Email' ), |
||
| 68 | 'action' => array( |
||
| 69 | 'new' => 'new.gif', 'new_alt' => 'Add Sub', |
||
| 70 | 'view' => 'view.gif', 'view_alt' => 'View Subs', |
||
| 71 | 'parent' => 'parent.gif', 'parent_alt' => 'View other Subs', |
||
| 72 | 'edit' => 'edit.gif', 'edit_alt' => 'Edit', |
||
| 73 | 'addfile' => 'addfile.gif', 'addfile_alt' => 'Add a file', |
||
| 74 | 'delete' => 'delete.gif', 'delete_alt' => 'Delete', |
||
| 75 | 'close' => 'done.gif', 'close_alt' => 'Close' , |
||
| 76 | 'close_all' => 'done_all.gif', 'close_all_alt' => 'Close' ), |
||
| 77 | 'status' => array( |
||
| 78 | 'billed' => 'billed.gif', 'billed_alt' => 'billed', |
||
| 79 | 'done' => 'done.gif', 'done_alt' => 'done', |
||
| 80 | 'will-call' => 'will-call.gif', 'will-call_alt' => 'will-call', |
||
| 81 | 'call' => 'call.gif', 'call_alt' => 'call', |
||
| 82 | 'ongoing' => 'ongoing.gif', 'ongoing_alt' => 'ongoing', |
||
| 83 | 'offer' => 'offer.gif', 'offer_alt' => 'offer' ) |
||
| 84 | ); |
||
| 85 | var $filters; |
||
| 86 | var $messages = array( |
||
| 87 | 'edit' => 'InfoLog - Edit', |
||
| 88 | 'add' => 'InfoLog - New', |
||
| 89 | 'add_sub' => 'InfoLog - New Subproject', |
||
| 90 | 'sp' => '- Subprojects from', |
||
| 91 | ); |
||
| 92 | |||
| 93 | /** |
||
| 94 | * Constructor |
||
| 95 | * |
||
| 96 | * @return infolog_ui |
||
| 97 | */ |
||
| 98 | function __construct(Etemplate $etemplate = null) |
||
| 149 | } |
||
| 150 | |||
| 151 | /** |
||
| 152 | * Sets additional fields for one infolog entry, which are not persistent in the DB |
||
| 153 | * |
||
| 154 | * @param array $info infolog entry read from the db |
||
| 155 | * @param array &$readonlys ACL specific settings for the buttons |
||
| 156 | * @param string $action |
||
| 157 | * @param string/int $action_id |
||
| 158 | * @param boolean $show_links |
||
| 159 | * @param int $details |
||
| 160 | * @return array |
||
| 161 | */ |
||
| 162 | function get_info($info,&$readonlys,$action='',$action_id='',$show_links=false,$details = 1) |
||
| 273 | } |
||
| 274 | |||
| 275 | /** |
||
| 276 | * Check if no filter is active |
||
| 277 | * |
||
| 278 | * @param array $query |
||
| 279 | * @return string name of 1. filter found or null |
||
| 280 | */ |
||
| 281 | protected static function filter(array $query) |
||
| 282 | { |
||
| 283 | $filter = $query['filter'] ? 'filter' : ($query['cat_id'] ? 'cat_id' : null); |
||
| 284 | foreach((array)$query['col_filter'] as $name => $value) |
||
| 285 | { |
||
| 286 | if ((string)$value !== '') |
||
| 287 | { |
||
| 288 | $filter = $name; |
||
| 289 | break; |
||
| 290 | } |
||
| 291 | } |
||
| 292 | //error_log(__METHOD__."(col_filter=".array2string($query['col_filter']).") returning ".array2string($filter)); |
||
| 293 | return $filter; |
||
| 294 | } |
||
| 295 | |||
| 296 | /** |
||
| 297 | * Callback for nextmatch widget |
||
| 298 | * |
||
| 299 | * @param array &$query |
||
| 300 | * @param array &$rows |
||
| 301 | * @param array &$readonlys |
||
| 302 | * @return int |
||
| 303 | */ |
||
| 304 | function get_rows(&$query,&$rows,&$readonlys) |
||
| 305 | { |
||
| 306 | //error_log(__METHOD__."() query[csv_export]=".array2string($query['csv_export']).", query[filter]=".array2string($query['filter']).", query[col_filter]=".array2string(array_diff($query['col_filter'],array('',0))).' '.function_backtrace()); |
||
| 307 | if (!$query['csv_export']) |
||
| 308 | { |
||
| 309 | unset($query['no_actions']); |
||
| 310 | if (!$query['col_filter']['parent_id'] && !$query['search'] && |
||
| 311 | ($this->prefs['listNoSubs'] == '1' || $this->prefs['listNoSubs'] === 'filter' && !self::filter($query))) |
||
| 312 | { |
||
| 313 | $parent_id = 0; |
||
| 314 | } |
||
| 315 | else |
||
| 316 | { |
||
| 317 | $parent_id = $query['col_filter']['parent_id']; |
||
| 318 | } |
||
| 319 | //error_log(__METHOD__."() prefs[listNoSubs]=".array2string($this->prefs['listNoSubs'])." --> parent_id=$parent_id"); |
||
| 320 | unset($query['col_filter']['parent_id']); |
||
| 321 | if(!$query['action']) |
||
| 322 | { |
||
| 323 | Api\Cache::setSession('infolog', $query['session_for'].'session_data', |
||
| 324 | array_diff_key ($query, array_flip(array('rows','actions','action_links','placeholder_actions')))); |
||
| 325 | } |
||
| 326 | $query['actions'] = $this->get_actions($query); |
||
| 327 | $query['row_id'] = 'info_id'; |
||
| 328 | $query['row_modified'] = 'row_mod'; |
||
| 329 | $query['parent_id'] = 'info_id_parent'; |
||
| 330 | $query['is_parent'] = 'info_anz_subs'; |
||
| 331 | $query['action_var'] = 'multi_action'; // as 'action' is already used in infolog |
||
| 332 | } |
||
| 333 | // nextmatch opened an infolog containing children --> do not filter them, always show all children |
||
| 334 | elseif($query['csv_export'] === 'children') |
||
| 335 | { |
||
| 336 | $query['filter'] = $query['search'] = $query['cat_id'] = ''; |
||
| 337 | $query['col_filter'] = array('info_id_parent' => $query['col_filter']['info_id_parent']); |
||
| 338 | } |
||
| 339 | |||
| 340 | $GLOBALS['egw']->session->commit_session(); |
||
| 341 | $orginal_colfilter = $query['col_filter']; |
||
| 342 | if (isset($parent_id)) $query['col_filter']['info_id_parent'] = (string)$parent_id; |
||
| 343 | |||
| 344 | //echo "<p>infolog_ui.get_rows(start=$query[start],search='$query[search]',filter='$query[filter]',cat_id=$query[cat_id],action='$query[action]/$query[action_id]',col_filter=".print_r($query['col_filter'],True).",sort=$query[sort],order=$query[order])</p>\n"; |
||
| 345 | if (!isset($query['start'])) $query['start'] = 0; |
||
| 346 | |||
| 347 | // handle action and linked filter (show only entries linked to a certain other entry) |
||
| 348 | $link_filters = array(); |
||
| 349 | $links = array(); |
||
| 350 | if ($query['col_filter']['linked']) |
||
| 351 | { |
||
| 352 | $link_filters['linked'] = $query['col_filter']['linked']; |
||
| 353 | $links['linked'] = array(); |
||
| 354 | unset($query['col_filter']['linked']); |
||
| 355 | } |
||
| 356 | if($query['action'] && in_array($query['action'], array_keys($GLOBALS['egw_info']['apps'])) && $query['action_id']) |
||
| 357 | { |
||
| 358 | $link_filters['action'] = array('app'=>$query['action'], 'id' => $query['action_id']); |
||
| 359 | $links['action'] = array(); |
||
| 360 | } |
||
| 361 | foreach($link_filters as $key => $link) |
||
| 362 | { |
||
| 363 | if(!is_array($link)) |
||
| 364 | { |
||
| 365 | // Legacy string style |
||
| 366 | list($app,$id) = explode(':',$link); |
||
| 367 | } |
||
| 368 | else |
||
| 369 | { |
||
| 370 | // Full info |
||
| 371 | $app = $link['app']; |
||
| 372 | $id = $link['id']; |
||
| 373 | } |
||
| 374 | if(!is_array($id)) $id = explode(',',$id); |
||
| 375 | if (!($linked = Link::get_links_multiple($app,$id,true,'infolog','',$query['col_filter']['info_status'] == 'deleted'))) |
||
| 376 | { |
||
| 377 | $rows = array(); // no infologs linked to selected link --> no rows to return |
||
| 378 | return 0; |
||
| 379 | } |
||
| 380 | |||
| 381 | |||
| 382 | foreach($linked as $infos) |
||
| 383 | { |
||
| 384 | $links[$key] = array_merge($links[$key],$infos); |
||
| 385 | } |
||
| 386 | $links[$key] = array_unique($links[$key]); |
||
| 387 | if($key == 'linked') |
||
| 388 | { |
||
| 389 | $linked = array('app' => $app, 'id' => $id, 'title' => (count($id) == 1 ? Link::title($app, $id) : lang('multiple'))); |
||
| 390 | } |
||
| 391 | } |
||
| 392 | if(count($links)) |
||
| 393 | { |
||
| 394 | $query['col_filter']['info_id'] = count($links) > 1 ? call_user_func_array('array_intersect', $links) : $links[$key]; |
||
| 395 | } |
||
| 396 | |||
| 397 | // check if we have a custom, type-specific template |
||
| 398 | $old_template = $query['template']; |
||
| 399 | |||
| 400 | // Reset custom, type-specific template if type was cleared (without changing it for home) |
||
| 401 | if(!$query['template'] || stripos($query['template'], 'infolog.index.rows') === 0) |
||
| 402 | { |
||
| 403 | $query['template'] = 'infolog.index.rows'; |
||
| 404 | } |
||
| 405 | unset($query['custom_fields']); |
||
| 406 | if ($query['col_filter']['info_type']) |
||
| 407 | { |
||
| 408 | $tpl = new Etemplate; |
||
| 409 | if ($tpl->read('infolog.index.rows.'.$query['col_filter']['info_type'])) |
||
| 410 | { |
||
| 411 | $query['template'] = $tpl->name; |
||
| 412 | $query['custom_fields'] = true; // read the custom fields too |
||
| 413 | } |
||
| 414 | // If status is not valid for selected type, clear status filter |
||
| 415 | if($query['col_filter']['info_status'] && $query['col_filter']['info_status'] != 'deleted' && |
||
| 416 | !in_array($query['col_filter']['info_status'], array_keys($this->bo->status[$query['col_filter']['info_type']]))) |
||
| 417 | { |
||
| 418 | $query['col_filter']['info_status'] = ''; |
||
| 419 | $clear_status_filter = true; |
||
| 420 | } |
||
| 421 | } |
||
| 422 | // Framework\Template change forces the UI to do a full update first, no point in getting rows right now |
||
| 423 | if($old_template && $old_template != $query['template']) return 0; |
||
| 424 | |||
| 425 | // do we need to read the custom fields, depends on the column is enabled and customfields exist, prefs are filter specific |
||
| 426 | // so we have to check that as well |
||
| 427 | $details = $query['filter2'] == 'all'; |
||
| 428 | $columnselection_pref = 'nextmatch-'.($query['action'] ? 'infolog.'.$query['action'] : ($tpl && $tpl->name == $query['template'] ? $query['template'] : 'infolog.index.rows')) |
||
| 429 | .($details ? '-details' : ''); |
||
| 430 | //error_log(__METHOD__."(start=$query[start], num_rows=$query[num_rows]) query[col_filter][info_type]={$query['col_filter']['info_type']} --> query[template]=$query[template], columselection_pref=$columnselection_pref"); |
||
| 431 | |||
| 432 | $columselection = $this->prefs[$columnselection_pref]; |
||
| 433 | |||
| 434 | if (!$query['selectcols'] && $columselection) |
||
| 435 | { |
||
| 436 | $columselection = is_array($columselection) ? $columselection : explode(',',$columselection); |
||
| 437 | } |
||
| 438 | else |
||
| 439 | { |
||
| 440 | $columselection = $query['selectcols'] ? (is_array($query['selectcols']) ? $query['selectcols'] : explode(',',$query['selectcols'])) : array(); |
||
| 441 | } |
||
| 442 | // do we need to query the cf's |
||
| 443 | $query['custom_fields'] = $this->bo->customfields && (!$columselection || in_array('customfields',$columselection)); |
||
| 444 | |||
| 445 | $infos = $this->bo->search($query); |
||
| 446 | $query['col_filter'] = $orginal_colfilter; |
||
| 447 | if (!is_array($infos)) |
||
| 448 | { |
||
| 449 | $infos = array( ); |
||
| 450 | } |
||
| 451 | // add a '-details' to the name of the columnselection pref |
||
| 452 | if ($details) |
||
| 453 | { |
||
| 454 | $query['default_cols'] = '!cat_id,info_used_time_info_planned_time,info_used_time_info_planned_time_info_replanned_time,info_id'; |
||
| 455 | } |
||
| 456 | else |
||
| 457 | { |
||
| 458 | $query['default_cols'] = '!cat_id,info_datemodified,info_used_time_info_planned_time,info_used_time_info_planned_time_info_replanned_time,info_id'; |
||
| 459 | } |
||
| 460 | // set old show_times pref, that get_info calculates the cumulated time of the timesheets (we only check used&planned to work for both time cols) |
||
| 461 | $this->prefs['show_times'] = strpos($this->prefs[$query['columnselection_pref']],'info_used_time_info_planned_time') !== false; |
||
| 462 | |||
| 463 | // query all links and sub counts in one go |
||
| 464 | if ($infos && (!$query['csv_export'] || !is_array($query['csv_export']))) |
||
| 465 | { |
||
| 466 | $links = Link::get_links_multiple('infolog',array_keys($infos),true,'','link_lastmod DESC',true); // true=incl. deleted |
||
| 467 | $anzSubs = $this->bo->anzSubs(array_keys($infos)); |
||
| 468 | } |
||
| 469 | $rows = array(); |
||
| 470 | |||
| 471 | // Don't add parent in if info_id_parent (expanding to show subs) |
||
| 472 | if ($query['action_id'] && $query['csv_export'] !== 'children') |
||
| 473 | { |
||
| 474 | $parents = $query['action'] == 'sp' && $query['action_id'] ? (array)$query['action_id'] : array(); |
||
| 475 | if (!empty($parents) && count($parents) == 1 && is_array($query['action_id'])) |
||
| 476 | { |
||
| 477 | $query['action_id'] = array_shift($query['action_id']); // display single parent as app_header |
||
| 478 | } |
||
| 479 | } |
||
| 480 | |||
| 481 | $parent_first = !empty($parents) && count($parents) == 1; |
||
| 482 | $parent_index = 0; |
||
| 483 | // et2 nextmatch listens to total, and only displays that many rows, so add parent in or we'll lose the last row |
||
| 484 | if($parent_first || $query['action'] == 'sp' && is_array($query['action_id'])) $query['total']++; |
||
| 485 | |||
| 486 | // Check to see if we need to remove description |
||
| 487 | foreach($infos as $id => $info) |
||
| 488 | { |
||
| 489 | if (!$query['csv_export'] || !is_array($query['csv_export'])) |
||
| 490 | { |
||
| 491 | $info['links'] =& $links[$id]; |
||
| 492 | $info['info_anz_subs'] = (int)$anzSubs[$id]; |
||
| 493 | $info = $this->get_info($info,$readonlys,null,null,false,$details); |
||
| 494 | } |
||
| 495 | // for subs view ('sp') add parent(s) in front of subs once(!) |
||
| 496 | if ( $parent_first && ($main = $this->bo->read($query['action_id'])) || |
||
| 497 | $parents && ($parent_index = array_search($info['info_id_parent'], $parents)) !== false && |
||
| 498 | ($main = $this->bo->read($info['info_id_parent']))) |
||
| 499 | { |
||
| 500 | $main = $this->get_info($main, $readonlys); |
||
| 501 | $main['class'] .= 'th '; |
||
| 502 | // if only certain custom-fields are to be displayed, we need to unset the not displayed ones manually |
||
| 503 | // as read() always read them all, while search() only reads the selected ones |
||
| 504 | if ($query['custom_fields']) |
||
| 505 | { |
||
| 506 | foreach($columselection as $col) |
||
| 507 | { |
||
| 508 | if ($col[0] == '#') |
||
| 509 | { |
||
| 510 | foreach(array_keys($main) as $n) |
||
| 511 | { |
||
| 512 | if ($n[0] == '#' && !in_array($n, $columselection)) unset($main[$n]); |
||
| 513 | } |
||
| 514 | break; |
||
| 515 | } |
||
| 516 | } |
||
| 517 | } |
||
| 518 | $parent_first = false; |
||
| 519 | if($query['start'] == 0) |
||
| 520 | { |
||
| 521 | array_splice($rows, $id, 0, array($main)); |
||
| 522 | unset($parents[$parent_index]); |
||
| 523 | } |
||
| 524 | } |
||
| 525 | $rows[] = $info; |
||
| 526 | } |
||
| 527 | unset($links); |
||
| 528 | |||
| 529 | if ($query['cat_id']) $rows['no_cat_id'] = true; |
||
| 530 | if ($query['no_actions']) $rows['no_actions'] = true; |
||
| 531 | $rows['no_timesheet'] = !isset($GLOBALS['egw_info']['user']['apps']['timesheet']); |
||
| 532 | if($clear_status_filter) |
||
| 533 | { |
||
| 534 | $rows['info_status'] = ''; |
||
| 535 | } |
||
| 536 | |||
| 537 | // switch cf column off, if we have no cf's |
||
| 538 | $rows['no_customfields'] = !$query['custom_fields']; |
||
| 539 | |||
| 540 | $rows['no_info_owner_info_responsible'] = ( |
||
| 541 | $GLOBALS['egw_info']['user']['preferences']['common']['account_selection'] == 'none' && |
||
| 542 | !isset($GLOBALS['egw_info']['user']['apps']['admin']) |
||
| 543 | ); |
||
| 544 | |||
| 545 | // if filtered by type, show only the stati of the filtered type |
||
| 546 | $rows['sel_options']['info_status'] = $this->bo->get_status($query['col_filter']['info_type']); |
||
| 547 | |||
| 548 | if ($this->bo->history) |
||
| 549 | { |
||
| 550 | $rows['sel_options']['info_status']['deleted'] = 'deleted'; |
||
| 551 | } |
||
| 552 | // Update actions for selected type / status / etc. |
||
| 553 | $query['actions'] = $this->get_actions($query); |
||
| 554 | |||
| 555 | if ($GLOBALS['egw_info']['flags']['currentapp'] == 'infolog' && !$this->called_by) |
||
| 556 | { |
||
| 557 | $headers = array(); |
||
| 558 | if ($query['filter'] != '' && !empty($this->filters[$query['filter']])) |
||
| 559 | { |
||
| 560 | $headers[] = lang($this->filters[$query['filter']]); |
||
| 561 | } |
||
| 562 | if ($query['action'] && ($title = $query['action_title'] || is_array($query['action_id']) ? |
||
| 563 | $query['action_title'] : Link::title($query['action']=='sp'?'infolog':$query['action'],$query['action_id']))) |
||
| 564 | { |
||
| 565 | $headers[] = $title; |
||
| 566 | } |
||
| 567 | if ($query['search']) |
||
| 568 | { |
||
| 569 | $headers[] = lang("Search for '%1'", $query['search']); |
||
| 570 | } |
||
| 571 | $GLOBALS['egw_info']['flags']['app_header'] = implode(': ', $headers); |
||
| 572 | } |
||
| 573 | |||
| 574 | if (isset($linked)) $query['col_filter']['linked'] = $linked; // add linked back to the colfilter |
||
| 575 | |||
| 576 | return $query['total']; |
||
| 577 | } |
||
| 578 | |||
| 579 | /** |
||
| 580 | * Hook for timesheet to set some extra data and links |
||
| 581 | * |
||
| 582 | * @param array $data |
||
| 583 | * @param int $data[id] info_id |
||
| 584 | * @return array with key => value pairs to set in new timesheet and link_app/link_id arrays |
||
| 585 | */ |
||
| 586 | function timesheet_set($data) |
||
| 587 | { |
||
| 588 | $set = array(); |
||
| 589 | if ((int)$data['id'] && ($info = $this->bo->read($data['id']))) |
||
| 590 | { |
||
| 591 | if ($info['info_cat']) $set['cat_id'] = $info['info_cat']; |
||
| 592 | if ($info['info_used_time']) |
||
| 593 | { |
||
| 594 | $set['ts_duration'] = $info['info_used_time']; |
||
| 595 | } |
||
| 596 | if ($info['pl_id']) |
||
| 597 | { |
||
| 598 | $set['pl_id'] = $info['pl_id']; |
||
| 599 | } |
||
| 600 | if ($info['info_price']) |
||
| 601 | { |
||
| 602 | $set['ts_unitprice'] = $info['info_price']; |
||
| 603 | } |
||
| 604 | |||
| 605 | foreach(Link::get_links('infolog',$info['info_id'],'','link_lastmod DESC',true) as $link) |
||
| 606 | { |
||
| 607 | if ($link['app'] != 'timesheet' && $link['app'] != Link::VFS_APPNAME) |
||
| 608 | { |
||
| 609 | $set['link_app'][] = $link['app']; |
||
| 610 | $set['link_id'][] = $link['id']; |
||
| 611 | } |
||
| 612 | } |
||
| 613 | |||
| 614 | } |
||
| 615 | return $set; |
||
| 616 | } |
||
| 617 | |||
| 618 | /** |
||
| 619 | * Hook for calendar to set some extra data and links |
||
| 620 | * |
||
| 621 | * @param array $data event-array preset by calendar plus |
||
| 622 | * @param int $data[entry_id] info_id |
||
| 623 | * @return array with key => value pairs to set in new event and link_app/link_id arrays |
||
| 624 | */ |
||
| 625 | function calendar_set($data) |
||
| 626 | { |
||
| 627 | if (!($infolog = $this->bo->read($data['entry_id']))) |
||
| 628 | { |
||
| 629 | return $data; |
||
| 630 | } |
||
| 631 | $event = array_merge($data,array( |
||
| 632 | 'category' => $GLOBALS['egw']->categories->check_list(Acl::READ, $infolog['info_cat']), |
||
| 633 | 'priority' => $infolog['info_priority'] + 1, |
||
| 634 | 'public' => $infolog['info_access'] != 'private', |
||
| 635 | 'title' => $infolog['info_subject'], |
||
| 636 | 'description' => $infolog['info_des'], |
||
| 637 | 'location' => $infolog['info_location'], |
||
| 638 | 'start' => $infolog['info_startdate'], |
||
| 639 | 'end' => $infolog['info_enddate'] ? $infolog['info_enddate'] : $infolog['info_datecompleted'] |
||
| 640 | )); |
||
| 641 | unset($event['entry_id']); |
||
| 642 | if (!$event['end']) $event['end'] = $event['start'] + (int) $GLOBALS['egw_info']['user']['preferences']['calendar']['defaultlength']*60; |
||
| 643 | |||
| 644 | // Match Api\Categories by name |
||
| 645 | $event['category'] = $GLOBALS['egw']->categories->name2id(Api\Categories::id2name($infolog['info_cat'])); |
||
| 646 | |||
| 647 | // make current user the owner of the new event, not the selected calendar, if current user has rights for it |
||
| 648 | $event['owner'] = $user = $GLOBALS['egw_info']['user']['account_id']; |
||
| 649 | |||
| 650 | // add/modify participants according to prefs |
||
| 651 | $prefs = explode(',',$this->prefs['calendar_set'] ? $this->prefs['calendar_set'] : 'responsible,contact,user'); |
||
| 652 | |||
| 653 | // if no default participants (selected calendars) --> remove all |
||
| 654 | if (!in_array('selected',$prefs)) |
||
| 655 | { |
||
| 656 | $event['participants'] = $event['participant_types'] = array(); |
||
| 657 | } |
||
| 658 | // Add responsible as participant |
||
| 659 | if (in_array('responsible',$prefs)) |
||
| 660 | { |
||
| 661 | foreach($infolog['info_responsible'] as $responsible) |
||
| 662 | { |
||
| 663 | $event['participants'][$responsible] = $event['participant_types']['u'][$responsible] = |
||
| 664 | calendar_so::combine_status($user==$responsible?'A':'U'); |
||
| 665 | } |
||
| 666 | } |
||
| 667 | // Add linked contact as participant |
||
| 668 | if (in_array('contact',$prefs) && $infolog['info_link']['app'] == 'addressbook') |
||
| 669 | { |
||
| 670 | $event['participants'][calendar_so::combine_user('c',$infolog['info_link']['id'])] = |
||
| 671 | $event['participant_types']['c'][$infolog['info_link']['id']] = calendar_so::combine_status('U'); |
||
| 672 | } |
||
| 673 | if (in_array('owner',$prefs)) |
||
| 674 | { |
||
| 675 | $event['participants'][$infolog['info_owner']] = $event['participant_types']['u'][$infolog['info_owner']] = |
||
| 676 | calendar_so::combine_status('A',1,'CHAIR'); |
||
| 677 | } |
||
| 678 | // Add current user, if set or no other participants, which is not allowed |
||
| 679 | if (in_array('user',$prefs)) |
||
| 680 | { |
||
| 681 | $event['participants'][$user] = $event['participant_types']['u'][$user] = |
||
| 682 | calendar_so::combine_status('A',1,'CHAIR'); |
||
| 683 | } |
||
| 684 | |||
| 685 | // Add infolog link to calendar entry |
||
| 686 | $event['link_app'][] = $infolog['info_link']['app']; |
||
| 687 | $event['link_id'][] = $infolog['info_link']['id']; |
||
| 688 | |||
| 689 | // Copy infolog's links |
||
| 690 | foreach(Link::get_links('infolog',$infolog['info_id'],'','link_lastmod DESC',true) as $link) |
||
| 691 | { |
||
| 692 | if ($link['app'] != Link::VFS_APPNAME) |
||
| 693 | { |
||
| 694 | $event['link_app'][] = $link['app']; |
||
| 695 | $event['link_id'][] = $link['id']; |
||
| 696 | } |
||
| 697 | } |
||
| 698 | // Copy same custom fields |
||
| 699 | foreach(array_keys(Api\Storage\Customfields::get('calendar')) as $name) |
||
| 700 | { |
||
| 701 | if ($this->bo->customfields[$name]) $event['#'.$name] = $infolog['#'.$name]; |
||
| 702 | } |
||
| 703 | //error_log(__METHOD__.'('.array2string($data).') infolog='.array2string($infolog).' returning '.array2string($event)); |
||
| 704 | return $event; |
||
| 705 | } |
||
| 706 | |||
| 707 | /** |
||
| 708 | * hook called be calendar to include events or todos in the cal-dayview |
||
| 709 | * Since the hook has no idea about infolog or preferences, we add the user's |
||
| 710 | * current sorting for infolog here so they're in the expected order |
||
| 711 | * |
||
| 712 | * @param int $args[year], $args[month], $args[day] date of the events |
||
| 713 | * @param int $args[owner] owner of the events |
||
| 714 | * @param string $args[location] calendar_include_{events|todos} |
||
| 715 | * @return array of events (array with keys starttime, endtime, title, view, icon, content) |
||
| 716 | */ |
||
| 717 | public function cal_to_include($args) |
||
| 718 | { |
||
| 719 | $nm = Api\Cache::getSession('infolog', 'session_data'); |
||
| 720 | if($nm) |
||
| 721 | { |
||
| 722 | $args['order'] = $nm['order']; |
||
| 723 | $args['sort'] = $nm['sort']; |
||
| 724 | } |
||
| 725 | |||
| 726 | return $this->bo->cal_to_include($args); |
||
| 727 | } |
||
| 728 | |||
| 729 | /** |
||
| 730 | * Shows the infolog list |
||
| 731 | * |
||
| 732 | * @param array/string $values etemplate content or 'reset_action_view' if called by index.php to reset an action-view |
||
| 733 | * @param string $action if set only entries liked to that $action:$action_id are shown |
||
| 734 | * @param string $action_id if set only entries liked to that $action:$action_id are shown |
||
| 735 | * @param mixed $called_as is how we got called, for a hook eg. the call-params of that page containing the hook |
||
| 736 | * @param boolean $e$extra_app_header * @param boolean $return_html=false |
||
| 737 | * @param string $own_referer='' this is our own referer |
||
| 738 | * @param string $action_title='' app_header for the action, if '' we try the link-title |
||
| 739 | */ |
||
| 740 | function index($values = null,$action='',$action_id='',$called_as=0,$extra_app_header=False,$return_html=False,$own_referer='',$action_title='') |
||
| 741 | { |
||
| 742 | unset($extra_app_header); // not used, but dont want to change signature |
||
| 743 | if (is_array($values)) |
||
| 744 | { |
||
| 745 | $called_as = $values['called_as']; |
||
| 746 | $own_referer = $values['own_referer']; |
||
| 747 | } |
||
| 748 | elseif ($own_referer === '') |
||
| 749 | { |
||
| 750 | $own_referer = Api\Header\Referer::get(); |
||
| 751 | if (strpos($own_referer,'menuaction=infolog.infolog_ui.edit') !== false) |
||
| 752 | { |
||
| 753 | $own_referer = Api\Cache::getSession('infolog', 'own_session'); |
||
| 754 | } |
||
| 755 | else |
||
| 756 | { |
||
| 757 | Api\Cache::setSession('infolog', 'own_session', $own_referer); |
||
| 758 | } |
||
| 759 | } |
||
| 760 | |||
| 761 | // Handle legacy buttons like actions |
||
| 762 | if(is_array($values)) |
||
| 763 | { |
||
| 764 | foreach(array('document', 'view', 'delete') as $button) |
||
| 765 | { |
||
| 766 | if(isset($values['nm']['rows'][$button])) |
||
| 767 | { |
||
| 768 | $id = @key($values['nm']['rows'][$button]); |
||
| 769 | $values['nm']['multi_action'] = $button; |
||
| 770 | $values['nm']['selected'] = array($id); |
||
| 771 | break; // Only one can come per submit |
||
| 772 | } |
||
| 773 | } |
||
| 774 | } |
||
| 775 | if (is_array($values) && !empty($values['nm']['multi_action'])) |
||
| 776 | { |
||
| 777 | if (empty($values['nm']['selected']) && !$values['nm']['select_all']) |
||
| 778 | { |
||
| 779 | $msg = lang('You need to select some entries first'); |
||
| 780 | } |
||
| 781 | else |
||
| 782 | { |
||
| 783 | // Some processing to add values in for links and cats |
||
| 784 | $multi_action = $values['nm']['multi_action']; |
||
| 785 | // Action has an additional action - add / delete, etc. Buttons named <multi-action>_action[action_name] |
||
| 786 | if(in_array($multi_action, array('link', 'responsible', 'startdate', 'enddate'))) |
||
| 787 | { |
||
| 788 | // eTemplate ignores the _popup namespace, but et2 doesn't |
||
| 789 | if($values[$multi_action.'_popup']) |
||
| 790 | { |
||
| 791 | $popup =& $values[$multi_action.'_popup']; |
||
| 792 | } |
||
| 793 | else |
||
| 794 | { |
||
| 795 | $popup =& $values; |
||
| 796 | } |
||
| 797 | $values['nm']['multi_action'] .= '_' . key($popup[$multi_action . '_action']); |
||
| 798 | if($multi_action == 'link') |
||
| 799 | { |
||
| 800 | $popup[$multi_action] = $popup['link']['app'] . ':'.$popup['link']['id']; |
||
| 801 | } |
||
| 802 | else if(is_array($popup[$multi_action])) |
||
| 803 | { |
||
| 804 | $popup[$multi_action] = implode(',',$popup[$multi_action]); |
||
| 805 | } |
||
| 806 | $values['nm']['multi_action'] .= '_' . $popup[$multi_action]; |
||
| 807 | unset($values[$multi_action.'_popup']); |
||
| 808 | unset($values[$multi_action]); |
||
| 809 | } |
||
| 810 | $success = $failed = $action_msg = null; |
||
| 811 | if ($this->action($values['nm']['multi_action'], $values['nm']['selected'], $values['nm']['select_all'], |
||
| 812 | $success, $failed, $action_msg, $values['nm'], $msg, $values['nm']['checkboxes']['no_notifications'])) |
||
| 813 | { |
||
| 814 | $msg .= lang('%1 entries %2',$success,$action_msg); |
||
| 815 | Framework::message($msg); |
||
| 816 | } |
||
| 817 | elseif(is_null($msg)) |
||
| 818 | { |
||
| 819 | $msg .= lang('%1 entries %2, %3 failed because of insufficent rights !!!',$success,$action_msg,$failed); |
||
| 820 | Framework::message($msg,'error'); |
||
| 821 | } |
||
| 822 | elseif($msg) |
||
| 823 | { |
||
| 824 | $msg .= "\n".lang('%1 entries %2, %3 failed.',$success,$action_msg,$failed); |
||
| 825 | Framework::message($msg,'error'); |
||
| 826 | } |
||
| 827 | unset($values['nm']['multi_action']); |
||
| 828 | unset($values['nm']['select_all']); |
||
| 829 | } |
||
| 830 | } |
||
| 831 | if (!$action) |
||
| 832 | { |
||
| 833 | $action = is_array($values) && $values['action'] ? $values['action'] : $_REQUEST['action']; |
||
| 834 | $action_id = is_array($values) && $values['action_id'] ? $values['action_id'] : $_REQUEST['action_id']; |
||
| 835 | $action_title = is_array($values) && $values['action_title'] ? $values['action_title'] : $_REQUEST['action_title']; |
||
| 836 | } |
||
| 837 | //echo "<p>".__METHOD__."(action='$action/$action_id',called_as='$called_as/$values[referer]',own_referer='$own_referer') values=\n"; _debug_array($values); |
||
| 838 | if (!is_array($values)) |
||
| 839 | { |
||
| 840 | $nm = Api\Cache::getSession('infolog', $this->called_by.'session_data'); |
||
| 841 | unset($nm['rows']); |
||
| 842 | if ($values === 'reset_action_view') |
||
| 843 | { |
||
| 844 | $action = ''; |
||
| 845 | $action_id = 0; |
||
| 846 | $action_title = ''; |
||
| 847 | } |
||
| 848 | if($_GET['ajax'] === 'true') |
||
| 849 | { |
||
| 850 | $nm['action'] = ''; |
||
| 851 | $nm['action_id'] = 0; |
||
| 852 | $nm['action_title'] = ''; |
||
| 853 | // check if action-view reset filter and restore it |
||
| 854 | if (($filter = Api\Cache::getSession('infolog', 'filter_reset_from'))) |
||
| 855 | { |
||
| 856 | $nm['filter'] = $filter; |
||
| 857 | Api\Cache::unsetSession('infolog', 'filter_reset_from'); |
||
| 858 | } |
||
| 859 | } |
||
| 860 | $values = array('nm' => $nm); |
||
| 861 | |||
| 862 | if (isset($_GET['filter']) && $_GET['filter'] != 'default' || !isset($values['nm']['filter']) && !$this->called_by) |
||
| 863 | { |
||
| 864 | $values['nm']['filter'] = $_GET['filter'] && $_GET['filter'] != 'default' ? $_GET['filter'] : |
||
| 865 | $this->prefs['defaultFilter']; |
||
| 866 | } |
||
| 867 | if (!isset($values['nm']['order']) || !$values['nm']['order']) |
||
| 868 | { |
||
| 869 | $values['nm']['order'] = 'info_datemodified'; |
||
| 870 | $values['nm']['sort'] = 'DESC'; |
||
| 871 | } |
||
| 872 | |||
| 873 | if (!$values['nm']['session_for'] && $this->called_by) $values['nm']['session_for'] = $this->called_by; |
||
| 874 | |||
| 875 | $action_id = $values['action_id'] = $action ? $action_id : $nm['action_id']; |
||
| 876 | $action_title = $values['action_title'] = $action ? $action_title : $nm['action_title']; |
||
| 877 | $action = $values['action'] = $action ? $action : $nm['action']; |
||
| 878 | } |
||
| 879 | if($_GET['search']) $values['nm']['search'] = $_GET['search']; |
||
| 880 | |||
| 881 | if ($values['nm']['add']) |
||
| 882 | { |
||
| 883 | $values['add'] = $values['nm']['add']; |
||
| 884 | unset($values['nm']['add']); |
||
| 885 | } |
||
| 886 | unset($values['nm']['rows']['checked']); // not longer used, but hides button actions |
||
| 887 | |||
| 888 | switch ($action) |
||
| 889 | { |
||
| 890 | case 'sp': |
||
| 891 | if (!is_array($action_id) && strpos($action_id, 'infolog:') === 0) $action_id = (int)substr($action_id, 8); |
||
| 892 | if ((is_array($action_id) && !$this->bo->read(current($action_id))) || !$this->bo->read($action_id)) |
||
| 893 | { |
||
| 894 | $action = ''; |
||
| 895 | $action_id = 0; |
||
| 896 | break; |
||
| 897 | } |
||
| 898 | else |
||
| 899 | { |
||
| 900 | $values['nm']['col_filter']['info_id_parent'] = $action_id; |
||
| 901 | } |
||
| 902 | break; |
||
| 903 | default: |
||
| 904 | // Nothing |
||
| 905 | } |
||
| 906 | $readonlys['cancel'] = $action != 'sp'; |
||
| 907 | |||
| 908 | $this->tmpl->read('infolog.index'); |
||
| 909 | $values['nm']['options-filter'] = $this->filters; |
||
| 910 | $values['nm']['get_rows'] = 'infolog.infolog_ui.get_rows'; |
||
| 911 | $values['nm']['options-filter2'] = (in_array($this->prefs['show_links'],array('all','no_describtion')) ? array() : array( |
||
| 912 | '' => 'default', |
||
| 913 | )) + array( |
||
| 914 | 'no_describtion' => 'no details', |
||
| 915 | 'all' => 'details', |
||
| 916 | ); |
||
| 917 | |||
| 918 | //apply infolog_filter_change javascript method (hide/show of date filter form) over onchange filter |
||
| 919 | $values['nm']['filter_onchange'] = "app.infolog.filter_change();"; |
||
| 920 | |||
| 921 | //apply infolog_filter2_change javascript method (show/hide details each rows) over onchange filter2 |
||
| 922 | $values['nm']['filter2_onchange'] = "return app.infolog.filter2_change(ev, widget)"; |
||
| 923 | |||
| 924 | // disable favories dropdown button, if not running as infolog |
||
| 925 | if ($called_as && $called_as != 'infolog') |
||
| 926 | { |
||
| 927 | $values['nm']['favorites'] = false; |
||
| 928 | } |
||
| 929 | else |
||
| 930 | { |
||
| 931 | // Allow saving parent ID into favorites |
||
| 932 | $values['nm']['favorites'] = array('action','action_id'); |
||
| 933 | } |
||
| 934 | |||
| 935 | // Allow add actions even when there's no rows |
||
| 936 | $values['nm']['placeholder_actions'] = array('new'); |
||
| 937 | |||
| 938 | if(!isset($values['nm']['filter2'])) $values['nm']['filter2'] = $this->prefs['nextmatch-'.($action ? 'infolog.'.$action : 'infolog.index.rows').'-details-pref']; |
||
| 939 | |||
| 940 | // disable columns for main entry as set in the pref for details or no details |
||
| 941 | $values['nm']['columnselection_pref'] = 'nextmatch-'.($action ? 'infolog.'.$action : 'infolog.index.rows') |
||
| 942 | .($values['nm']['filter2']=='all' ? '-details' : ''); |
||
| 943 | if ($action == 'sp') |
||
| 944 | { |
||
| 945 | $pref = $values['nm']['columnselection_pref']; |
||
| 946 | foreach(array('info_used_time_info_planned_time_info_replanned_time','info_datemodified','info_owner_info_responsible','customfields') as $name) |
||
| 947 | { |
||
| 948 | $values['main']['no_'.$name] = strpos($this->prefs[$pref],$name) === false; |
||
| 949 | } |
||
| 950 | if (!$values['main']['no_customfields']) |
||
| 951 | { |
||
| 952 | // set the column-header of the main table for the customfields. |
||
| 953 | foreach(array_keys($this->bo->customfields) as $lname) |
||
| 954 | { |
||
| 955 | $values['main']['customfields'].=$lname."\n"; |
||
| 956 | } |
||
| 957 | } |
||
| 958 | } |
||
| 959 | if ($values['nm']['filter']=='bydate') |
||
| 960 | { |
||
| 961 | foreach (array_keys($values['nm']['col_filter']) as $colfk) |
||
| 962 | { |
||
| 963 | if (is_int($colfk)) unset($values['nm']['col_filter']); |
||
| 964 | } |
||
| 965 | } |
||
| 966 | $values['action'] = $persist['action'] = $values['nm']['action'] = $action; |
||
| 967 | $values['action_id'] = $persist['action_id'] = $values['nm']['action_id'] = $action_id; |
||
| 968 | $values['action_title'] = $persist['action_title'] = $values['nm']['action_title'] = $action_title; |
||
| 969 | $values['duration_format'] = ','.$this->duration_format; |
||
| 970 | $persist['called_as'] = $called_as; |
||
| 971 | $persist['own_referer'] = $own_referer; |
||
| 972 | |||
| 973 | // store whole $values[nm] in etemplate request |
||
| 974 | unset($values['nm']['rows']); |
||
| 975 | $persist['nm'] = $values['nm']; |
||
| 976 | |||
| 977 | if (!$called_as) |
||
| 978 | { |
||
| 979 | $GLOBALS['egw_info']['flags']['params']['manual'] = array('page' => 'ManualInfologIndex'); |
||
| 980 | } |
||
| 981 | else |
||
| 982 | { |
||
| 983 | $values['css'] = '<style type="text/css">@import url('.$GLOBALS['egw_info']['server']['webserver_url'].'/infolog/templates/default/app.css);'."</style>"; |
||
| 984 | // Avoid DOM conflicts |
||
| 985 | $this->tmpl->set_dom_id("{$this->tmpl->name}-$action-$action_id"); |
||
| 986 | } |
||
| 987 | // add scrollbar to long description, if user choose so in his prefs |
||
| 988 | if ($this->prefs['limit_des_lines'] > 0 || (string)$this->prefs['limit_des_lines'] == '') |
||
| 989 | { |
||
| 990 | $values['css'] .= '<style type="text/css">@media screen { .infoDes { '. |
||
| 991 | ' max-height: '. |
||
| 992 | (($this->prefs['limit_des_lines'] ? $this->prefs['limit_des_lines'] : 5) * 1.35). // dono why em is not real lines |
||
| 993 | 'em; overflow: auto; }}</style>'; |
||
| 994 | } |
||
| 995 | |||
| 996 | $sel_options = array( |
||
| 997 | 'info_type' => $this->bo->enums['type'], |
||
| 998 | 'pm_id' => array(lang('No project')), |
||
| 999 | 'info_priority' => $this->bo->enums['priority'], |
||
| 1000 | ); |
||
| 1001 | |||
| 1002 | // remove group-types user has not any rights to as filter |
||
| 1003 | // does not take implicit rights as delegated into account, so they will not be available as filters |
||
| 1004 | foreach($this->bo->group_owners as $type => $group) |
||
| 1005 | { |
||
| 1006 | if (!isset($this->bo->grants[$group])) unset($sel_options['info_type'][$type]); |
||
| 1007 | } |
||
| 1008 | |||
| 1009 | |||
| 1010 | return $this->tmpl->exec('infolog.infolog_ui.index',$values,$sel_options,$readonlys,$persist,$return_html ? -1 : 0); |
||
| 1011 | } |
||
| 1012 | |||
| 1013 | /** |
||
| 1014 | * Get valid types |
||
| 1015 | * |
||
| 1016 | * @return array - array of valid types |
||
| 1017 | */ |
||
| 1018 | private function get_validtypes() |
||
| 1034 | } |
||
| 1035 | |||
| 1036 | /** |
||
| 1037 | * Get actions / context menu items |
||
| 1038 | * |
||
| 1039 | * @param array $query |
||
| 1040 | * @return array see nextmatch_widget::get_actions() |
||
| 1041 | */ |
||
| 1042 | private function get_actions(array $query) |
||
| 1043 | { |
||
| 1044 | for($i = 0; $i <= 100; $i += 10) |
||
| 1045 | { |
||
| 1046 | $percent[$i] = $i.'%'; |
||
| 1047 | } |
||
| 1048 | // Types |
||
| 1049 | $types = $this->get_validtypes(); |
||
| 1050 | $types_add = array(); |
||
| 1051 | // Do not add deleted type to add or change menus |
||
| 1052 | unset($types['delete']); |
||
| 1053 | foreach($types as $type => &$data) |
||
| 1054 | { |
||
| 1055 | $image_exists = Api\Image::find('infolog',$type); |
||
| 1056 | $data = array( |
||
| 1057 | 'caption' => $data, |
||
| 1058 | 'icon' => $image_exists ? $type : 'infolog/navbar', |
||
| 1059 | ); |
||
| 1060 | $types_add[$type] = $data + array( |
||
| 1061 | 'onExecute' => "javaScript:app.infolog.add_action_handler" |
||
| 1062 | ); |
||
| 1063 | } |
||
| 1064 | |||
| 1065 | $icons = null; |
||
| 1066 | $statis = $this->bo->get_status($query['col_filter']['info_type'], $icons); |
||
| 1067 | foreach($statis as $type => &$data) |
||
| 1068 | { |
||
| 1069 | $image_exists = Api\Image::find('infolog',$icons[$type]); |
||
| 1070 | $data = array( |
||
| 1071 | 'caption' => $data, |
||
| 1072 | 'icon' => $image_exists ? $icons[$type] : 'infolog/status', |
||
| 1073 | ); |
||
| 1074 | } |
||
| 1075 | |||
| 1076 | $actions = array( |
||
| 1077 | 'open' => array( |
||
| 1078 | 'caption' => 'Open', |
||
| 1079 | 'default' => true, |
||
| 1080 | 'allowOnMultiple' => false, |
||
| 1081 | 'onExecute' => Api\Header\UserAgent::mobile()?'javaScript:app.infolog.viewEntry':'', |
||
| 1082 | 'url' => 'menuaction=infolog.infolog_ui.edit&info_id=$id', |
||
| 1083 | 'popup' => Link::get_registry('infolog', 'add_popup'), |
||
| 1084 | 'group' => $group=1, |
||
| 1085 | 'mobileViewTemplate' => 'view?'.filemtime(Api\Etemplate\Widget\Template::rel2path('/infolog/templates/mobile/view.xet')) |
||
| 1086 | ), |
||
| 1087 | 'parent' => array( |
||
| 1088 | 'caption' => 'View parent with children', |
||
| 1089 | 'icon' => 'up.grey', |
||
| 1090 | 'allowOnMultiple' => false, |
||
| 1091 | 'enabled' => 'javaScript:app.infolog.has_parent', |
||
| 1092 | 'onExecute' => 'javaScript:app.infolog.view_parent', |
||
| 1093 | 'group' => $group, |
||
| 1094 | 'hideOnMobile' => true |
||
| 1095 | ), |
||
| 1096 | 'add' => array( |
||
| 1097 | 'caption' => 'Add', |
||
| 1098 | 'group' => $group, |
||
| 1099 | 'children' => array( |
||
| 1100 | 'new' => array( |
||
| 1101 | 'caption' => 'New', |
||
| 1102 | 'children' => $types_add, |
||
| 1103 | 'icon' => 'task', |
||
| 1104 | ), |
||
| 1105 | 'sub' => array( |
||
| 1106 | 'caption' => 'Sub-entry', |
||
| 1107 | 'url' => 'menuaction=infolog.infolog_ui.edit&action=sp&action_id=$id', |
||
| 1108 | 'popup' => Link::get_registry('infolog', 'add_popup'), |
||
| 1109 | 'allowOnMultiple' => false, |
||
| 1110 | 'hint' => 'Add a new sub-task, -note, -call to this entry', |
||
| 1111 | 'icon' => 'new', |
||
| 1112 | ), |
||
| 1113 | 'copy' => array( |
||
| 1114 | 'caption' => 'Copy', |
||
| 1115 | 'url' => 'menuaction=infolog.infolog_ui.edit&action=copy&info_id=$id', |
||
| 1116 | 'popup' => Link::get_registry('infolog', 'add_popup'), |
||
| 1117 | 'allowOnMultiple' => false, |
||
| 1118 | 'icon' => 'copy', |
||
| 1119 | ), |
||
| 1120 | ), |
||
| 1121 | 'hideOnMobile' => true |
||
| 1122 | ), |
||
| 1123 | 'no_notifications' => array( |
||
| 1124 | 'caption' => 'Do not notify', |
||
| 1125 | 'checkbox' => true, |
||
| 1126 | 'confirm_mass_selection' => "You are going to change %1 entries: Are you sure you want to send notifications about this change?", |
||
| 1127 | 'hint' => 'Do not notify of these changes', |
||
| 1128 | 'group' => $group, |
||
| 1129 | ), |
||
| 1130 | // modifying content of one or multiple infolog(s) |
||
| 1131 | 'change' => array( |
||
| 1132 | 'caption' => 'Change', |
||
| 1133 | 'group' => ++$group, |
||
| 1134 | 'icon' => 'edit', |
||
| 1135 | 'disableClass' => 'rowNoEdit', |
||
| 1136 | 'confirm_mass_selection' => true, |
||
| 1137 | 'children' => array( |
||
| 1138 | 'type' => array( |
||
| 1139 | 'caption' => 'Type', |
||
| 1140 | 'prefix' => 'type_', |
||
| 1141 | 'children' => $types, |
||
| 1142 | 'group' => $group, |
||
| 1143 | 'icon' => 'task', |
||
| 1144 | ), |
||
| 1145 | 'status' => array( |
||
| 1146 | 'caption' => 'Status', |
||
| 1147 | 'prefix' => 'status_', |
||
| 1148 | 'children' => $statis, |
||
| 1149 | 'group' => $group, |
||
| 1150 | 'icon' => 'ongoing', |
||
| 1151 | ), |
||
| 1152 | 'completion' => array( |
||
| 1153 | 'caption' => 'Completed', |
||
| 1154 | 'prefix' => 'completion_', |
||
| 1155 | 'children' => $percent, |
||
| 1156 | 'group' => $group, |
||
| 1157 | 'icon' => 'completed', |
||
| 1158 | ), |
||
| 1159 | 'cat' => Etemplate\Widget\Nextmatch::category_action( |
||
| 1160 | 'infolog',$group,'Change category','cat_' |
||
| 1161 | ), |
||
| 1162 | 'startdate' => array( |
||
| 1163 | 'caption' => 'Start date', |
||
| 1164 | 'group' => $group, |
||
| 1165 | 'nm_action' => 'open_popup', |
||
| 1166 | ), |
||
| 1167 | 'enddate' => array( |
||
| 1168 | 'caption' => 'Due date', |
||
| 1169 | 'group' => $group, |
||
| 1170 | 'nm_action' => 'open_popup', |
||
| 1171 | ), |
||
| 1172 | 'responsible' => array( |
||
| 1173 | 'caption' => 'Delegation', |
||
| 1174 | 'group' => $group, |
||
| 1175 | 'icon' => 'users', |
||
| 1176 | 'nm_action' => 'open_popup', |
||
| 1177 | 'onExecute' => 'javaScript:app.infolog.change_responsible' |
||
| 1178 | ), |
||
| 1179 | 'link' => array( |
||
| 1180 | 'caption' => 'Links', |
||
| 1181 | 'group' => $group, |
||
| 1182 | 'nm_action' => 'open_popup', |
||
| 1183 | ), |
||
| 1184 | ), |
||
| 1185 | 'hideOnMobile' => true |
||
| 1186 | ), |
||
| 1187 | 'close' => array( |
||
| 1188 | 'caption' => 'Close', |
||
| 1189 | 'icon' => 'done', |
||
| 1190 | 'group' => $group, |
||
| 1191 | 'disableClass' => 'rowNoClose', |
||
| 1192 | 'confirm_mass_selection' => true, |
||
| 1193 | ), |
||
| 1194 | 'close_all' => array( |
||
| 1195 | 'caption' => 'Close all', |
||
| 1196 | 'icon' => 'done_all', |
||
| 1197 | 'group' => $group, |
||
| 1198 | 'hint' => 'Sets the status of this entry and its subs to done', |
||
| 1199 | 'allowOnMultiple' => false, |
||
| 1200 | 'disableClass' => 'rowNoCloseAll', |
||
| 1201 | 'confirm_mass_selection' => true, |
||
| 1202 | ), |
||
| 1203 | 'print' => array( |
||
| 1204 | 'caption' => 'Print', |
||
| 1205 | 'icon' => 'print', |
||
| 1206 | 'group' => $group, |
||
| 1207 | 'onExecute' => 'javaScript:app.infolog.infolog_menu_print' |
||
| 1208 | ) |
||
| 1209 | ); |
||
| 1210 | ++$group; // integration with other apps |
||
| 1211 | if ($GLOBALS['egw_info']['user']['apps']['filemanager']) |
||
| 1212 | { |
||
| 1213 | $actions['filemanager'] = array( |
||
| 1214 | 'icon' => 'filemanager/navbar', |
||
| 1215 | 'caption' => 'Filemanager', |
||
| 1216 | 'url' => 'menuaction=filemanager.filemanager_ui.index&path=/apps/infolog/$id&ajax=true', |
||
| 1217 | 'allowOnMultiple' => false, |
||
| 1218 | 'group' => $group, |
||
| 1219 | ); |
||
| 1220 | } |
||
| 1221 | if ($GLOBALS['egw_info']['user']['apps']['calendar']) |
||
| 1222 | { |
||
| 1223 | $actions['calendar'] = array( // interactive add for a single event |
||
| 1224 | 'icon' => 'calendar/navbar', |
||
| 1225 | 'caption' => 'Schedule appointment', |
||
| 1226 | 'group' => $group, |
||
| 1227 | 'url' => 'menuaction=calendar.calendar_uiforms.edit&'. |
||
| 1228 | Link::get_registry('calendar', 'add_app') . '[]=infolog&'.Link::get_registry('calendar','add_id').'[]=$id', |
||
| 1229 | 'allowOnMultiple' => false, |
||
| 1230 | 'popup' => Link::get_registry('calendar', 'edit_popup') |
||
| 1231 | ); |
||
| 1232 | } |
||
| 1233 | if ($GLOBALS['egw_info']['user']['apps']['timesheet']) |
||
| 1234 | { |
||
| 1235 | $actions['timesheet'] = array( // interactive add for a single event |
||
| 1236 | 'icon' => 'timesheet/navbar', |
||
| 1237 | 'caption' => 'Timesheet', |
||
| 1238 | 'group' => $group, |
||
| 1239 | 'allowOnMultiple' => false, |
||
| 1240 | |||
| 1241 | 'children' => array( |
||
| 1242 | 'timesheet_list' => array( |
||
| 1243 | 'caption' => lang('View linked %1 entries', lang('timesheet')), |
||
| 1244 | 'icon' => 'infolog/navbar', |
||
| 1245 | 'onExecute' => 'javaScript:app.infolog.timesheet_list', |
||
| 1246 | 'allowOnMultiple' => false, |
||
| 1247 | 'hideOnDisabled' => true, |
||
| 1248 | ), |
||
| 1249 | 'timesheet_add' => array( |
||
| 1250 | 'icon' => 'timesheet/navbar', |
||
| 1251 | 'caption' => 'Add timesheet entry', |
||
| 1252 | 'url' => 'menuaction=timesheet.timesheet_ui.edit&link_app[]=infolog&link_id[]=$id', |
||
| 1253 | 'popup' => Link::get_registry('timesheet', 'add_popup'), |
||
| 1254 | ) |
||
| 1255 | ) |
||
| 1256 | ); |
||
| 1257 | } |
||
| 1258 | if ($GLOBALS['egw_info']['user']['apps']['tracker']) |
||
| 1259 | { |
||
| 1260 | $actions['to_tracker'] = array( |
||
| 1261 | 'icon' => 'tracker/navbar', |
||
| 1262 | 'caption' => 'Tracker', |
||
| 1263 | 'hint' => 'Convert to a ticket', |
||
| 1264 | 'group' => $group, |
||
| 1265 | 'url' => 'menuaction=tracker.tracker_ui.edit&'. |
||
| 1266 | Link::get_registry('tracker', 'add_app') . '[]=infolog&'.Link::get_registry('tracker','add_id').'[]=$id', |
||
| 1267 | 'allowOnMultiple' => false, |
||
| 1268 | 'popup' => Link::get_registry('tracker', 'add_popup'), |
||
| 1269 | ); |
||
| 1270 | } |
||
| 1271 | |||
| 1272 | $actions['documents'] = infolog_merge::document_action( |
||
| 1273 | $this->prefs['document_dir'], ++$group, 'Insert in document', 'document_', |
||
| 1274 | $this->prefs['default_document'] |
||
| 1275 | ); |
||
| 1276 | $actions['ical'] = array( |
||
| 1277 | 'icon' => 'ical', |
||
| 1278 | 'caption' => 'Export iCal', |
||
| 1279 | 'postSubmit' => true, // download needs post submit to work |
||
| 1280 | 'group' => $group, |
||
| 1281 | 'allowOnMultiple' => true, |
||
| 1282 | 'hideOnMobile' => true |
||
| 1283 | ); |
||
| 1284 | |||
| 1285 | $actions['delete'] = array( |
||
| 1286 | 'caption' => 'Delete', |
||
| 1287 | 'group' => ++$group, |
||
| 1288 | 'disableClass' => 'rowNoDelete', |
||
| 1289 | 'onExecute' => 'javaScript:app.infolog.confirm_delete', |
||
| 1290 | 'confirm_mass_selection' => true, |
||
| 1291 | ); |
||
| 1292 | if ($query['col_filter']['info_status'] == 'deleted') |
||
| 1293 | { |
||
| 1294 | $actions['undelete'] = array( |
||
| 1295 | 'caption' => 'Un-Delete', |
||
| 1296 | 'group' => $group, |
||
| 1297 | 'icon' => 'revert', |
||
| 1298 | 'disableClass' => 'rowNoUndelete', |
||
| 1299 | 'confirm_mass_selection' => true, |
||
| 1300 | ); |
||
| 1301 | } |
||
| 1302 | $actions['info_drop_mail'] = array( |
||
| 1303 | 'type' => 'drop', |
||
| 1304 | 'caption' => 'Link mail', |
||
| 1305 | 'acceptedTypes' => 'mail', |
||
| 1306 | 'onExecute' => 'javaScript:app.infolog.handle_dropped_mail', |
||
| 1307 | 'hideOnDisabled' => true |
||
| 1308 | ); |
||
| 1309 | //echo "<p>".__METHOD__."($do_email, $tid_filter, $org_view)</p>\n"; _debug_array($actions); |
||
| 1310 | return $actions; |
||
| 1311 | } |
||
| 1312 | |||
| 1313 | /** |
||
| 1314 | * Handles actions on multiple infologs |
||
| 1315 | * |
||
| 1316 | * @param string $_action |
||
| 1317 | * @param array $checked contact id's to use if !$use_all |
||
| 1318 | * @param boolean $use_all if true use all entries of the current selection (in the session) |
||
| 1319 | * @param int &$success number of succeded actions |
||
| 1320 | * @param int &$failed number of failed actions (not enought permissions) |
||
| 1321 | * @param string &$action_msg translated verb for the actions, to be used in a message like '%1 entries deleted' |
||
| 1322 | * @param array $query get_rows parameter |
||
| 1323 | * @param string &$msg on return user feedback |
||
| 1324 | * @param boolean $skip_notifications true to NOT notify users about changes |
||
| 1325 | * @return boolean true if all actions succeded, false otherwise |
||
| 1326 | */ |
||
| 1327 | function action($_action, $checked, $use_all, &$success, &$failed, &$action_msg, |
||
| 1580 | } |
||
| 1581 | |||
| 1582 | /** |
||
| 1583 | * Closes an infolog |
||
| 1584 | * |
||
| 1585 | * @param int|array $values=0 info_id (default _GET[info_id]) |
||
| 1586 | * @param string $_referer='' |
||
| 1587 | * @param boolean $closesingle=false |
||
| 1588 | */ |
||
| 1589 | function close($values=0,$_referer='',$closesingle=false,$skip_notification = false) |
||
| 1630 | } |
||
| 1631 | |||
| 1632 | /** |
||
| 1633 | * Deletes an InfoLog entry |
||
| 1634 | * |
||
| 1635 | * @param array|int $values info_id (default _GET[info_id]) |
||
| 1636 | * @param string $_referer |
||
| 1637 | * @param string $called_by |
||
| 1638 | * @param boolean $skip_notification Do not send notification of deletion |
||
| 1639 | */ |
||
| 1640 | function delete($values=0,$_referer='',$called_by='',$skip_notification=False) |
||
| 1641 | { |
||
| 1642 | $info_id = (int) (is_array($values) ? $values['info_id'] : ($values ? $values : $_GET['info_id'])); |
||
| 1643 | $referer = is_array($values) ? $values['referer'] : $_referer; |
||
| 1644 | |||
| 1645 | if (!is_array($values) && $info_id > 0 && !$this->bo->anzSubs($info_id)) // entries without subs get confirmed by javascript |
||
| 1646 | { |
||
| 1647 | $values = array('delete' => true); |
||
| 1648 | } |
||
| 1649 | //echo "<p>infolog_ui::delete(".print_r($values,true).",'$referer','$called_by') info_id=$info_id</p>\n"; |
||
| 1650 | |||
| 1651 | if (is_array($values) || $info_id <= 0) |
||
| 1652 | { |
||
| 1653 | if (($values['delete'] || $values['delete_subs']) && $info_id > 0 && $this->bo->check_access($info_id,Acl::DELETE)) |
||
| 1654 | { |
||
| 1655 | $deleted = $this->bo->delete($info_id,$values['delete_subs'],$values['info_id_parent'], $skip_notification); |
||
| 1656 | } |
||
| 1657 | if ($called_by) // direct call from the same request |
||
| 1658 | { |
||
| 1659 | return $deleted ? lang('InfoLog entry deleted') : ''; |
||
| 1660 | } |
||
| 1661 | if ($values['called_by'] == 'edit') // we run in the edit popup => give control back to edit |
||
| 1662 | { |
||
| 1663 | $this->edit(array( |
||
| 1664 | 'info_id' => $info_id, |
||
| 1665 | 'button' => array('deleted' => true), // not delete! |
||
| 1666 | 'referer' => $referer, |
||
| 1667 | 'msg' => $deleted ? lang('Infolog entry deleted') : '', |
||
| 1668 | )); |
||
| 1669 | } |
||
| 1670 | return $referer ? $this->tmpl->location($referer) : $this->index(); |
||
| 1671 | } |
||
| 1672 | $readonlys = $values = array(); |
||
| 1673 | $values['main'][1] = $this->get_info($info_id,$readonlys['main']); |
||
| 1674 | |||
| 1675 | $this->tmpl->read('infolog.delete'); |
||
| 1676 | |||
| 1677 | $values['nm'] = array( |
||
| 1678 | 'action' => 'sp', |
||
| 1679 | 'action_id' => $info_id, |
||
| 1680 | 'options-filter' => $this->filters, |
||
| 1681 | 'get_rows' => 'infolog.infolog_ui.get_rows', |
||
| 1682 | 'no_filter2' => True |
||
| 1683 | ); |
||
| 1684 | $values['main']['no_actions'] = $values['nm']['no_actions'] = True; |
||
| 1685 | |||
| 1686 | $persist['info_id'] = $info_id; |
||
| 1687 | $persist['referer'] = $referer; |
||
| 1688 | $persist['info_id_parent'] = $values['main'][1]['info_id_parent']; |
||
| 1689 | $persist['called_by'] = $called_by; |
||
| 1690 | |||
| 1691 | $GLOBALS['egw_info']['flags']['app_header'] = lang('InfoLog').' - '.lang('Delete'); |
||
| 1692 | $GLOBALS['egw_info']['flags']['params']['manual'] = array('page' => 'ManualInfologDelete'); |
||
| 1693 | |||
| 1694 | $this->tmpl->exec('infolog.infolog_ui.delete',$values,array(),$readonlys,$persist,$called_by == 'edit' ? 2 : 0); |
||
| 1695 | } |
||
| 1696 | |||
| 1697 | /** |
||
| 1698 | * Edit/Create an InfoLog Entry |
||
| 1699 | * |
||
| 1700 | * @param array $content Content from the eTemplate Exec call or info_id on inital call |
||
| 1701 | * @param string $action Name of an app of 'sp' for a infolog-sub |
||
| 1702 | * @param int $action_id of app-entry to which a link is created |
||
| 1703 | * @param string $type Type of log-entry: note,todo,task |
||
| 1704 | * @param string $referer array with param/get-vars of the refering page |
||
| 1705 | */ |
||
| 1706 | function edit($content = null,$action = '',$action_id=0,$type='',$referer='') |
||
| 1707 | { |
||
| 1708 | if (($submit = is_array($content))) |
||
| 1709 | { |
||
| 1710 | //echo "infolog_ui::edit: content="; _debug_array($content); |
||
| 1711 | $info_id = $content['info_id']; |
||
| 1712 | $action = $content['action']; unset($content['action']); |
||
| 1713 | $action_id = $content['action_id']; unset($content['action_id']); |
||
| 1714 | $referer = $content['referer']; unset($content['referer']); |
||
| 1715 | $no_popup = $content['no_popup']; unset($content['no_popup']); |
||
| 1716 | |||
| 1717 | $button = @key($content['button']); |
||
| 1718 | if (!$button && $action) $button = $action; // action selectbox |
||
| 1719 | //info_cc expects an comma separated string |
||
| 1720 | //error_log(__METHOD__.__LINE__.array2string($content)); |
||
| 1721 | if (empty($content['info_cc'])) $content['info_cc'] = ""; |
||
| 1722 | if (is_array($content['info_cc'])) |
||
| 1723 | { |
||
| 1724 | foreach($content['info_cc'] as $i => $value) |
||
| 1725 | { |
||
| 1726 | //imap_rfc822 should not be used, but it works reliable here, until we have some regex solution or use horde stuff |
||
| 1727 | $addresses = imap_rfc822_parse_adrlist($value, ''); |
||
| 1728 | //error_log(__METHOD__.__LINE__.$value.'->'.array2string($addresses[0])); |
||
| 1729 | $content['info_cc'][$i]=$addresses[0]->host ? $addresses[0]->mailbox.'@'.$addresses[0]->host : $addresses[0]->mailbox; |
||
| 1730 | } |
||
| 1731 | if (!empty($content['info_cc'])) $content['info_cc'] = implode(',',$content['info_cc']); |
||
| 1732 | } |
||
| 1733 | unset($content['button']); |
||
| 1734 | if ($button) |
||
| 1735 | { |
||
| 1736 | // Copy or schedule Infolog |
||
| 1737 | if (in_array($button,array('copy','schedule','ical','tracker'))) |
||
| 1738 | { |
||
| 1739 | $action = $button; |
||
| 1740 | if (!$info_id || $this->bo->check_access($info_id,Acl::EDIT)) |
||
| 1741 | { |
||
| 1742 | $button = 'apply'; // need to store infolog first |
||
| 1743 | } |
||
| 1744 | } |
||
| 1745 | //Validate the enddate must be grather than startdate |
||
| 1746 | if (!empty($content['info_enddate']) && !empty($content['info_startdate'])) |
||
| 1747 | { |
||
| 1748 | $duration_date = $content['info_enddate']-$content['info_startdate']; |
||
| 1749 | if ($duration_date < 0) |
||
| 1750 | { |
||
| 1751 | $this->tmpl->set_validation_error('info_startdate', lang('Startdate must be before Enddate!!!')); |
||
| 1752 | $button = $action = ''; // stop save or apply |
||
| 1753 | } |
||
| 1754 | } |
||
| 1755 | //echo "<p>infolog_ui::edit(info_id=$info_id) '$button' button pressed, content="; _debug_array($content); |
||
| 1756 | if (($button == 'save' || $button == 'apply') && isset($content['info_subject']) && empty($content['info_subject'])) |
||
| 1757 | { |
||
| 1758 | $this->tmpl->set_validation_error('info_subject',lang('Field must not be empty !!!')); |
||
| 1759 | $button = $action = ''; // stop save or apply |
||
| 1760 | } |
||
| 1761 | if (($button == 'save' || $button == 'apply') && $info_id) |
||
| 1762 | { |
||
| 1763 | $old = $this->bo->read($info_id); |
||
| 1764 | if (!($edit_acl = $this->bo->check_access($info_id,Acl::EDIT))) |
||
| 1765 | { |
||
| 1766 | $status_only = $this->bo->is_responsible($old); |
||
| 1767 | $undelete = $this->bo->check_access($old,infolog_bo::ACL_UNDELETE); |
||
| 1768 | } |
||
| 1769 | // enddate in the past gives warning |
||
| 1770 | if (isset($content['info_enddate']) |
||
| 1771 | && $content['info_enddate'] < $this->bo->user_time_now |
||
| 1772 | && !$this->bo->allow_past_due_date && !($content['info_status'] == 'done' |
||
| 1773 | || $content['info_status'] == 'archive')) |
||
| 1774 | { |
||
| 1775 | $this->tmpl->set_validation_error('info_enddate', lang('Due date must be in the future!!!')); |
||
| 1776 | } |
||
| 1777 | } |
||
| 1778 | if (($button == 'save' || $button == 'apply') && (!$info_id || $edit_acl || $status_only || $undelete)) |
||
| 1779 | { |
||
| 1780 | $operation = $info_id ? 'edit' : 'add'; |
||
| 1781 | |||
| 1782 | if (is_array($content['link_to']['to_id']) && count($content['link_to']['to_id'])) |
||
| 1783 | { |
||
| 1784 | $content['info_link_id'] = 0; // as field has to be int |
||
| 1785 | } |
||
| 1786 | $active_tab = $content['tabs']; |
||
| 1787 | if (!($info_id = $this->bo->write($content, true, true, true, $content['no_notifications']))) |
||
| 1788 | { |
||
| 1789 | $content['msg'] = $info_id !== 0 || !$content['info_id'] ? lang('Error: saving the entry') : |
||
| 1790 | lang('Error: the entry has been updated since you opened it for editing!').'<br />'. |
||
| 1791 | lang('Copy your changes to the clipboard, %1reload the entry%2 and merge them.','<a href="'. |
||
| 1792 | htmlspecialchars(Egw::link('/index.php',array( |
||
| 1793 | 'menuaction' => 'infolog.infolog_ui.edit', |
||
| 1794 | 'info_id' => $content['info_id'], |
||
| 1795 | 'no_popup' => $no_popup, |
||
| 1796 | 'referer' => $referer, |
||
| 1797 | ))).'">','</a>'); |
||
| 1798 | $button = $action = ''; // not exiting edit |
||
| 1799 | $info_id = $content['info_id']; |
||
| 1800 | } |
||
| 1801 | else |
||
| 1802 | { |
||
| 1803 | $GLOBALS['egw']->preferences->add('infolog','preferred_type',$content['info_type']); |
||
| 1804 | $GLOBALS['egw']->preferences->save_repository(false,'user',false); |
||
| 1805 | $content['msg'] = lang('InfoLog entry saved'); |
||
| 1806 | Framework::refresh_opener($content['msg'],'infolog',$info_id,$operation); |
||
| 1807 | } |
||
| 1808 | $content['tabs'] = $active_tab; |
||
| 1809 | |||
| 1810 | $pm_links = Link::get_links('infolog',$content['info_id'],'projectmanager'); |
||
| 1811 | |||
| 1812 | $content['link_to']['to_app'] = 'infolog'; |
||
| 1813 | $content['link_to']['to_id'] = $info_id; |
||
| 1814 | |||
| 1815 | if ($info_link_id && strpos($info_link_id,':') !== false) // updating info_link_id if necessary |
||
| 1816 | { |
||
| 1817 | list($app,$id) = explode(':',$info_link_id); |
||
| 1818 | $link = Link::get_link('infolog',$info_id,$app,$id); |
||
| 1819 | if ((int) $content['info_link_id'] != (int) $link['link_id']) |
||
| 1820 | { |
||
| 1821 | $content['info_link_id'] = $link['link_id']; |
||
| 1822 | |||
| 1823 | $to_write = array( |
||
| 1824 | 'info_id' => $content['info_id'], |
||
| 1825 | 'info_link_id' => $content['info_link_id'], |
||
| 1826 | 'info_from' => $content['info_from'], |
||
| 1827 | 'info_type' => $content['info_type'], |
||
| 1828 | 'info_owner' => $content['info_owner'], |
||
| 1829 | ); |
||
| 1830 | //echo "<p>updating info_link_id: ".print_r($to_write,true)."</p>\n"; |
||
| 1831 | $this->bo->write($to_write,False,true,true,true); // last true = no notifications, as no real change |
||
| 1832 | |||
| 1833 | // Do not override info_contact if is already filled with contact |
||
| 1834 | if ($content['info_contact']) |
||
| 1835 | { |
||
| 1836 | unset($to_write['info_contact']); |
||
| 1837 | unset($to_write['blur_title']); |
||
| 1838 | } |
||
| 1839 | |||
| 1840 | // we need eg. the new modification date, for further updates |
||
| 1841 | $content = array_merge($content,$to_write); |
||
| 1842 | } |
||
| 1843 | } |
||
| 1844 | |||
| 1845 | // Need to purge description history after encryption? |
||
| 1846 | if($content['clean_history']) |
||
| 1847 | { |
||
| 1848 | $history = new Api\Storage\History('infolog'); |
||
| 1849 | $record_count = $history->delete_field($info_id, 'De'); |
||
| 1850 | } |
||
| 1851 | } |
||
| 1852 | elseif ($button == 'delete' && $info_id > 0) |
||
| 1853 | { |
||
| 1854 | if (!$referer && $action) $referer = array( |
||
| 1855 | 'menuaction' => 'infolog.infolog_ui.index', |
||
| 1856 | 'action' => $action, |
||
| 1857 | 'action_id' => $action_id |
||
| 1858 | ); |
||
| 1859 | if (!($content['msg'] = $this->delete($info_id,$referer,'edit'))) return; // checks ACL first |
||
| 1860 | |||
| 1861 | Framework::refresh_opener($content['msg'],'infolog',$info_id,'delete'); |
||
| 1862 | } |
||
| 1863 | // called again after delete confirmation dialog |
||
| 1864 | elseif ($button == 'deleted' && $content['msg']) |
||
| 1865 | { |
||
| 1866 | Framework::refresh_opener($content['msg'],'infolog',$info_id,'delete'); |
||
| 1867 | } |
||
| 1868 | if ($button == 'save' || $button == 'cancel' || $button == 'delete' || $button == 'deleted') |
||
| 1869 | { |
||
| 1870 | if ($no_popup) |
||
| 1871 | { |
||
| 1872 | Egw::redirect_link($referer,array('msg' => $content['msg'])); |
||
| 1873 | } |
||
| 1874 | Framework::window_close(); |
||
| 1875 | } |
||
| 1876 | } |
||
| 1877 | // on a type-change, set the status to the default status of that type, if the actual status is not supported by the new type |
||
| 1878 | if (!array_key_exists($content['info_status'],$this->bo->status[$content['info_type']])) |
||
| 1879 | { |
||
| 1880 | $content['info_status'] = $this->bo->status['defaults'][$content['info_type']]; |
||
| 1881 | // Make sure we don't end up with invalid status / percent combinations |
||
| 1882 | if ($content['info_status'] != 'done') |
||
| 1883 | { |
||
| 1884 | $content['info_datecompleted'] = ''; |
||
| 1885 | if((int)$content['info_percent'] === 100) |
||
| 1886 | { |
||
| 1887 | $content['info_percent'] = 10; |
||
| 1888 | } |
||
| 1889 | } |
||
| 1890 | else |
||
| 1891 | { |
||
| 1892 | $content['info_percent'] = 100; |
||
| 1893 | } |
||
| 1894 | if($content['info_status'] != 'not-started' && (int)$content['info_percent'] == 0) |
||
| 1895 | { |
||
| 1896 | $content['info_percent'] = 10; |
||
| 1897 | } |
||
| 1898 | } |
||
| 1899 | } |
||
| 1900 | else // new call via GET |
||
| 1901 | { |
||
| 1902 | //echo "<p>infolog_ui::edit: info_id=$info_id, action='$action', action_id='$action_id', type='$type', referer='$referer'</p>\n"; |
||
| 1903 | $action = $action ? $action : $_REQUEST['action']; |
||
| 1904 | $action_id = $action_id ? $action_id : $_REQUEST['action_id']; |
||
| 1905 | $info_id = $content ? $content : $_REQUEST['info_id']; |
||
| 1906 | $type = $type ? $type : $_REQUEST['type']; |
||
| 1907 | $referer = $referer !== '' ? $referer : ($_GET['referer'] ? $_GET['referer'] : |
||
| 1908 | Api\Header\Referer::get('/index.php?menuaction=infolog.infolog_ui.index')); |
||
| 1909 | if (strpos($referer, 'msg=') !== false) $referer = preg_replace('/([&?]{1})msg=[^&]+&?/','\\1',$referer); // remove previou/old msg from referer |
||
| 1910 | $no_popup = $_GET['no_popup']; |
||
| 1911 | $print = (int) $_REQUEST['print']; |
||
| 1912 | //echo "<p>infolog_ui::edit: info_id=$info_id, action='$action', action_id='$action_id', type='$type', referer='$referer'</p>\n"; |
||
| 1913 | |||
| 1914 | if (($content = $this->bo->read( $info_id || $action != 'sp' ? $info_id : $action_id )) === false) |
||
| 1915 | { |
||
| 1916 | Framework::window_close(lang('Permission denied!')); |
||
| 1917 | } |
||
| 1918 | if (is_numeric($_REQUEST['cat_id'])) |
||
| 1919 | { |
||
| 1920 | $content['info_cat'] = (int)$_REQUEST['cat_id']; |
||
| 1921 | } |
||
| 1922 | if (!$content) |
||
| 1923 | { |
||
| 1924 | $content['info_cat'] = $this->prefs['cat_add_default']; |
||
| 1925 | } |
||
| 1926 | if ($_GET['msg']) $content['msg'] = strip_tags($_GET['msg']); // dont allow HTML! |
||
| 1927 | |||
| 1928 | switch($this->prefs['set_start']) |
||
| 1929 | { |
||
| 1930 | case 'date': default: $set_startdate = mktime(0,0,0,date('m',$this->bo->user_time_now),date('d',$this->bo->user_time_now),date('Y',$this->bo->user_time_now)); break; |
||
| 1931 | case 'datetime': $set_startdate = $this->bo->user_time_now; break; |
||
| 1932 | case 'empty': $set_startdate = 0; break; |
||
| 1933 | } |
||
| 1934 | if ((int)$content['info_link_id'] > 0 && !Link::get_link($content['info_link_id'])) |
||
| 1935 | { |
||
| 1936 | $content['info_link_id'] = 0; // link has been deleted |
||
| 1937 | if (!$content['info_custom_link']) $content['info_from'] = ''; |
||
| 1938 | } |
||
| 1939 | if (!$info_id && $action_id && $action == 'sp') // new SubProject |
||
| 1940 | { |
||
| 1941 | if (!$this->bo->check_access($action_id,Acl::ADD)) |
||
| 1942 | { |
||
| 1943 | return $referer ? $this->tmpl->location($referer) : $this->index(0,$action,$action_id); |
||
| 1944 | } |
||
| 1945 | } |
||
| 1946 | else |
||
| 1947 | { |
||
| 1948 | $undelete = $this->bo->check_access($content,infolog_bo::ACL_UNDELETE); |
||
| 1949 | } |
||
| 1950 | $content['links'] = $content['link_to'] = array( |
||
| 1951 | 'to_id' => $info_id, |
||
| 1952 | 'to_app' => 'infolog', |
||
| 1953 | ); |
||
| 1954 | } |
||
| 1955 | // new call via GET or some actions handled here, as they can happen both ways ($_GET[action] or button/action in GUI) |
||
| 1956 | if (!$submit || in_array($action,array('sp','copy','schedule','ical','to_tracker'))) |
||
| 1957 | { |
||
| 1958 | switch ($action) |
||
| 1959 | { |
||
| 1960 | case 'schedule': |
||
| 1961 | Egw::redirect_link('/index.php',array( |
||
| 1962 | 'menuaction' => 'calendar.calendar_uiforms.edit', |
||
| 1963 | 'link_app' => 'infolog', |
||
| 1964 | 'link_id' => $info_id, |
||
| 1965 | )); |
||
| 1966 | break; |
||
| 1967 | case 'ical': |
||
| 1968 | $boical = new infolog_ical(); |
||
| 1969 | $result = $boical->exportVTODO($content,'2.0','PUBLISH',false); |
||
| 1970 | Api\Header\Content::type('todo.ics', 'text/calendar'); |
||
| 1971 | echo $result; |
||
| 1972 | exit(); |
||
| 1973 | case 'sp': |
||
| 1974 | case 'copy': |
||
| 1975 | $info_id = 0; |
||
| 1976 | $this->create_copy($content, $action == 'sp'); |
||
| 1977 | if ($action == 'sp') // for sub-entries use type or category, like for new entries |
||
| 1978 | { |
||
| 1979 | if ($type) $content['info_type'] = $type; |
||
| 1980 | if (is_numeric($_REQUEST['cat_id'])) $content['info_cat'] = (int) $_REQUEST['cat_id']; |
||
| 1981 | } |
||
| 1982 | unset($action); // it get stored in $content and will cause an other copy after [apply] |
||
| 1983 | break; |
||
| 1984 | case 'to_tracker': |
||
| 1985 | Egw::redirect_link('/index.php',array( |
||
| 1986 | 'menuaction' => 'tracker.tracker_ui.edit', |
||
| 1987 | Link::get_registry('tracker', 'add_app').'[]' => 'infolog', |
||
| 1988 | Link::get_registry('tracker','add_id').'[]' => $info_id, |
||
| 1989 | )); |
||
| 1990 | break; |
||
| 1991 | case 'projectmanager': |
||
| 1992 | $content['pm_id'] = $action_id; |
||
| 1993 | default: // to allow other apps to participate |
||
| 1994 | $content['info_subject'] = Link::title($action, $id); |
||
| 1995 | $action_ids = explode(',',$action_id); |
||
| 1996 | if(count($action_ids) == 1) |
||
| 1997 | { |
||
| 1998 | $content['info_contact'] = array('app' => $action, 'id' => $action_id); |
||
| 1999 | } |
||
| 2000 | foreach ($action_ids as $n => $id) |
||
| 2001 | { |
||
| 2002 | Link::link('infolog', $content['link_to']['to_id'], $action, $id); |
||
| 2003 | |||
| 2004 | // calling "infolog_set" hook for first, in case app wants to set some more values |
||
| 2005 | if (!$n && ($set = Api\Hooks::single(array('location'=>'infolog_set','id'=>$action_id),$action))) |
||
| 2006 | { |
||
| 2007 | foreach((array)$set['link_app'] as $i => $l_app) |
||
| 2008 | { |
||
| 2009 | if (($l_id=$set['link_id'][$i])) Link::link('infolog',$content['link_to']['to_id'],$l_app,$l_id); |
||
| 2010 | } |
||
| 2011 | unset($set['link_app']); |
||
| 2012 | unset($set['link_id']); |
||
| 2013 | |||
| 2014 | $content = array_merge($content, $set); |
||
| 2015 | } |
||
| 2016 | } |
||
| 2017 | // fall through |
||
| 2018 | case '': |
||
| 2019 | if ($info_id) |
||
| 2020 | { |
||
| 2021 | if (!isset($pm_links)) |
||
| 2022 | { |
||
| 2023 | $pm_links = Link::get_links('infolog',$info_id,'projectmanager'); |
||
| 2024 | } |
||
| 2025 | break; // normal edit |
||
| 2026 | } |
||
| 2027 | case 'new': // new entry, set some defaults, if not set by infolog_set hook |
||
| 2028 | if (empty($content['info_startdate'])) $content['info_startdate'] = (int) $_GET['startdate'] ? (int) $_GET['startdate'] : $set_startdate; |
||
| 2029 | if (empty($content['info_priority'])) $content['info_priority'] = 1; // normal |
||
| 2030 | $content['info_owner'] = $this->user; |
||
| 2031 | if ($type != '' && empty($content['info_type'])) |
||
| 2032 | { |
||
| 2033 | $content['info_type'] = $type; |
||
| 2034 | } |
||
| 2035 | else if ($type == '' && empty($content['info_type']) && isset($GLOBALS['egw_info']['user']['preferences']['infolog']['preferred_type'])) |
||
| 2036 | { |
||
| 2037 | $content['info_type'] = $GLOBALS['egw_info']['user']['preferences']['infolog']['preferred_type']; |
||
| 2038 | } |
||
| 2039 | if (empty($content['info_status'])) $content['info_status'] = $this->bo->status['defaults'][$content['info_type']]; |
||
| 2040 | if (empty($content['info_percent'])) $content['info_percent'] = $content['info_status'] == 'done' ? '100%' : '0%'; |
||
| 2041 | break; |
||
| 2042 | } |
||
| 2043 | if (!isset($this->bo->enums['type'][$content['info_type']])) |
||
| 2044 | { |
||
| 2045 | $content['info_type'] = 'note'; |
||
| 2046 | } |
||
| 2047 | } |
||
| 2048 | // group owners |
||
| 2049 | $types = $this->bo->enums['type']; |
||
| 2050 | if ($this->bo->group_owners) |
||
| 2051 | { |
||
| 2052 | // remove types owned by groups the user has no edit grant (current type is made readonly) |
||
| 2053 | foreach($this->bo->group_owners as $type => $group) |
||
| 2054 | { |
||
| 2055 | if (!($this->bo->grants[$group] & Acl::EDIT)) |
||
| 2056 | { |
||
| 2057 | if ($type == $content['info_type']) |
||
| 2058 | { |
||
| 2059 | //echo "<p>setting type to r/o as user has no edit rights from group #$group</p>\n"; |
||
| 2060 | $readonlys['info_type'] = true; |
||
| 2061 | } |
||
| 2062 | else |
||
| 2063 | { |
||
| 2064 | unset($types[$type]); |
||
| 2065 | } |
||
| 2066 | } |
||
| 2067 | } |
||
| 2068 | // set group as owner if type has a group-owner set |
||
| 2069 | if (isset($this->bo->group_owners[$content['info_type']])) |
||
| 2070 | { |
||
| 2071 | $content['info_owner'] = $this->bo->group_owners[$content['info_type']]; |
||
| 2072 | // Dont allow to change the type, if user has no delete rights from the group-owner |
||
| 2073 | if ($info_id && !($this->bo->grants[$content['info_owner']] & Acl::DELETE)) |
||
| 2074 | { |
||
| 2075 | //echo "<p>setting type to r/o as user has no delete rights from group #$group</p>\n"; |
||
| 2076 | $readonlys['info_type'] = true; |
||
| 2077 | } |
||
| 2078 | // disable info_access for group-owners |
||
| 2079 | $readonlys['info_access'] = true; |
||
| 2080 | } |
||
| 2081 | elseif($GLOBALS['egw']->accounts->get_type($content['info_owner']) == 'g') |
||
| 2082 | { |
||
| 2083 | $content['info_owner'] = $this->user; |
||
| 2084 | } |
||
| 2085 | } |
||
| 2086 | $preserv = $content; |
||
| 2087 | |||
| 2088 | // Don't preserve message or links |
||
| 2089 | unset($preserv['msg']); |
||
| 2090 | unset($preserv['links']); unset($preserv['link_to']); |
||
| 2091 | |||
| 2092 | // for no edit rights or implizit edit of responsible user make all fields readonly, but status and percent |
||
| 2093 | if ($info_id && !$this->bo->check_access($content, Acl::EDIT) && !$undelete) |
||
| 2094 | { |
||
| 2095 | $readonlys['__ALL__'] = true; // make all fields not explicitly set readonly |
||
| 2096 | if ($this->bo->is_responsible($content)) |
||
| 2097 | { |
||
| 2098 | foreach($this->bo->responsible_edit as $name) |
||
| 2099 | { |
||
| 2100 | $readonlys[$name] = false; |
||
| 2101 | } |
||
| 2102 | $readonlys['timestamp'] = $readonlys['info_des']; |
||
| 2103 | $readonlys['button[edit]'] = $readonlys['button[save]'] = $readonlys['button[apply]'] = $readonlys['no_notifications'] = false; |
||
| 2104 | } |
||
| 2105 | $readonlys['action'] = $readonlys['button[cancel]'] = false; // always allowed |
||
| 2106 | } |
||
| 2107 | elseif (!$info_id) |
||
| 2108 | { |
||
| 2109 | $readonlys['action'] = true; |
||
| 2110 | } |
||
| 2111 | // ToDo: use the old status before the delete |
||
| 2112 | if ($info_id && $undelete) |
||
| 2113 | { |
||
| 2114 | $content['info_status'] = $this->bo->status['defaults'][$content['info_type']]; |
||
| 2115 | $this->tmpl->setElementAttribute('button[save]', 'label', 'Un-Delete'); |
||
| 2116 | } |
||
| 2117 | |||
| 2118 | if (!($readonlys['button[delete]'] = !$info_id || !$this->bo->check_access($content, Acl::DELETE))) |
||
| 2119 | { |
||
| 2120 | $content['info_anz_subs'] = $this->bo->anzSubs($info_id); // to determine js confirmation of delete or not |
||
| 2121 | } |
||
| 2122 | $GLOBALS['egw_info']['flags']['app_header'] = lang($this->messages[$info_id ? 'edit' : ($action == 'sp' ? 'add_sub' : 'add')]); |
||
| 2123 | |||
| 2124 | // use a typ-specific template (infolog.edit.xyz), if one exists, otherwise fall back to the generic one |
||
| 2125 | if (!$this->tmpl->read('infolog.edit.'.$content['info_type'])) |
||
| 2126 | { |
||
| 2127 | $this->tmpl->read($print ? 'infolog.edit.print':'infolog.edit'); |
||
| 2128 | } |
||
| 2129 | if ($this->bo->has_customfields($content['info_type'])) |
||
| 2130 | { |
||
| 2131 | $content['customfields'] = $content['info_type']; |
||
| 2132 | } |
||
| 2133 | else |
||
| 2134 | { |
||
| 2135 | $readonlys['tabs']['customfields'] = true; |
||
| 2136 | } |
||
| 2137 | if (!isset($GLOBALS['egw_info']['user']['apps']['projectmanager'])) |
||
| 2138 | { |
||
| 2139 | $readonlys['tabs']['project'] = true; // disable the project tab |
||
| 2140 | } |
||
| 2141 | |||
| 2142 | $content['duration_format'] = $this->duration_format; |
||
| 2143 | $content['hours_per_workday'] = $this->hours_per_workday; |
||
| 2144 | if ($this->prefs['show_id']) $content['info_number'] = $info_id; |
||
| 2145 | |||
| 2146 | // Check no notification preference, update if type changed |
||
| 2147 | if($content['info_type'] != $content['old_type']) |
||
| 2148 | { |
||
| 2149 | $content['no_notifications'] = in_array($content['info_type'], !is_array($this->prefs['no_notification_types']) ? |
||
| 2150 | explode(',',$this->prefs['no_notification_types']): |
||
| 2151 | $this->prefs['no_notification_types'] |
||
| 2152 | ); |
||
| 2153 | } |
||
| 2154 | |||
| 2155 | $content['info_anz_subs'] = (int)$content['info_anz_subs']; // gives javascript error if empty! |
||
| 2156 | |||
| 2157 | $old_pm_id = is_array($pm_links) ? array_shift($pm_links) : $content['old_pm_id']; |
||
| 2158 | unset($content['old_pm_id']); |
||
| 2159 | |||
| 2160 | if ($info_id && $this->bo->history) |
||
| 2161 | { |
||
| 2162 | $content['history'] = array( |
||
| 2163 | 'id' => $info_id, |
||
| 2164 | 'app' => 'infolog', |
||
| 2165 | 'status-widgets' => array( |
||
| 2166 | 'Ty' => $types, |
||
| 2167 | //'Li', // info_link_id |
||
| 2168 | 'parent' => 'link-entry:infolog', |
||
| 2169 | 'Ca' => 'select-cat', |
||
| 2170 | 'Pr' => $this->bo->enums['priority'], |
||
| 2171 | 'Ow' => 'select-account', |
||
| 2172 | //'Ac', // info_access: private||public |
||
| 2173 | 'St' => (array)$this->bo->status[$content['info_type']]+array('deleted' => 'deleted'), |
||
| 2174 | 'Pe' => 'select-percent', |
||
| 2175 | 'Co' => 'date-time', |
||
| 2176 | 'st' => 'date-time', |
||
| 2177 | 'Mo' => 'date-time', |
||
| 2178 | 'En' => 'date', |
||
| 2179 | 'Re' => 'select-account', |
||
| 2180 | // PM fields, ToDo: access control!!! |
||
| 2181 | 'pT' => 'date-duration', |
||
| 2182 | 'uT' => 'date-duration', |
||
| 2183 | 'replanned' => 'date-duration', |
||
| 2184 | // 'pL' => 'projectmanager-pricelist', |
||
| 2185 | 'pr' => 'float', |
||
| 2186 | ), |
||
| 2187 | ); |
||
| 2188 | $history_stati = array(); |
||
| 2189 | $tracking = new infolog_tracking($this); |
||
| 2190 | foreach($tracking->field2history as $field => $history) |
||
| 2191 | { |
||
| 2192 | $history_stati[$history] = $tracking->field2label[$field]; |
||
| 2193 | } |
||
| 2194 | // Modified date removed from field2history, we don't need that in the history |
||
| 2195 | $history_stati['Mo'] = $tracking->field2label['info_datemodified']; |
||
| 2196 | unset($tracking); |
||
| 2197 | } |
||
| 2198 | else |
||
| 2199 | { |
||
| 2200 | $readonlys['tabs']['history'] = true; |
||
| 2201 | } |
||
| 2202 | $sel_options = array( |
||
| 2203 | 'info_type' => $types, |
||
| 2204 | 'info_priority' => $this->bo->enums['priority'], |
||
| 2205 | 'info_confirm' => $this->bo->enums['confirm'], |
||
| 2206 | 'info_status' => $this->bo->status[$content['info_type']], |
||
| 2207 | 'status' => $history_stati, |
||
| 2208 | 'action' => array( |
||
| 2209 | 'copy' => array('label' => 'Copy', 'title' => 'Copy this Infolog'), |
||
| 2210 | 'sp' => 'Sub-entry', |
||
| 2211 | 'print' => array('label' => 'Print', 'title' => 'Print this Infolog'), |
||
| 2212 | 'ical' => array('label' => 'Export iCal', 'title' => 'Export iCal'), |
||
| 2213 | 'to_tracker' => array('label' => 'Tracker', 'title' => 'Convert to a ticket'), |
||
| 2214 | ), |
||
| 2215 | ); |
||
| 2216 | if ($GLOBALS['egw_info']['user']['apps']['calendar']) |
||
| 2217 | { |
||
| 2218 | $sel_options['action']['schedule'] = array('label' => 'Schedule', 'title' => 'Schedule appointment'); |
||
| 2219 | } |
||
| 2220 | if ($GLOBALS['egw_info']['user']['apps']['stylite'] && !$GLOBALS['egw_info']['server']['disable_pgp_encryption']) |
||
| 2221 | { |
||
| 2222 | $content['encryption_ts'] = filemtime(EGW_SERVER_ROOT.'/stylite/js/infolog-encryption.js'); |
||
| 2223 | } |
||
| 2224 | elseif ($GLOBALS['egw_info']['server']['disable_pgp_encryption']) |
||
| 2225 | { |
||
| 2226 | $readonlys['encrypt'] = true; |
||
| 2227 | } |
||
| 2228 | $GLOBALS['egw_info']['flags']['app_header'] = lang('InfoLog').' - '. |
||
| 2229 | ($content['status_only'] ? lang('Edit Status') : lang('Edit')); |
||
| 2230 | $GLOBALS['egw_info']['flags']['params']['manual'] = array('page' => ($info_id ? 'ManualInfologEdit' : 'ManualInfologAdd')); |
||
| 2231 | //error_log(substr($content['info_des'],1793,10)); |
||
| 2232 | //$content['info_des'] = substr($content['info_des'],0,1793); |
||
| 2233 | //echo "<p>infolog_ui.edit(info_id='$info_id',action='$action',action_id='$action_id') readonlys="; print_r($readonlys); echo ", content = "; _debug_array($content); |
||
| 2234 | //$content['info_cc'] is expected (by the widget) to be an array of emailaddresses, but is stored as comma separated string |
||
| 2235 | if (!empty($content['info_cc'])&&!is_array($content['info_cc']))$content['info_cc'] = explode(',',$content['info_cc']); |
||
| 2236 | $preserve = array_merge( $preserv, array( // preserved values |
||
| 2237 | 'info_id' => $info_id, |
||
| 2238 | 'action' => $action, |
||
| 2239 | 'action_id' => $action_id, |
||
| 2240 | 'referer' => $referer, |
||
| 2241 | 'no_popup' => $no_popup, |
||
| 2242 | 'old_pm_id' => $old_pm_id, |
||
| 2243 | 'old_type' => $content['info_type'], |
||
| 2244 | )); |
||
| 2245 | $this->tmpl->exec('infolog.infolog_ui.edit',$content,$sel_options,$readonlys,$preserve,$no_popup ? 0 : 2); |
||
| 2246 | } |
||
| 2247 | |||
| 2248 | /** |
||
| 2249 | * Create copy or sub-entry from an entry currently read into $content |
||
| 2250 | * |
||
| 2251 | * Taking into account prefs and config about what to copy |
||
| 2252 | * |
||
| 2253 | * @param array &$content |
||
| 2254 | * @param boolean $create_sub true: create a sub-entry instead of a copy, default false to create a copy |
||
| 2255 | */ |
||
| 2256 | private function create_copy(array &$content, $create_sub=false) |
||
| 2357 | } |
||
| 2358 | } |
||
| 2359 | |||
| 2360 | function icon($cat,$id,$status='') |
||
| 2378 | } |
||
| 2379 | |||
| 2380 | /** |
||
| 2381 | * Infolog's site configuration |
||
| 2382 | * |
||
| 2383 | */ |
||
| 2384 | public function admin($content = array()) |
||
| 2510 | } |
||
| 2511 | |||
| 2512 | /** |
||
| 2513 | * imports a mail as infolog |
||
| 2514 | * |
||
| 2515 | * @param array $mailContent = null content of mail |
||
| 2516 | * @return array |
||
| 2517 | */ |
||
| 2518 | function mail_import(array $mailContent=null) |
||
| 2519 | { |
||
| 2520 | // It would get called from compose as a popup with egw_data |
||
| 2521 | if (!is_array($mailContent) && ($_GET['egw_data'])) |
||
| 2522 | { |
||
| 2523 | // get the mail raw data |
||
| 2524 | Link::get_data ($_GET['egw_data']); |
||
| 2525 | return false; |
||
| 2526 | } |
||
| 2527 | |||
| 2528 | return $this->edit($this->bo->import_mail($mailContent['addresses'], |
||
| 2529 | $mailContent['subject'], |
||
| 2530 | $mailContent['message'], |
||
| 2531 | $mailContent['attachments'], |
||
| 2532 | $mailContent['date'])); |
||
| 2533 | } |
||
| 2534 | |||
| 2535 | /** |
||
| 2536 | * shows infolog in other applications |
||
| 2537 | * |
||
| 2538 | * @param $args['location'] location des hooks: {addressbook|projects|calendar}_view|infolog |
||
| 2539 | * @param $args['view'] menuaction to view, if location == 'infolog' |
||
| 2540 | * @param $args['app'] app-name, if location == 'infolog' |
||
| 2541 | * @param $args['view_id'] name of the id-var for location == 'infolog' |
||
| 2542 | * @param $args[$args['view_id']] id of the entry |
||
| 2543 | * this function can be called for any app, which should include infolog: \ |
||
| 2544 | * Api\Hooks::process(array( \ |
||
| 2545 | * * 'location' => 'infolog', \ |
||
| 2546 | * * 'app' => <your app>, \ |
||
| 2547 | * * 'view_id' => <id name>, \ |
||
| 2548 | * * <id name> => <id value>, \ |
||
| 2549 | * * 'view' => <menuaction to view an entry in your app> \ |
||
| 2550 | * )); |
||
| 2551 | */ |
||
| 2552 | function hook_view($args) |
||
| 2596 | } |
||
| 2597 | |||
| 2598 | /** |
||
| 2599 | * Defines the fields for the csv export |
||
| 2600 | * |
||
| 2601 | * @param string $type infolog type to include only the matching custom fields if set |
||
| 2602 | * @return array |
||
| 2603 | */ |
||
| 2604 | function csv_export_fields($type=null) |
||
| 2648 |