| [ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 <?php 2 /**************************************************************************\ 3 * eGroupWare - KnowledgeBase * 4 * http://www.egroupware.org * 5 * Written by Alejandro Pedraza [alpeb AT users.sourceforge DOT net] * 6 * ------------------------------------------------------------------------ * 7 * Started off as a port of phpBrain - http://vrotvrot.com/phpBrain/ * 8 * but quickly became a full rewrite * 9 * ------------------------------------------------------------------------ * 10 * This program is free software; you can redistribute it and/or modify it * 11 * under the terms of the GNU General Public License as published by the * 12 * Free Software Foundation; either version 2 of the License, or (at your * 13 * option) any later version. * 14 \**************************************************************************/ 15 16 /* $Id: class.bokb.inc.php 20295 2006-02-15 12:31:25Z $ */ 17 18 /** 19 * Business logic layer of the Knowledge Base 20 * 21 * Last Editor: $Author: $ 22 * @author Alejandro Pedraza 23 * @package phpbrain 24 * @version $Revision: 20295 $ 25 * @license GPL 26 **/ 27 class bokb 28 { 29 /** 30 * Data manipulation object 31 * 32 * @access private 33 * @var object so 34 */ 35 var $so; 36 37 /** 38 * Categories object 39 * 40 * @access public 41 * @var object categories 42 */ 43 var $categories_obj; 44 45 /** 46 * Array of all categories accesible by the current user 47 * 48 * @access public 49 * @var array 50 */ 51 var $all_categories; 52 53 /** 54 * Variable holding categories to show 55 * 56 * @access public 57 * @var array 58 */ 59 var $categories; 60 61 /** 62 * Array of current user's grants on other users or groups 63 * 64 * @access public 65 * @var array 66 */ 67 var $grants; 68 69 /** 70 * Preferences for this application 71 * 72 * @access public 73 * @var array 74 */ 75 var $preferences; 76 77 /** 78 * For pagination 79 * 80 * @access public 81 * @var int 82 */ 83 var $start; 84 85 /** 86 * Sorting order 87 * 88 * @access public 89 * @var string ASC | DESC 90 */ 91 var $sort; 92 93 /** 94 * Sorting field 95 * 96 * @access public 97 * @var string 98 */ 99 var $order; 100 101 /** 102 * Administration options for this app 103 * 104 * @access public 105 * @var array 106 */ 107 var $admin_config; 108 109 /** 110 * Number of entries returned by a query 111 * 112 * @access public 113 * @var int 114 */ 115 var $num_rows; 116 117 /** 118 * Number of questions returned by a query 119 * 120 * @access public 121 * @var int 122 */ 123 var $num_questions; 124 125 /** 126 * Number of comments returned by a query 127 * 128 * @access public 129 * @var int 130 */ 131 var $num_comments; 132 133 /** 134 * Error messages produced by methods 135 * 136 * @access public 137 * @var string 138 */ 139 var $error_msg; 140 141 /** 142 * Filter by publication status 143 * 144 * @access public 145 * @var string 146 */ 147 var $publish_filter; 148 149 /** 150 * Search string 151 * 152 * @access public 153 * @var string 154 */ 155 var $query; 156 157 /** 158 * Current article owner's id 159 * 160 * @access public 161 * @var int 162 */ 163 var $article_owner; 164 165 /** 166 * Current article id 167 * 168 * @access public 169 * @var int 170 */ 171 var $article_id; 172 173 /** 174 * Success or error messages returned by methods 175 * 176 * @access public 177 * @var array 178 */ 179 var $messages_array = array( 180 'no_perm' => 'You have not the proper permissions to do that', 181 'add_ok_cont' => 'Article added to database, you can now attach files or links, or relate to other articles', 182 'comm_submited' => 'Comment has been submited for revision', 183 'comm_ok' => 'Comment has been published', 184 'rate_ok' => 'Rating has been submited', 185 'comm_rate_ok' => 'Comment and rating have been published', 186 'comm_rate_submited' => 'Comment has been submited for revision and rating will be published', 187 'no_basedir' => 'Base directory does not exist, please ask adminstrator to check the global configuration', 188 'no_kbdir' => '/kb directory does not exist and could not be created, please ask adminstrator to check the global configuration', 189 'overwrite' => 'That file already exists', 190 'no_file_serv' => 'The file was already missing in the server', 191 'failure_delete' => 'Failure trying to delete the file', 192 'file_del_ok' => 'File was deleted successfully', 193 'file_db_del_err' => 'File could be deleted from server but not from database', 194 'file_noserv_db_ok' => "File was already missing from server, and was deleted from the database", 195 'file_noserv_db_err' => "File wasn't in server and it couldn't be deleted from the database", 196 'del_rel_ok' => 'Relation with article was removed successfully', 197 'link_del_err' => 'Error deleting link', 198 'link_del_ok' => 'Link deleted successfully', 199 'error_cd' => 'Error locating files directory', 200 'nothing_uploaded' => 'Nothing was uploaded!', 201 'error_cp' => 'Error moving file to directory', 202 'upload_ok' => 'File has been successfully uploaded', 203 'articles_added' => 'Articles added', 204 'articles_not_added' => 'Problem relating articles', 205 'link_ok' => 'Link has been added', 206 'link_prob' => 'Link could not be added', 207 'err_del_art' => 'Error deleting article from database', 208 'err_del_q' => 'Error trying to delete question', 209 'del_art_ok' => 'Article deleted successfully', 210 'del_arts_ok' => 'Articles deleted successfully', 211 'del_q_ok' => 'Question deleted successfully', 212 'del_qs_ok' => 'Questions deleted successfully', 213 'del_comm_err' => 'Error trying to delete comment', 214 'del_comm_ok' => 'Comment has been deleted', 215 'edit_err' => 'Error trying to edit article', 216 'publish_err' => 'Error trying to publish article', 217 'publish_comm_err' => 'Error publishing comment', 218 'publish_ok' => 'Article has been published', 219 'publish_comm_ok' => 'Comment has been pusblished', 220 'publishs_ok' => 'Articles have been published', 221 'mail_ok' => 'e-mail has been sent', 222 'mail_err' => 'Error in e-mail address' 223 ); 224 225 226 /** 227 * Class constructor 228 * 229 * @author Alejandro Pedraza 230 * @access public 231 **/ 232 function bokb() 233 { 234 // version check 235 if ($GLOBALS['phpgw_info']['apps']['phpbrain']['version'] != '1.0.5') 236 { 237 $GLOBALS['phpgw']->common->phpgw_header(); 238 echo parse_navbar(); 239 die("Please upgrade this application to be able to use it"); 240 } 241 242 $this->so = CreateObject('phpbrain.sokb'); 243 $this->categories_obj = CreateObject('phpgwapi.categories', '', 'phpbrain'); // force phpbrain cause it might be running from sitemgr... 244 $GLOBALS['phpgw']->config = CreateObject('phpgwapi.config'); 245 $GLOBALS['phpgw']->vfs = CreateObject('phpgwapi.vfs'); 246 $GLOBALS['phpgw']->historylog = CreateObject('phpgwapi.historylog','phpbrain'); 247 248 $this->grants = $GLOBALS['phpgw']->acl->get_grants('phpbrain'); 249 //echo "grants: <pre>";print_r($this->grants);echo "</pre>"; 250 // full grants for admin on user 0 (anonymous questions on previous phpbrain version) 251 if ($GLOBALS['phpgw']->acl->check('run',1,'admin')) $this->grants[0] = -1; 252 $this->preferences = $GLOBALS['phpgw']->preferences->data['phpbrain']; 253 254 $this->read_right = PHPGW_ACL_READ; 255 $this->edit_right = PHPGW_ACL_EDIT; 256 $this->publish_right = PHPGW_ACL_CUSTOM_1; 257 258 // acl grants puts all rights (-1) on current the user itself. That has to be modified here since the user doesn't have necessarily publish rights 259 // Here I have to accumulate the rights the user has on every group it belongs to 260 $grants_user = $this->read_right | $this->edit_right; // The user can always read and edit his own articles 261 $user_groups = $GLOBALS['phpgw']->accounts->membership($GLOBALS['phpgw_info']['user']['account_id']); 262 foreach ($user_groups as $group) 263 { 264 $grants_user |= $this->grants[$group['account_id']]; 265 //echo "for the group: ";echo $group['account_id'];echo " the right: ";echo $this->grants[$group['account_id']];echo "<br>"; 266 } 267 //echo "grants_user: $grants_user<br>"; 268 $this->grants[$GLOBALS['phpgw_info']['user']['account_id']] = $grants_user; 269 270 $this->admin_config = $GLOBALS['phpgw']->config->read_repository(); 271 272 if (!$this->all_categories = $this->categories_obj->return_sorted_array('', False, '', '', '', True, 0)) $this->all_categories = array(); 273 274 // default preferences and admin config 275 if (!$this->preferences['num_lines']) $this->preferences['num_lines'] = 3; 276 if (!$this->preferences['show_tree']) $this->preferences['show_tree'] = 'all'; 277 if (!$this->preferences['num_comments']) $this->preferences['num_comments'] = '5'; 278 if (!$this->admin_config['publish_comments']) $this->admin_config['publish_comments'] = 'True'; 279 if (!$this->admin_config['publish_articles']) $this->admin_config['publish_articles'] = 'True'; 280 if (!$this->admin_config['publish_questions']) $this->admin_config['publish_questions'] = 'True'; 281 282 $this->start = get_var('start', 'any', 0); 283 $this->query = urldecode(get_var('query', 'any', '')); 284 $this->sort = get_var('sort', 'any', ''); 285 $this->order = get_var('order', 'any', ''); 286 $this->publish_filter = get_var('publish_filter', 'any', 'all'); 287 288 // advanced search parameters 289 $this->all_words = get_var('all_words', 'any', ''); 290 $this->phrase = get_var('phrase', 'any', ''); 291 $this->one_word = get_var('one_word', 'any', ''); 292 $this->without_words= get_var('without_words', 'any', ''); 293 $this->cat = get_var('cat', 'any', 0); 294 $this->include_subs = get_var('include_subs', 'any', ''); 295 $this->pub_date = get_var('pub_date', 'any', ''); 296 $this->ocurrences = get_var('ocurrences', 'any', 0); 297 $this->num_res = get_var('num_res', 'any', ''); 298 } 299 300 /** 301 * Returns a single category 302 * 303 * @author Alejandro Pedraza 304 * @access public 305 * @param int $cat_id Category id 306 * @return array Category infoA 307 */ 308 function return_single_category($cat_id) 309 { 310 return $this->categories_obj->return_single($cat_id); 311 } 312 313 /** 314 * Loads in object $this->categories, an array of the descendant categories of $parent_cat_id 315 * 316 * @author Alejandro Pedraza 317 * @access public 318 * @param int $parent_cat_id id of the parent category 319 * @return void 320 */ 321 function load_categories($parent_cat_id) 322 { 323 if (!$this->categories = $this->categories_obj->return_sorted_array('', False, '', '', '', True, $parent_cat_id)) $this->categories = array(); 324 } 325 326 /** 327 * Return html code for drop-down select box with categories accessible by user 328 * 329 * @author Alejandro Pedraza 330 * @access public 331 * @param int $category_selected id of category to show selected 332 * @return string Html code 333 */ 334 function select_category($category_selected = '') 335 { 336 return $this->categories_obj->formated_list('select', 'all', $category_selected , True); 337 } 338 339 /** 340 * Returns list of user ids to which the current user has permissions 341 * 342 * @author Alejandro Pedraza 343 * @access private 344 * @param int $permissions Permissions bitmask. If not given, uses $this->read_right 345 * @return array User ids 346 */ 347 function accessible_owners($permissions = 0) 348 { 349 $owners = array($GLOBALS['phpgw_info']['user']['account_id']); 350 if (!$permissions) $permissions = $this->read_right; 351 foreach ($this->grants as $user=>$right) 352 { 353 if ($right & $permissions) 354 { 355 $owners[] = $user; 356 } 357 } 358 359 return $owners; 360 } 361 362 /** 363 * Checks for rights on article 364 * 365 * @author Alejandro Pedraza 366 * @access public 367 * @param int $check_rights bitmask ACL right (use $this->read_right or $this->edit_right) 368 * @param int $article_owner if not set, checks rights against current article 369 * @return bool True if has rights, False if not 370 */ 371 function check_permission($check_rights, $article_owner = 0) 372 { 373 if (!$article_owner) $article_owner = $this->article_owner; 374 if ($this->grants[$article_owner]) 375 { 376 $rights_on_owner = $this->grants[$article_owner]; 377 } 378 else 379 { 380 return False; 381 } 382 383 return ($rights_on_owner & $check_rights); 384 } 385 386 /** 387 * Returns array of articles 388 * 389 * @author Alejandro Pedraza 390 * @access public 391 * @param int $category_id Category under which articles are to be retrieved 392 * @param mixed $publish_filter To filter pusblished or unpublished entries 393 * @param int $permissions Specific permissions on article owners 394 * @param bool $questions Whether looking for questions or articles 395 * @return array Articles 396 **/ 397 function search_articles($category_id, $publish_filter = False, $permissions=0, $questions=False) 398 { 399 $search = $questions? 'unanswered_questions' : 'search_articles'; 400 if (!$permissions) $permissions = $this->read_right; 401 402 $owners = $this->accessible_owners($permissions); 403 // admins can also see questions asked by user_id=0 (questions that were passed from previous phpbrain version were the user_id wasn't recorded) 404 if ($questions && $GLOBALS['phpgw']->acl->check('run',1,'admin')) $owners[0] = 0; 405 406 if ($this->preferences['show_tree'] == 'all') 407 { 408 // show all articles under present category and descendant categories 409 $cats_ids = array(); 410 foreach ($this->categories as $cat) 411 { 412 $cats_ids[] = $cat['id']; 413 } 414 $cats_ids[] = $category_id; 415 416 $articles = $this->so->$search($owners, $cats_ids, $this->start, '', $this->sort, $this->order, $publish_filter, $this->query); 417 } 418 elseif ($category_id == 0) 419 { 420 // show only articles that are not categorized 421 $articles = $this->so->$search($owners, 0, $this->start, '', $this->sort, $this->order, $publish_filter, $this->query); 422 } 423 else 424 { 425 // show only articles in present category 426 $articles = $this->so->$search($owners, array($category_id), $this->start, '', $this->sort, $this->order, $publish_filter, $this->query); 427 } 428 429 $this->num_rows = $this->so->num_rows; 430 return $articles; 431 } 432 433 /** 434 * Returns results of advanced search 435 * 436 * @author Alejandro Pedraza 437 * @access public 438 * @return array Articles 439 */ 440 function adv_search_articles() 441 { 442 $owners = $this->accessible_owners(); 443 444 $cats_ids = array(); 445 if ($this->cat && !$this->include_subs) 446 { 447 // only search in one category 448 $cats_ids[] = $this->cat; 449 } 450 elseif ($this->cat) 451 { 452 // search in category passed and all its descendency 453 foreach ($this->categories as $cat) 454 { 455 $cats_ids[] = $cat['id']; 456 } 457 $cats_ids[] = $this->cat; 458 } 459 460 $articles = $this->so->adv_search_articles($owners, $cats_ids, $this->ocurrences, $this->pub_date, $this->start, $this->num_res, $this->all_words, $this->phrase, $this->one_word, $this->without_words, $this->cat, $this->include_subs); 461 $this->num_rows = $this->so->num_rows; 462 return $articles; 463 } 464 465 /** 466 * Returns unanswered questions 467 * 468 * @author Alejandro Pedraza 469 * @access public 470 * @param int $category_id Category in which to look for 471 * @return array Questions 472 */ 473 function unanswered_questions($category_id) 474 { 475 $owners = $this->accessible_owners(); 476 477 // admins can also see questions asked by user_id=0 (questions that were passed from previous phpbrain version were the user_id wasn't recorded) 478 if ($GLOBALS['phpgw']->acl->check('run',1,'admin')) $owners[0] = 0; 479 480 $cats_ids = array(); 481 foreach ($this->categories as $cat) 482 { 483 $cats_ids[] = $cat['id']; 484 } 485 $cats_ids[] = $category_id; 486 487 $questions = $this->so->unanswered_questions($owners, $cats_ids, 0, $this->preferences['num_lines'], 'DESC', 'creation', 'published', ''); 488 $this->num_questions = $this->so->num_questions; 489 return $questions; 490 } 491 492 /** 493 * Returns article's history 494 * 495 * @author Alejandro Pedraza 496 * @access public 497 * @return array Articles's history 498 */ 499 function return_history() 500 { 501 $history = $GLOBALS['phpgw']->historylog->return_array('', '', 'history_timestamp', 'DESC', $this->article_id); 502 // echo "history: <pre>";print_r($history);echo "</pre>"; 503 for ($i = 0; $i<sizeof($history); $i++) 504 { 505 $history[$i]['datetime'] = $GLOBALS['phpgw']->common->show_date($history[$i]['datetime'], $GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat']); 506 $GLOBALS['phpgw']->accounts->get_account_name($history[$i]['owner'], $lid, $fname, $lname); 507 $history[$i]['owner'] = $fname . ' ' . $lname; 508 509 switch ($history[$i]['status']) 510 { 511 case 'AF': 512 $history[$i]['action'] = lang ('Added file %1', $history[$i]['new_value']); 513 break; 514 case 'RF': 515 $history[$i]['action'] = lang ('Removed file %1', $history[$i]['new_value']); 516 break; 517 case 'AL': 518 $history[$i]['action'] = lang ('Added link %1', $history[$i]['new_value']); 519 break; 520 case 'RL': 521 $history[$i]['action'] = lang ('Removed link %1', $history[$i]['new_value']); 522 break; 523 case 'AR': 524 $history[$i]['action'] = lang ('Added related articles %1', $history[$i]['new_value']); 525 break; 526 case 'DR': 527 $history[$i]['action'] = lang ('Deleted relation to article %1', $history[$i]['new_value']); 528 break; 529 case 'EA': 530 $history[$i]['action'] = lang ('Article edited'); 531 break; 532 case 'NA': 533 $history[$i]['action'] = lang ('Article created'); 534 break; 535 case 'AD': 536 $history[$i]['action'] = lang ('Article deleted'); 537 break; 538 } 539 } 540 return $history; 541 } 542 543 /** 544 * Returns latest or most viewed articles 545 * 546 * @author Alejandro Pedraza 547 * @param int $category_id articles must belong to the descendancy of this category 548 * @param string $order Field by which the query is ordered, determines whether latest or most viewed articles are returned 549 * @return array array of articles 550 */ 551 function return_latest_mostviewed($category_id = 0, $order = '') 552 { 553 $owners = $this->accessible_owners(); 554 555 $cats_ids = array($category_id); 556 foreach ($this->categories as $cat) 557 { 558 $cats_ids[] = $cat['id']; 559 } 560 561 return $this->so->search_articles($owners, $cats_ids, 0, $this->preferences['num_lines'], 'DESC', $order, 'published', ''); 562 } 563 564 /** 565 * Saves a new or edited article 566 * 567 * @author Alejandro Pedraza 568 * @access public 569 * @param array $content Article contents. Extracted from $_POST if empty 570 * @return bool True on success, False on failure 571 **/ 572 function save_article($content = '') 573 { 574 if (!$content) { 575 $content = array(); 576 $content['exec'] = get_var('exec', 'POST'); 577 $content['editing_article_id'] = (int)get_var('editing_article_id', 'POST', 0); 578 $content['articleID'] = get_var('articleID', 'POST'); 579 $content['answering_question'] = (int)get_var('answering_question', 'POST', 0); 580 $content['title'] = get_var('title', 'POST'); 581 $content['topic'] = get_var('topic', 'POST'); 582 $content['cat_id'] = (int)get_var('cat_id', 'POST', 0); 583 $content['keywords'] = get_var('keywords', 'POST'); 584 } 585 586 $content['text'] = $content['exec']['text']; 587 588 // if editing an article, check it has the right to do so 589 if ($content['editing_article_id'] && !($this->check_permission($this->edit_right))) 590 { 591 $this->error_msg = lang('You have not the proper permissions to do that'); 592 return False; 593 } 594 elseif ($content['editing_article_id']) 595 { 596 if(!$art_id = $this->so->save_article($content, False)) 597 { 598 $this->error_msg = 'edit_err'; 599 return False; 600 } 601 $GLOBALS['phpgw']->historylog->add('EA', $this->article_id, 'article edited', ''); 602 return $art_id; 603 } 604 605 // if given, articleID must be a number 606 if ($content['articleID']!='' && !is_numeric($content['articleID'])) 607 { 608 $this->error_msg = lang('The article ID must be a number'); 609 return False; 610 } 611 612 // if adding a new article, check that the articleID doesn't already exist if it was given 613 if ($content['articleID'] && $this->so->exist_articleID($content['articleID'])) 614 { 615 $this->error_msg = "Article ID already exists"; 616 return False; 617 } 618 619 $publish = False; 620 if ($this->admin_config['publish_articles'] == 'True') $publish = True; 621 622 $art_id = $this->so->save_article($content, True, $publish); 623 if ($art_id) $GLOBALS['phpgw']->historylog->add('NA', $art_id, 'article created', ''); 624 return $art_id; 625 } 626 627 /** 628 * Deletes article 629 * 630 * @author Alejandro Pedraza 631 * @access public 632 * @param array Article's files 633 * @param int $art_id Article id. If not given, $this->article_id is used 634 * @param int $owner Article's owner id. -1 to avoid checking permissions (when admin is deleting all user's articles) 635 * @return string Success or failure message 636 */ 637 function delete_article($files, $art_id = 0, $owner = 0) 638 { 639 if (!$art_id) $art_id = $this->article_id; 640 // check user has edit rights 641 if ($owner != -1 && !$this->check_permission($this->edit_right, $owner)) return 'no_perm'; 642 // delete files 643 if ($files) 644 { 645 foreach ($files as $file) 646 { 647 // verify the file exists in the server 648 $test = $GLOBALS['phpgw']->vfs->ls(array( 649 'string' => '/kb/' . $file['file'], 650 'relatives' => array(RELATIVE_NONE), 651 'checksubdirs' => False, 652 'nofiles' => False 653 )); 654 if ($test[0]['name']) 655 { 656 // the file is in the server, proceed to rm it 657 $remove = $GLOBALS['phpgw']->vfs->rm(array( 658 'string' => '/kb/' . $file['file'], 659 'relatives' => array(RELATIVE_NONE) 660 )); 661 } 662 } 663 } 664 // delete comments 665 $this->so->delete_comments($art_id); 666 // delete ratings 667 $this->so->delete_ratings($art_id); 668 // delete related articles 669 $this->so->delete_related($art_id, $art_id, True); 670 // delete search index 671 $this->so->delete_search($art_id); 672 // delete files entries in phpgw_kb_files 673 $this->so->delete_files($art_id); 674 // delete urls 675 $this->so->delete_urls($art_id); 676 // delete article 677 if (!$this->so->delete_article($art_id)) return 'err_del_art'; 678 if ($art_id) $GLOBALS['phpgw']->historylog->add('AD', $art_id, 'article deleted', ''); 679 return 'del_art_ok'; 680 } 681 682 /** 683 * Deletes owners articles (called by hook_deleteaccount) 684 * 685 * @author Alejandro Pedraza 686 * @access public 687 * @param int $owner Article's owner id 688 * @return void 689 */ 690 function delete_owner_articles($owner) 691 { 692 // check if user calling deletion is an admin with user deletion privileges 693 if ($GLOBALS['phpgw']->acl->check('account_access',32,'admin')) 694 { 695 $this->list_users(); 696 die('invalid rights'); 697 } 698 699 // fetch articles from user 700 $GLOBALS['phpgw']->vfs->override_acl = 1; 701 $owner = (int)$owner; 702 $articles_ids = $this->so->get_articles_ids($owner); 703 foreach ($articles_ids as $article_id) 704 { 705 $article = $this->so->get_article($article_id); 706 $this->delete_article($article['files'], $article_id, -1); 707 } 708 } 709 710 /** 711 * changes articles owner (called by hook_deleteaccount) 712 * 713 * @author Alejandro Pedraza 714 * @access public 715 * @param int $owner Article's owner id 716 * @param int $owner Article's new owner id 717 * @return void 718 */ 719 function change_articles_owner($owner, $new_owner) 720 { 721 // check if user calling deletion is an admin with user deletion privileges 722 if ($GLOBALS['phpgw']->acl->check('account_access',32,'admin')) 723 { 724 $this->list_users(); 725 die('invalid rights'); 726 } 727 728 $owner = (int)$owner; 729 $new_owner = (int)$new_owner; 730 731 // first change file owners in vfs 732 $articles_ids = $this->so->get_articles_ids($owner); 733 foreach ($articles_ids as $article_id) 734 { 735 $article = $this->so->get_article($article_id); 736 $GLOBALS['phpgw']->vfs->override_acl = 1; 737 if (is_array($article['files'])) 738 { 739 foreach ($article['files'] as $file) 740 { 741 $GLOBALS['phpgw']->vfs->set_attributes(array( 742 'string' => '/kb/' . $file['file'], 743 'relatives' => array(RELATIVE_NONE), 744 'attributes' => array('owner_id' => $new_owner), 745 )); 746 } 747 } 748 } 749 750 // now change articles owners 751 $this->so->change_articles_owner($owner, $new_owner); 752 } 753 754 /** 755 * Deletes question 756 * 757 * @author Alejandro Pedraza 758 * @access public 759 * @param int $q_id Question id 760 * @param int $owner Article's owner id 761 * @return string Success or failure message 762 **/ 763 function delete_question($q_id, $owner) 764 { 765 // check user has edit rights on owner 766 $this->article_owner = $owner; 767 if (!$this->check_permission($this->edit_right, $owner)) return 'no_perm'; 768 769 if (!$this->so->delete_question($q_id)) return 'err_del_q'; 770 return 'del_q_ok'; 771 } 772 773 /** 774 * Returns article 775 * 776 * @author Alejandro Pedraza 777 * @access public 778 * @param int $art_id article id 779 * @return array Article 780 **/ 781 function get_article($art_id) 782 { 783 if (!$article = $this->so->get_article($art_id)) return False; 784 $this->article_id = $article['art_id']; 785 786 // check permissions 787 $this->article_owner = $article['user_id']; 788 if (!$this->check_permission($this->read_right | $this->publish_right)) $this->die_peacefully('You have not the proper permissions to do that'); 789 790 $GLOBALS['phpgw']->accounts->get_account_name($article['user_id'], $lid, $fname, $lname); 791 $article['username'] = $fname . ' ' . $lname; 792 $fname = ''; $lname = ''; 793 $GLOBALS['phpgw']->accounts->get_account_name($article['modified_user_id'], $lid, $fname, $lname); 794 $article['modified_username'] = $fname . ' ' .$lname; 795 796 // register article view if it has been published (one hit per session) 797 if (!$data = $GLOBALS['phpgw']->session->appsession('views', 'phpbrain')) $data = array(); 798 if ($article['published'] && !in_array($this->article_id, $data)) 799 { 800 $data[] = $this->article_id; 801 $GLOBALS['phpgw']->session->appsession('views', 'phpbrain', $data); 802 $this->so->register_view($this->article_id, $article['views']); 803 } 804 805 // process search_feedback (can do this only once per session per article) 806 if (!$data = $GLOBALS['phpgw']->session->appsession('feedback', 'phpbrain')) $data = array(); 807 if ($_POST['feedback_query'] && !in_array($this->article_id, $data)) 808 { 809 $data[] = $this->article_id; 810 $GLOBALS['phpgw']->session->appsession('feedback', 'phpbrain', $data); 811 $upgrade_key = $_POST['yes_easy']? True : False; 812 $words = explode(' ', $_POST['feedback_query']); 813 foreach ($words as $word) 814 { 815 $this->so->update_keywords($this->article_id, $word, $upgrade_key); 816 } 817 } 818 819 return $article; 820 } 821 822 /** 823 * Previous checks before downloading a file 824 * 825 * @author Alejandro Pedraza 826 * @access public 827 * @param int $art_id Article id 828 * @param string $filename filename 829 * @return void 830 */ 831 function download_file_checks($art_id, $filename) 832 { 833 if (!$article = $this->get_article($art_id)) $this->die_peacefully('Error downloading file'); 834 if (!$this->check_permission($this->read_right)) $this->die_peacefully('You have not the proper permissions to do that'); 835 $found_file = False; 836 foreach ($article['files'] as $article_file) 837 { 838 if ($article_file['file'] == $filename) $found_file = True; 839 } 840 if (!$found_file) $this->die_peacefully("Error: file doesn't exist in the database"); 841 } 842 843 /** 844 * Returns article's comments 845 * 846 * @author Alejandro Pedraza 847 * @access public 848 * @param int $art_id article id 849 * @param int $limit Number of comments to return 850 * @return array Comments 851 */ 852 function get_comments($art_id, $limit = False) 853 { 854 if ($limit) $limit = $this->preferences['num_comments']; 855 $comments = $this->so->get_comments($art_id, $limit); 856 $this->num_comments = $this->so->num_comments; 857 return $comments; 858 } 859 860 /** 861 * Returns an article related comments 862 * 863 * @author Alejandro Pedraza 864 * @acces public 865 * @param int $art_id Article id 866 * @return array IDs and titles of articles 867 */ 868 function get_related_articles($art_id) 869 { 870 $owners = $this->accessible_owners(); 871 return $this->so->get_related_articles($art_id, $owners); 872 } 873 874 /** 875 * Tells if the current user has already rated the article 876 * 877 * @author Alejandro Pedraza 878 * @access public 879 * @returns bool 1 if he has, 0 if not 880 **/ 881 function user_has_voted() 882 { 883 return $this->so->user_has_voted($this->article_id); 884 } 885 886 /** 887 * Registers user's vote. When accessing through egroupware users can only vote once. When accessign through sitemgr, they can vote as many times they wish, but only once per session on an individual article 888 * 889 * @author Alejandro Pedraza 890 * @access public 891 * @param int $current_rating Current number of votes in the level $rating (this saves me a trip to the db) 892 * @param bool $sitemgr Whether user is accessing through sitemgr 893 * @return bool 1 on success, 0 on failure 894 */ 895 function add_rating($current_rating, $sitemgr=False) 896 { 897 if(!$this->so->add_vote($this->article_id, $_POST['Rate'], $current_rating)) return 0; 898 if (!$sitemgr) 899 { 900 if (!$this->so->add_rating_user($this->article_id)) return 0; 901 } 902 // register vote in session 903 if (!$data = $GLOBALS['phpgw']->session->appsession('ratings', 'phpbrain')) $data = array(); 904 $data[] = $this->article_id; 905 $GLOBALS['phpgw']->session->appsession('ratings', 'phpbrain', $data); 906 907 return 1; 908 } 909 910 /** 911 * Stores new comment 912 * 913 * @author Alejandro Pedraza 914 * @access public 915 * @return mixed Success message or 0 if failure 916 */ 917 function add_comment() 918 { 919 $comment = get_var('comment_box', 'POST'); 920 if ($this->admin_config['publish_comments'] == 'True') 921 { 922 $publish = True; 923 $message = 'comm_ok'; 924 } 925 else 926 { 927 $publish = False; 928 $message = 'comm_submited'; 929 } 930 if (!$this->so->add_comment($comment, $this->article_id, $publish)) return 0; 931 return $message; 932 } 933 934 /** 935 * Adds link to article 936 * 937 * @author Alejandro Pedraza 938 * @access public 939 * @return string Success or failure message 940 */ 941 function add_link() 942 { 943 // first check permission 944 if (!$this->check_permission($this->edit_right)) return 'no_perm'; 945 946 if(!$this->so->add_link(get_var('url', 'POST'), get_var('url_title', 'POST'), $this->article_id)) return 'link_prob'; 947 948 $GLOBALS['phpgw']->historylog->add('AL', $this->article_id, get_var('url', 'POST'), ''); 949 return 'link_ok'; 950 } 951 952 /** 953 * Publishes article 954 * 955 * @author Alejandro Pedraza 956 * @access public 957 * @params int $art_id Article ID. If not given uses current article 958 * @params int $owner Article's owner ID. If not given uses owner of current article 959 * @return string Success or error message 960 **/ 961 function publish_article($art_id=0, $owner=0) 962 { 963 if (!$art_id) $art_id = $this->article_id; 964 965 // first check permission 966 if (!$this->check_permission($this->publish_right, $owner)) return 'no_perm'; 967 968 if (!$this->so->publish_article($art_id)) return 'publish_err'; 969 return 'publish_ok'; 970 } 971 972 /** 973 * Publishes question 974 * 975 * @author Alejandro Pedraza 976 * @access public 977 * @params int $q_id Question ID. 978 * @params int $owner Article's owner ID 979 * @return string Success or error message 980 **/ 981 function publish_question($q_id, $owner) 982 { 983 // first check permission 984 if (!$this->check_permission($this->publish_right, $owner)) return 'no_perm'; 985 986 if (!$this->so->publish_question($q_id)) return 'publish_err'; 987 return 'publish_ok'; 988 } 989 990 /** 991 * Publishes article comment 992 * 993 * @author Alejandro Pedraza 994 * @access public 995 * @return string Success or error message 996 */ 997 function publish_comment() 998 { 999 $comment_id = (int)$_GET['pub_com']; 1000 // first check permission 1001 if (!$this->check_permission($this->edit_right)) return 'no_perm'; 1002 1003 if (!$this->so->publish_comment($this->article_id, $comment_id)) return 'publish_comm_err'; 1004 return 'publish_comm_ok'; 1005 } 1006 1007 /** 1008 * Deletes article comment 1009 * 1010 * @author Alejandro Pedraza 1011 * @access public 1012 * @return string Success or error message 1013 */ 1014 function delete_comment() 1015 { 1016 $comment_id = (int)$_GET['del_comm']; 1017 1018 // check permission 1019 if (!$this->check_permission($this->edit_right)) return 'no_perm'; 1020 1021 if (!$this->so->delete_comment($this->article_id, $comment_id)) return 'del_comm_err'; 1022 return 'del_comm_ok'; 1023 } 1024 1025 /** 1026 * Deletes article comment 1027 * 1028 * @author Alejandro Pedraza 1029 * @access public 1030 * @return string Success or error message 1031 */ 1032 function delete_link() 1033 { 1034 $link = urldecode($_GET['delete_link']); 1035 // first check permission 1036 if (!$this->check_permission($this->edit_right)) return 'no_perm'; 1037 1038 if (!$this->so->delete_link($this->article_id, $link)) return 'link_del_err'; 1039 1040 $GLOBALS['phpgw']->historylog->add('RL', $this->article_id, $delete_link, ''); 1041 return 'link_del_ok'; 1042 } 1043 1044 /** 1045 * @function process_upload 1046 * 1047 * @abstract Uploads file to system 1048 * @author Alejandro Pedraza 1049 * @return string: error or confirmation message 1050 */ 1051 function process_upload() 1052 { 1053 // check permissions 1054 if (!$this->check_permission($this->edit_right)) return 'no_perm'; 1055 // check something was indeed uploaded 1056 if ($_FILES['new_file']['error'] == 4) return 'nothing_uploaded'; 1057 1058 // TODO: check filename for invalid characters 1059 1060 // check if basedir exists 1061 $test=$GLOBALS['phpgw']->vfs->get_real_info(array('string' => '/', 'relatives' => array(RELATIVE_NONE), 'relative' => False)); 1062 if($test[mime_type]!='Directory') 1063 { 1064 return 'no_basedir'; 1065 } 1066 1067 // check if /kb exists 1068 $test = @$GLOBALS['phpgw']->vfs->get_real_info(array('string' => '/kb', 'relatives' => array(RELATIVE_NONE), 'relative' => False)); 1069 if($test[mime_type]!='Directory') 1070 { 1071 // if not, create it 1072 $GLOBALS['phpgw']->vfs->override_acl = 1; 1073 $GLOBALS['phpgw']->vfs->mkdir(array( 1074 'string' => '/kb', 1075 'relatives' => array(RELATIVE_NONE) 1076 )); 1077 $GLOBALS['phpgw']->vfs->override_acl = 0; 1078 1079 // test one more time 1080 $test = $GLOBALS['phpgw']->vfs->get_real_info(array('string' => '/kb', 'relatives' => array(RELATIVE_NONE), 'relative' => False)); 1081 if($test[mime_type]!='Directory') 1082 { 1083 return 'no_kbdir'; 1084 } 1085 } 1086 // prefix with article number 1087 $filename = stripslashes('kb' . $this->article_id . '-' . $_FILES['new_file']['name']); // strip slashes eventually generated if magic_quotes_gpc is set on 1088 1089 // check the file doesn't already exist (happens when double POSTing) 1090 $test = $GLOBALS['phpgw']->vfs->ls(array( 1091 'string' => '/kb/' . $filename, 1092 'relatives' => array(RELATIVE_NONE), 1093 'checksubdirs' => False, 1094 'nofiles' => False 1095 )); 1096 if ($test[0]['name']) return 'overwrite'; 1097 1098 // at last, copy the file from /tmp to /kb 1099 $cd_args = array('string' => '/kb', 'relative' => False, 'relatives' => RELATIVE_NONE); 1100 if (!$GLOBALS['phpgw']->vfs->cd($cd_args)) return 'error_cd'; 1101 1102 $cp_args = array( 1103 'from' => $_FILES['new_file']['tmp_name'], 1104 'to' => $filename, 1105 'relatives' => array(RELATIVE_NONE|VFS_REAL, RELATIVE_ALL) 1106 ); 1107 $GLOBALS['phpgw']->vfs->override_acl = 1; // should I implement ACL on this folder? Don't think so :> 1108 if (!$GLOBALS['phpgw']->vfs->cp($cp_args)) return 'error_cp'; 1109 $GLOBALS['phpgw']->vfs->override_acl = 0; 1110 1111 $this->so->add_file($this->article_id, $filename); 1112 1113 $GLOBALS['phpgw']->historylog->add('AF', $this->article_id, $_FILES['new_file']['name'], ''); 1114 return 'upload_ok'; 1115 } 1116 1117 /** 1118 * Deletes file 1119 * 1120 * @author Alejandro Pedraza 1121 * @access public 1122 * @param string $current_files Forgot why this 1123 * @param string $file File name 1124 * @return string Success or error message 1125 * @todo see what's the deal with $current_files 1126 */ 1127 function delete_file($current_files, $file = '') 1128 { 1129 if (!$file) $file = urldecode($_GET['delete_file']); 1130 1131 // check permissions 1132 if (!$this->check_permission($this->edit_right)) return 'no_perm'; 1133 1134 // verify the file exists in the server 1135 $test = $GLOBALS['phpgw']->vfs->ls(array( 1136 'string' => '/kb/' . $file, 1137 'relatives' => array(RELATIVE_NONE), 1138 'checksubdirs' => False, 1139 'nofiles' => False 1140 )); 1141 if ($test[0]['name']) 1142 { 1143 // the file is in the server, proceed to rm it 1144 $remove = $GLOBALS['phpgw']->vfs->rm(array( 1145 'string' => '/kb/' . $file, 1146 'relatives' => array(RELATIVE_NONE) 1147 )); 1148 if (!$remove) return 'failure_delete'; 1149 $in_server = True; 1150 1151 } 1152 else 1153 { 1154 // the file was already missing 1155 $in_server = False; 1156 } 1157 1158 // now delete it from the database 1159 ereg('^kb[0-9]*-(.*)', $file, $new_filename); 1160 if ($success = $this->so->delete_files($this->article_id, $file)) 1161 $GLOBALS['phpgw']->historylog->add('RF', $this->article_id, $new_filename[1], ''); 1162 if ($in_server && $success) return 'file_del_ok'; 1163 if ($in_server && !$success) return 'file_db_del_err'; 1164 if (!$in_server && $success) return 'file_noserv_db_ok'; 1165 return 'file_noserv_db_err'; 1166 } 1167 1168 /** 1169 * Adds related article to article 1170 * 1171 * @author Alejandro Pedraza 1172 * @access public 1173 * @return string Success or error message 1174 */ 1175 function add_related() 1176 { 1177 $parsed_list = array(); 1178 $final_list = array(); 1179 1180 // validate list 1181 $list = explode(', ', $_POST['related_articles']); 1182 for ($i=0; $i<sizeof($list); $i++) 1183 { 1184 if ((int)$list[$i]) 1185 { 1186 $parsed_list[] = (int)$list[$i]; 1187 } 1188 } 1189 1190 // check permissions on those articles 1191 $owners_list = $this->so->owners_list($parsed_list); 1192 foreach ($owners_list as $owner) 1193 { 1194 if ($this->check_permission($this->edit_right, $owner['user_id'])) $final_list[] = $owner['art_id']; 1195 } 1196 1197 // update database 1198 if (!$this->so->add_related($this->article_id, $final_list)) return 'articles_not_added'; 1199 1200 $final_list = implode(', ', $final_list); 1201 $GLOBALS['phpgw']->historylog->add('AR', $this->article_id, $final_list, ''); 1202 return 'articles_added'; 1203 } 1204 1205 /** 1206 * Deletes related article to article 1207 * 1208 * @author Alejandro Pedraza 1209 * @access public 1210 * @return void 1211 */ 1212 function delete_related() 1213 { 1214 $related_article = urldecode($_GET['delete_related']); 1215 $this->so->delete_related($this->article_id, $related_article); 1216 $GLOBALS['phpgw']->historylog->add('DR', $this->article_id, $related_article, ''); 1217 } 1218 1219 /** 1220 * Adds question to database 1221 * 1222 * @author Alejandro Pedraza 1223 * @access public 1224 * @return int Numbers of lines affected (should be 1, if not there's an error) 1225 */ 1226 function add_question() 1227 { 1228 $data = array(); 1229 $data['summary'] = get_var('summary', 'POST'); 1230 $data['details'] = get_var('details', 'POST'); 1231 $data['cat_id'] = (int)get_var('cat_id', 'POST', 0); 1232 $publish = ($this->admin_config['publish_questions'] == 'True')? True : False; 1233 return $this->so->add_question($data, $publish); 1234 } 1235 1236 /** 1237 * Returns question 1238 * 1239 * @author Alejandro Pedraza 1240 * @access public 1241 * @param int $q_id Question id 1242 * @return array Question 1243 */ 1244 function get_question($q_id) 1245 { 1246 $question = $this->so->get_question($q_id); 1247 $username = $GLOBALS['phpgw']->accounts->get_account_name($question['user_id'], $lid, $fname, $lname); 1248 $question['username'] = $fname . ' ' . $lname; 1249 $question['creation'] = $GLOBALS['phpgw']->common->show_date($question['creation'], $GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat']); 1250 return $question; 1251 } 1252 1253 /** 1254 * Mails article 1255 * 1256 * @author Alejandro Pedraza 1257 * @access public 1258 * @param array $article_contents 1259 * @return string Success or error message 1260 */ 1261 function mail_article($article_contents) 1262 { 1263 // check address syntaxis 1264 $recipient = get_var('recipient', 'POST'); 1265 $reply_to = get_var('reply', 'POST', 0); 1266 $theresults = ereg("^[^@ ]+@[^@ ]+\.[^@ \.]+$", $recipient, $trashed); 1267 if (!$theresults) return 'mail_err'; 1268 1269 $GLOBALS['phpgw']->send = CreateObject('phpgwapi.send'); 1270 $GLOBALS['phpgw']->send->From = $GLOBALS['phpgw_info']['user']['email']; 1271 $GLOBALS['phpgw']->send->FromName = $GLOBALS['phpgw_info']['user']['fullname']; 1272 if ($reply_to) $GLOBALS['phpgw']->send->AddReplyTo($reply_to); 1273 $GLOBALS['phpgw']->send->AddAddress($recipient); 1274 $GLOBALS['phpgw']->send->Subject = get_var('subject', 'POST'); 1275 $GLOBALS['phpgw']->send->Body = get_var('txt_message', 'POST', lang('E-GroupWare Knowledge Base article attached')); 1276 $GLOBALS['phpgw']->send->AddStringAttachment($article_contents, lang('article').'.html', 'base64', 'text/html'); 1277 $message = ''; 1278 if (!$GLOBALS['phpgw']->send->Send()) 1279 { 1280 $message = lang('Your message could not be sent!') . '<br>' . lang('The mail server returned:') . htmlspecialchars($GLOBALS['phpgw']->send->ErrorInfo); 1281 } 1282 if ($message) return $message; 1283 return 'mail_ok'; 1284 } 1285 1286 /** 1287 * Stop execution and show error message 1288 * 1289 * @author Alejandro Pedraza 1290 * @access public 1291 * @param string $error_msg Error message to translate and show 1292 * @return void 1293 */ 1294 function die_peacefully($error_msg) 1295 { 1296 if (!$this->navbar_shown) 1297 { 1298 $GLOBALS['phpgw']->common->phpgw_header(); 1299 echo parse_navbar(); 1300 } 1301 echo "<div style='text-align:center; font-weight:bold'>" . lang($error_msg) . "</div>"; 1302 $GLOBALS['phpgw']->common->phpgw_footer(); 1303 die(); 1304 } 1305 } 1306 ?>
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 |