| [ Index ] |
|
Code source de Plume CMS 1.2.2 |
1 <?php 2 /* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 3 /* 4 # ***** BEGIN LICENSE BLOCK ***** 5 # This file is part of Plume CMS, a website management application. 6 # Copyright (C) 2001-2005 Loic d'Anterroches and contributors. 7 # 8 # Plume CMS is free software; you can redistribute it and/or modify 9 # it under the terms of the GNU General Public License as published by 10 # the Free Software Foundation; either version 2 of the License, or 11 # (at your option) any later version. 12 # 13 # Plume CMS is distributed in the hope that it will be useful, 14 # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 # GNU General Public License for more details. 17 # 18 # You should have received a copy of the GNU General Public License 19 # along with this program; if not, write to the Free Software 20 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 # 22 # ***** END LICENSE BLOCK ***** */ 23 24 require_once dirname(__FILE__).'/class.l10n.php'; 25 require_once dirname(__FILE__).'/class.resource.php'; 26 require_once dirname(__FILE__).'/class.basicmanager.php'; 27 require_once dirname(__FILE__).'/class.user.php'; 28 require_once dirname(__FILE__).'/class.article.php'; 29 require_once dirname(__FILE__).'/class.news.php'; 30 31 class Manager extends BasicManager 32 { 33 var $con = null; 34 var $user = null; 35 36 /** 37 * Constructor. 38 * Depending on the context, a user is automatically created 39 * from the session data. 40 */ 41 function Manager() 42 { 43 $this->con =& pxDBConnect(); 44 45 if ('manager' == config::f('context')) { 46 //create a user from the session 47 $this->user = new User(); 48 $this->user->synchronize(); 49 $this->l10n = new l10n($this->user->lang); 50 } 51 } 52 53 54 /** 55 * Set a message. 56 * 57 * @param string Message 58 */ 59 function setMessage($msg) 60 { 61 $_SESSION['message'] = $msg; 62 } 63 64 /** 65 * Get the message 66 * 67 * The message is poped. 68 * 69 * @return string Message 70 */ 71 function getMessage() 72 { 73 $m = ''; 74 if (!empty($_SESSION['message'])) { 75 $m = $_SESSION['message']; 76 $_SESSION['message'] = ''; 77 unset($_SESSION['message']); 78 } 79 return $m; 80 } 81 82 /* Functions used in the manager to populate data for the 83 * forms etc... 84 * ------------------------------------------------------------ */ 85 86 /** 87 * If $addallcat set to true a special "All the categories" is also 88 * given. Used for the listing of the resources in the manager. 89 */ 90 function getArrayCategories($addallcat=false) 91 { 92 $cats = $this->getCategories(); 93 $arry_cat = array(); 94 if ($addallcat) 95 $arry_cat[ __('All the categories')]='allcat'; 96 while (!$cats->EOF()) { 97 $name = $cats->f('category_name'); 98 $name .= ' ('.$cats->f('category_path').')'; 99 if (isGhostCat($cats->f('category_path'))) 100 $name .= ' ['. __('Hidden category').']'; 101 $arry_cat[$name] = $cats->f('category_id'); 102 $cats->moveNext(); 103 } 104 return $arry_cat; 105 } 106 107 /** 108 * Get the list of months for the drop-down selectors. 109 * 110 * @param string type of resource 111 * @param int category id 112 * @param bool (true) add the all dates choice (true by default!!!) 113 * @return array($first, $last, array of months + year) 114 */ 115 function getArrayMonths($type='', $cat_id='', $addalldates=true) 116 { 117 $arry_months = array(); 118 if ($addalldates) 119 $arry_months[__('All the dates')] = 'alldate'; 120 $last = ''; 121 $k = ''; 122 //getAllDates returns the values in time DESC order 123 foreach ($this->getAllDates('m', $type, $cat_id) as $k => $v) { 124 if (empty($last)) $last = $k; 125 $arry_months[if_utf8(strftime('%B %Y',date::unix($k)))] = $k; 126 } 127 return array($k, $last, $arry_months); 128 } 129 130 /** 131 * Get the list of months for the drop-down selectors. 132 * 133 * @return array Months 134 */ 135 function getArrayOnlyMonths() 136 { 137 $arry_months = array(); 138 for ($i=1; $i<=12; $i++) { 139 $month = sprintf('%02d', $i); 140 $arry_months[if_utf8(strftime('%B', strtotime('2000-'.$month.'-01')))] = $month; 141 } 142 return $arry_months; 143 } 144 145 146 /** 147 * Get the array of possible resource status. 148 * 149 * @return array Resource status 150 */ 151 function getArrayResStatus() 152 { 153 $arry_status = array(); 154 $arry_status[__('In edition')] = PX_RESOURCE_STATUS_INEDITION; 155 $arry_status[__('Waiting for validation')] = PX_RESOURCE_STATUS_TOBEVALIDATED; 156 if (auth::asLevel(PX_USER_LEVEL_ADVANCED, $_SESSION['website_id'])) { 157 $arry_status[__('On-line')] = PX_RESOURCE_STATUS_VALIDE; 158 } 159 $arry_status[__('Off-line')] = PX_RESOURCE_STATUS_OFFLINE; 160 return $arry_status; 161 } 162 163 /** 164 * Get the array of possible comment status. 165 * 166 * @return array Comment status 167 */ 168 function getArrayCommentStatus() 169 { 170 $arry_status = $this->getArrayResStatus(); 171 $arry_status[__('Junk')] = PX_RESOURCE_STATUS_JUNK; 172 unset($arry_status[__('In edition')]); 173 return $arry_status; 174 } 175 176 /** 177 * Get the array of possible support of the comment 178 * for a resource. 179 * 180 * @return array Comment support 181 */ 182 function getArrayCommentSupport() 183 { 184 $arry_status = array(__('Comments open') => 1, 185 __('Comments closed') => 3); 186 return $arry_status; 187 } 188 189 /* ===================================================================== * 190 * * 191 * Management of the resources * 192 * * 193 * ===================================================================== */ 194 195 /** 196 * Check if a user has the rights to edit a resource. 197 * 198 * @param &object Resource object 199 * @return bool 200 */ 201 function asRightToEdit(&$res) 202 { 203 if (auth::asLevel(PX_USER_LEVEL_ADVANCED, $res->f('website_id')) 204 || ($res->f('user_id') == $this->user->getId() 205 && $res->f('status') != PX_RESOURCE_STATUS_VALIDE) 206 ) { 207 return true; 208 } else { 209 return false; 210 } 211 } 212 213 214 /** 215 * Load a resource for the current website. 216 * As the resource object has a type, all the type checking is done 217 * by the object. Only the website checking is done by this method. 218 * 219 * @param &object Resource object in which the resource will be set 220 * @param int Resource id 221 * @return bool Success 222 */ 223 function loadResource(&$res, $id) 224 { 225 if (false === $res->load($id)) 226 return false; 227 if ($res->f('website_id') != $this->user->website) 228 return false; 229 230 return true; 231 } 232 233 234 235 236 /** 237 * Add a resource in a category. 238 * 239 * @param &object Reference of the resource object 240 * @param int Category id 241 * @param int Type of category (PX_RESOURCE_CATEGORY_MAIN) 242 * @return bool Success 243 */ 244 function addResourceInCategory(&$res, $catid, 245 $type=PX_RESOURCE_CATEGORY_MAIN) 246 { 247 //check the rights 248 if (!$this->asRightToEdit($res)) { 249 $this->setError(__('Error: You do not have the correct rights to edit this resource.'), 400); 250 return false; 251 } 252 if (!$res->addToCategory($catid, $type)) { 253 $this->bulkSetError($res->error()); 254 return false; 255 } 256 $this->triggerMassUpdate(); 257 return true; 258 } 259 260 /** 261 * Remove a resource from a category 262 * 263 * @param &object Reference of the resource object 264 * @param int Category id 265 * @return bool Success 266 */ 267 function removeResourceFromCategory(&$res, $catid) 268 { 269 //check the rights 270 if (!$this->asRightToEdit($res)) { 271 $this->setError(__('Error: You do not have the correct rights to edit this resource.'), 400); 272 return false; 273 } 274 if (!$res->removeFromCategory($catid)) { 275 $this->bulkSetError($res->error()); 276 return false; 277 } 278 $this->triggerMassUpdate(); 279 return true; 280 } 281 282 283 284 285 286 287 /* ===================================================================== * 288 * * 289 * Utility functions * 290 * * 291 * ===================================================================== */ 292 293 /** 294 * Trigger mass update for a given website. 295 * If no website given, use the currently managed by the user. 296 * 297 * @param string Website id ('') 298 * @return bool true 299 */ 300 function triggerMassUpdate($website='') 301 { 302 if (empty($website)) $website = config::f('website_id'); 303 @touch(dirname(__FILE__).'/../cache/'.$website.'/MASS_UPDATE', time()); 304 @chmod(dirname(__FILE__).'/../cache/'.$website.'/MASS_UPDATE', 0666); 305 } 306 307 /** 308 * Index a resource. 309 * 310 * @param &object Resource object 311 * @return bool Success 312 */ 313 function indexResource(&$res) 314 { 315 include_once dirname(__FILE__).'/class.search.php'; 316 317 $s = new Search($this->con, $res->f('website_id')); 318 $s->index($res->getAsString(), $res->f('resource_id')); 319 if (false !== $s->error()) { 320 return false; 321 } 322 return true; 323 } 324 325 /** 326 * Remove a resource from the index. 327 * 328 * @param &object Resource object 329 * @return bool Success 330 */ 331 function indexRemove(&$res) 332 { 333 include_once dirname(__FILE__).'/class.search.php'; 334 335 $s = new Search($this->con, $res->f('website_id')); 336 $s->remove_from_index($res->f('resource_id')); 337 if (false !== $s->error()) { 338 return false; 339 } 340 return true; 341 } 342 343 344 /** 345 * Get the list of subtypes, ordered by type 346 * 347 * @param int Optional, limit the search to one subtype 348 * @param string Optional, limit the search to a type of resource 349 * @return object RecordSet 350 */ 351 function getSubTypes($id='', $type='') 352 { 353 $r = 'SELECT * FROM '.$this->con->pfx. 354 'subtypes WHERE website_id=\''.$this->user->website.'\''; 355 356 if (!empty($id)) 357 $r .= ' AND subtype_id=\''.$this->con->escapeStr($id).'\''; 358 if (!empty($type)) 359 $r .= ' AND type_id=\''.$this->con->escapeStr($type).'\''; 360 361 $r .= ' ORDER BY type_id'; 362 if (($rs = $this->con->select($r)) !== false) { 363 return $rs; 364 } else { 365 $this->setError('MySQL: '.$this->con->error(), 500); 366 return false; 367 } 368 } 369 370 /** 371 * Get an array of the subtypes. 372 * Used in the display of the subtypes. 373 * 374 * @param string Type of resource ('') 375 * @param int Limit to the one having the given extra data set (0) 376 * @return array Ready to use in the display 377 */ 378 function getSubTypesArray($type='', $extra=0) 379 { 380 $subtypes = $this->getSubTypes('', $type); 381 $arry_subtypes = array(); 382 383 while (!$subtypes->EOF()) { 384 if (0 == $extra or $subtypes->f('subtype_extra'.$extra) == 1) { 385 $arry_subtypes[$subtypes->f('subtype_name')] = $subtypes->f('subtype_id'); 386 } 387 $subtypes->moveNext(); 388 } 389 return $arry_subtypes; 390 } 391 392 393 394 /** 395 Check if a subtype is used 396 @return bool True if in use 397 @param int Subtype id 398 */ 399 function isSubTypeUsed($id) 400 { 401 $req = 'SELECT COUNT(*) AS total FROM '.$this->con->pfx.'resources WHERE subtype_id=\''.$this->con->escapeStr($id).'\''; 402 if (($rs = $this->con->select($req)) === false) { 403 $this->setError('MySQL: '.$this->con->error(), 500); 404 return true; //by security set as used 405 } 406 if (0 == (int) $rs->f('total')) { 407 return false; 408 } 409 return true; 410 } 411 412 /** 413 Delete a subtype 414 @return bool Success or not 415 @param int Subtype id 416 */ 417 function deleteType($id) 418 { 419 if ($this->isSubTypeUsed($id)) { 420 $this->setError(__('Impossible to delete this type as it is in use.'), 400); 421 return false; 422 } 423 $delReq = 'DELETE FROM '.$this->con->pfx.'subtypes WHERE subtype_id=\''.$this->con->escapeStr($id).'\''; 424 if (!$this->con->execute($delReq)) { 425 $this->setError('MySQL: '.$this->con->error(), 500); 426 return false; 427 } 428 429 return true; 430 } 431 432 /** 433 Save/add the type 434 435 @return int Id of the subtype (false if error) 436 @param int Id of the subtype (empty if adding a new) 437 @param string Type id 'news' or 'articles' 438 @param string Name of the subtype 439 @param string Template file 440 @param int Time for the cache 441 @param string Extra information 1 442 @param string Extra information 2 443 @param string Website id (''), use the current website id from the user object if empty 444 */ 445 function saveType($id, $type_id, $name, $template, $cachetime, $extra1, $extra2, $website='') 446 { 447 if (empty($name)) { 448 $this->setError(__('You must provide a name.'), 400); 449 } 450 if (empty($template)) { 451 $this->setError(__('You must provide a template.'), 400); 452 } 453 if (!preg_match('/^[-]{0,1}[0-9]+$/', $cachetime)) { 454 $this->setError(__('The cachetime must be an integer.'), 400); 455 } 456 // if errors we go out. 457 if (false !== $this->error()) { 458 return false; 459 } 460 461 $new = false; 462 if (empty($id)) { 463 // get a new id 464 $new = true; 465 $req = 'INSERT INTO '; 466 } else { 467 $req = 'UPDATE '; 468 } 469 if (empty($website)) $website = $this->user->website; 470 471 // subtype_id=\''.$this->con->escapeStr($id).'\', 472 $req .= $this->con->pfx.'subtypes SET 473 type_id=\''.$this->con->escapeStr($type_id).'\', 474 website_id=\''.$this->con->escapeStr($website).'\', 475 subtype_name=\''.$this->con->escapeStr($name).'\', 476 subtype_template=\''.$this->con->escapeStr($template).'\', 477 subtype_cachetime=\''.$this->con->escapeStr($cachetime).'\', 478 subtype_extra1=\''.$this->con->escapeStr($extra1).'\', 479 subtype_extra2=\''.$this->con->escapeStr($extra2).'\''; 480 481 if (!$new) { 482 $req .= ' WHERE subtype_id=\''.$this->con->escapeStr($id).'\''; 483 } 484 485 if (!$this->con->execute($req)) { 486 $this->setError('MySQL: '.$this->con->error(), 500); 487 return false; 488 } 489 if (empty($id)) $id = $this->con->getLastID(); 490 $this->triggerMassUpdate(); 491 492 return $id; 493 } 494 495 496 497 function saveUser($id, $username, $password, $realname, $email, $pubemail, $authwebs = null) 498 { 499 if ($id == 1 && $this->user->f('user_id') != 1) { 500 $this->setError(__('Error: You do not have the rights to modify this user.'), 400); 501 return false; 502 } 503 if (preg_match('/[^A-Za-z0-9]/', $username)) { 504 $this->setError(__('Error: The login is not valid, only letters and digits allowed.'), 400); 505 return false; 506 } 507 // get the user with the same username if available 508 if (false === ($user = $this->getUserById($username))) { 509 return false; 510 } 511 512 // add a user check 513 if (empty($id)) { 514 if ($user->nbRow() > 0) { 515 $this->setError(__('Error: This login is already used, please use another one.'), 400); 516 return false; 517 } 518 if (strlen($password) == 0) { 519 $this->setError(__('Error: You need to give a password.'), 400); 520 return false; 521 } 522 } else { 523 if ($user->nbRow() > 0 && $user->f('user_id') != $id) { 524 $this->setError(__('Error: This login is already used, please use another one.'), 400); 525 return false; 526 } 527 } 528 if (strlen($realname) == 0) { 529 $this->setError(__('Error: You need to give a name.'), 400); 530 return false; 531 } 532 if (empty($id)) { 533 $insReq = 'INSERT INTO '; 534 } else { 535 $insReq = 'UPDATE '; 536 } 537 $insReq .= $this->con->pfx.'users SET 538 user_username = \''.$this->con->escapeStr($username).'\', 539 user_realname = \''.$this->con->escapeStr($realname).'\', 540 user_email = \''.$this->con->escapeStr($email).'\', 541 user_pubemail = \''.$this->con->escapeStr($pubemail).'\''; 542 if (!empty($password)) { 543 $insReq .= ', user_password = \''.$this->con->escapeStr(md5($password)).'\''; 544 } 545 if (empty($id)) { 546 $insReq .= ', user_creationdate = \''.date::stamp().'\''; 547 } else { 548 $insReq .= ' WHERE user_id = \''.$this->con->escapeStr($id).'\''; 549 } 550 if (!$this->con->execute($insReq)) { 551 $this->setError('MySQL: '.$this->con->error(), 500); 552 return false; 553 } 554 555 if (empty($id)) $id = $this->con->getLastID(); 556 557 if (!is_null($authwebs)) { 558 // update the rights for the websites 559 $delReq = 'DELETE FROM '.$this->con->pfx.'grants WHERE user_id = \''.$this->con->escapeStr($id).'\''; 560 if (!$this->con->execute($delReq)) { 561 $this->setError('MySQL: '.$this->con->error(), 500); 562 return false; 563 } 564 foreach ($authwebs as $site => $score) { 565 $insReq = 'INSERT INTO '.$this->con->pfx.'grants SET 566 user_id = \''.$this->con->escapeStr($id).'\', 567 website_id = \''.$this->con->escapeStr($site).'\', 568 level = \''.$this->con->escapeStr($score).'\''; 569 if (!$this->con->execute($insReq)) { 570 $this->setError('MySQL: '.$this->con->error(), 500); 571 return false; 572 } 573 } 574 } 575 if (!empty($id) and $id == $this->user->f('user_id')) { 576 $this->user->load($id); 577 $this->user->synchronize(PX_USER_SYNCHRO_TO_SESSION); 578 } 579 return $id; 580 } 581 582 583 function delUser($id) 584 { 585 if (false === ($user = $this->getUserById($id))) { 586 return false; 587 } 588 $res = $user->getListResources(); 589 if ($res->nbRow() > 0 || $id == 1) { 590 $this->setError(__('Error: This user cannot be deleted.'), 400); 591 return false; 592 } 593 $delReq = 'DELETE FROM '.$this->con->pfx.'grants WHERE user_id = \''.$this->con->escapeStr($id).'\''; 594 if (!$this->con->execute($delReq)) { 595 $this->setError('MySQL: '.$this->con->error(), 500); 596 return false; 597 } 598 $delReq = 'DELETE FROM '.$this->con->pfx.'users WHERE user_id = \''.$this->con->escapeStr($id).'\''; 599 if (!$this->con->execute($delReq)) { 600 $this->setError('MySQL: '.$this->con->error(), 500); 601 return false; 602 } 603 return true; 604 605 } 606 607 608 /** 609 * Save a site or create a new one. 610 * 611 * If $id is empty, a new site is created and the 612 * log of the creation is set in &$log_new_site. 613 * The log is pure HTML ready for display. 614 */ 615 function saveSite($id, $name, $description, $sitelang, $website_address, $website_path, $xmedia_name, $support_comments, $status_comments, &$log_new_site, $force_new_id='') 616 { 617 include_once dirname(__FILE__).'/../extinc/class.configfile.php'; 618 include_once dirname(__FILE__).'/class.checklist.php'; 619 include_once dirname(__FILE__).'/class.files.php'; 620 include_once dirname(__FILE__).'/lib.auth.php'; 621 global $_PX_config; 622 623 $update = (empty($id)) ? false : true; 624 $xmedia_path = ''; 625 if (!empty($website_path) && !empty($xmedia_name)) { 626 $xmedia_path = files::real_path($website_path).'/'.$xmedia_name; 627 } 628 $parsedurl = parse_url($website_address); 629 630 if ($update) { 631 // check the data if $update 632 if (0 == strlen(trim($id))) { 633 $this->setError(__('Error: Internal error, please report your actions leading to this error message.'),500); 634 } 635 if (preg_match('/[^A-Za-z0-9]/', $id)) { 636 $this->setError(sprintf(__('Error: The id of the website "%s" can only contain letters and numbers.'), htmlspecialchars($id)),500); 637 } 638 } 639 640 files::createfolder($xmedia_path); 641 files::createfolder($website_path); 642 643 if (empty($xmedia_path) or !file_exists($xmedia_path)) { 644 $this->setError(sprintf(__('Error: File and image folder %s not available. Check the name you gave.'), $xmedia_path), 400); 645 } 646 if (!empty($xmedia_path) && file_exists($xmedia_path) && !is_writable($xmedia_path)) { 647 $this->setError(sprintf(__('Error: No write access to the file and image folder %s. Check the name you gave.'), $xmedia_path), 400); 648 } 649 if (empty($website_path) or !file_exists($website_path)) { 650 $this->setError(sprintf(__('Error: The document root folder %s is not available.'), $website_path), 400); 651 } 652 if (!empty($website_path) && file_exists($website_path) && !is_writable($website_path)) { 653 $this->setError(sprintf(__('Error: No write access to the root folder %s.'), $website_path), 400); 654 } 655 if (2 != strlen(trim($sitelang))) { 656 $sitelang = 'en'; 657 } 658 if (0 == strlen(trim($website_address))) { 659 $this->setError(__('Error: You must give a website address.'),400); 660 } 661 if (0 == strlen(trim($description))) { 662 $this->setError(__('Error: You must give a description.'),400); 663 } 664 if ((0 != strlen(trim($website_address))) && (!is_array($parsedurl) 665 or empty($parsedurl['scheme']) 666 or !preg_match('/(http|https)/', $parsedurl['scheme']) 667 or empty($parsedurl['host']) 668 )) { 669 $this->setError(__('Error: You must provide a valid website address.'),400); 670 } 671 if (0 == strlen(trim($name))) { 672 $this->setError(__('Error: You must give a name.'),400); 673 } 674 675 // if errors, break 676 if (false !== $this->error(true, false)) { 677 return false; 678 } 679 680 // Generate all the needed information for at least the update 681 $xmedia_path = files::real_path($xmedia_path); 682 $website_path = files::real_path($website_path); 683 $reurl = (!empty($parsedurl['path'])) ? $parsedurl['path'] : ''; 684 685 $reurl = preg_replace('#(/)+$#', '', $reurl); 686 $website_path = preg_replace('#(/)+$#', '', $website_path); 687 $xmedia_reurl = preg_replace('#(/)+$#', '', $reurl.'/'.$xmedia_name); 688 689 $domain = trim($parsedurl['host']); 690 $secure = (strtolower($parsedurl['scheme']) == 'https'); 691 692 // get the website with this id 693 if (empty($id)) { 694 if (!empty($force_new_id)) { 695 //to be able to force the first site with the "default" id. 696 $id = $force_new_id; 697 } else { 698 //new id from the address (without http but the s) 699 $id = substr(preg_replace('/[^A-Za-z0-9]/', '', $website_address), 4); 700 } 701 } 702 $site = $this->getSites($id); 703 if ($update) { 704 if (!file_exists(dirname(__FILE__).'/../conf/configweb_'.$id.'.php') || !is_writable(dirname(__FILE__).'/../conf/configweb_'.$id.'.php')) { 705 $this->setError(sprintf(__('Error: The configuration file %s is not writeable.'), files::real_path(dirname(__FILE__).'/../conf/').'/configweb_'.$id.'.php'), 500); 706 return false; 707 } 708 if ($site->nbRow() == 0) { 709 $this->setError(__('This site is not available.') , 400); 710 return false; 711 } 712 713 } else { 714 // check if this website already exists 715 if ($site->nbRow() >= 1) { 716 $this->setError(__('Error: Id already used.') , 400); 717 return false; 718 } 719 // need to create a new file 720 // copy paste the config_default.php 721 if (!is_writable(dirname(__FILE__).'/../conf/')) { 722 $this->setError(sprintf(__('Error: The configuration folder %s is not writeable.'), 723 files::real_path(dirname(__FILE__).'/../conf/')), 500); 724 return false; 725 } 726 $source_file = dirname(__FILE__).'/../conf/configweb_default.copy.php'; 727 $destination_file = dirname(__FILE__).'/../conf/configweb_'.$id.'.php'; 728 if (file_exists($destination_file)) { 729 @unlink ($destination_file); 730 } 731 if (!copy($source_file, $destination_file)) { 732 $this->setError(__('Error: Impossible to create the configuration file.') , 500); 733 return false; 734 } 735 @chmod($destination_file, 0666); 736 737 } 738 // open file for edition of the data 739 $cfg = new configfile(dirname(__FILE__).'/../conf/configweb_'.$id.'.php'); 740 $cfg->prefix = '_PX_website_config'; 741 $cfg->editVar('website_id', (string) $id); 742 $cfg->editVar('xmedia_root', (string) $xmedia_path); 743 $cfg->editVar('domain', (string) $domain); 744 $cfg->editVar('rel_url', (string) $reurl); 745 $cfg->editVar('rel_url_files', (string) $xmedia_reurl); 746 $cfg->editVar('secure', (bool) $secure); 747 $cfg->editVar('lang', (string) $sitelang); 748 $cfg->editVar('comment_support', (int) $support_comments); 749 $cfg->editVar('comment_default_status', (int) $status_comments); 750 if (!$cfg->saveFile()) { 751 $this->setError(__('Error: Impossible to create the configuration file.') , 500); 752 return false; 753 } 754 // no update or add in the db 755 if ($update) { 756 $insReq = 'UPDATE '.$this->con->pfx.'websites SET '; 757 } else { 758 $insReq = 'INSERT INTO '.$this->con->pfx.'websites SET 759 website_id =\''.$this->con->escapeStr($id).'\', 760 website_startdate = \''.date::stamp().'\', '; 761 } 762 $securestring = $secure ? 's' : ''; 763 $insReq .= 'website_name = \''.$this->con->escapeStr($name).'\', '; 764 $insReq .= 'website_url = \''.$this->con->escapeStr('http'.$securestring.'://'.$domain.$reurl).'\', '; 765 $insReq .= 'website_reurl = \''.$this->con->escapeStr($reurl).'\', '; 766 $insReq .= 'website_path = \''.$this->con->escapeStr('').'\', '; 767 $insReq .= 'website_xmedia_reurl = \''.$this->con->escapeStr($xmedia_reurl).'\', '; 768 $insReq .= 'website_xmedia_path = \''.$this->con->escapeStr($xmedia_path).'\', '; 769 $insReq .= 'website_description = \''.$this->con->escapeStr($description).'\' '; 770 if ($update) { 771 $insReq .= 'WHERE website_id =\''.$this->con->escapeStr($id).'\''; 772 } 773 774 if (!$this->con->execute($insReq)) { 775 $this->setError('MySQL: '.$this->con->error(), 500); 776 return false; 777 } 778 779 780 if (!$update) { 781 // As this user adds the site, give him root access to it 782 $insReq = 'INSERT INTO '.$this->con->pfx.'grants SET 783 website_id =\''.$this->con->escapeStr($id).'\', 784 user_id = \''.$this->con->escapeStr($this->user->f('user_id')).'\', 785 level = \''.PX_AUTH_ADMIN.'\''; 786 787 if (!$this->con->execute($insReq)) { 788 $this->setError('MySQL: '.$this->con->error(), 500); 789 return false; 790 } 791 792 // Add the root category 793 $hp_title = __('Home Page'); 794 $hp_desc = __('Root category, that plays the role of homepage.'); 795 $hp_kw = __('homepage, index, default'); 796 $insReq = 'INSERT INTO '.$this->con->pfx.'categories SET 797 website_id=\''.$this->con->escapeStr($id).'\', 798 category_name=\''.$this->con->escapeStr($hp_title).'\', 799 category_description=\''.$this->con->escapeStr($hp_desc).'\', 800 category_keywords=\''.$this->con->escapeStr($hp_kw).'\', 801 category_path=\'/\', 802 category_publicationdate=\''.date::stamp().'\', 803 category_creationdate=\''.date::stamp().'\', 804 category_enddate=99991231235959, 805 category_template=\'category_homepage.php\', 806 category_type=\'default\', 807 category_cachetime=86400'; 808 if (!$this->con->execute($insReq)) { 809 $this->setError('MySQL: '.$this->con->error(), 500); 810 return false; 811 } 812 if (false == ($catid = $this->con->getLastID())) { 813 $this->setError('MySQL: '.$this->con->error(), 500); 814 return false; 815 } 816 $updReq = 'UPDATE '.$this->con->pfx.'categories SET category_parentid=\''.$this->con->escapeStr($catid).'\' 817 WHERE category_id = \''.$this->con->escapeStr($catid).'\''; 818 819 if (!$this->con->execute($updReq)) { 820 $this->setError('MySQL: '.$this->con->error(), 500); 821 return false; 822 } 823 824 // Add 2 default subtypes 825 if (false === $this->saveType('', 'articles', __('Article'), 'resource_article.php', 3600, '', '', $id)) { 826 return false; 827 } 828 if (false === $this->saveType('', 'news', __('News'), 'resource_news.php', 3600, '1', '', $id)) { 829 return false; 830 } 831 832 // All the database related work is done. The creation is a 833 // success, we may have error to copy the 834 // files, but they are not erros, only "warnings". 835 // 1- Create the xmedia/thumb folder 836 // 2- Create the xmedia/theme/default folder 837 // 3- Copy folder manager/templates/default/style into 838 // folder created in 2 839 // 4- If id != 'default' copy from the 'default' document 840 // root config.php index.php prepend.php rss.php search.php 841 // into new document root 842 // 5- Edit config.php for $_PX_config['manager_path'] and to 843 // load the good config file. 844 $f = new files(); 845 $checklist = new checklist(); 846 // 1- Create the xmedia/thumb folder 847 $checklist->addTest('thumb-folder', files::is_success($f->createfolder($xmedia_path.'/thumb', 0777)) ? 1 : 2, 848 sprintf(__('Thumbnail folder %s created successfully.'), files::real_path($xmedia_path.'/thumb')), 849 '' /* no error */, 850 sprintf(__('Unable to create the thumbnail folder %s.'), $xmedia_path.'/thumb')); 851 852 // 2- Create the xmedia/theme/default folder 853 $checklist->addTest('theme-folder', (files::is_success($f->createfolder($xmedia_path.'/theme', 0777)) && files::is_success($f->createfolder($xmedia_path.'/theme/default', 0777))) ? 1 : 2, 854 sprintf(__('Theme folder %s created successfully.'), files::real_path($xmedia_path.'/theme/default')), 855 '' /* no error */, 856 sprintf(__('Unable to create the theme folder %s.'), $xmedia_path.'/theme/default')); 857 858 // 3- Copy folder manager/templates/default/style into 859 // folder created in 2 860 $checklist->addTest('content-theme-folder', 861 files::is_success($f->copyfolder(files::real_path(dirname(__FILE__).'/../templates/default/style'), 862 files::real_path($xmedia_path.'/theme/default'))) ? 1 : 2, 863 sprintf(__('Theme files successfully copied from %s to the theme folder.'), files::real_path(dirname(__FILE__).'/../templates/default/style')), 864 '' /* no error */, 865 sprintf(__('Unable to copy the theme files from %s to the theme folder.'), files::real_path(dirname(__FILE__).'/../templates/default/style'))); 866 867 // 4- If id != 'default' copy from the 'default' document root 868 // config.php index.php prepend.php rss.php search.php 869 // into new document root 870 if ('default' != $id) { 871 $checklist->addTest('config-php', 872 files::is_success($f->copyfile(files::real_path(dirname(__FILE__).'/../../config.php'), $website_path.'/config.php')) ? 1 : 2, 873 sprintf(__('Config file successfully copied from %s to the document root folder.'), files::real_path(dirname(__FILE__).'/../../config.php') ), 874 '' /* no error */, 875 sprintf(__('Unable to copy the config file from %s to the document root folder.'), files::real_path(dirname(__FILE__).'/../../config.php') )); 876 877 $checklist->addTest('index-php', 878 files::is_success($f->copyfile(files::real_path(dirname(__FILE__).'/../../index.php'), $website_path.'/index.php')) ? 1 : 2, 879 sprintf(__('Index file successfully copied from %s to the document root folder.'), files::real_path(dirname(__FILE__).'/../../index.php') ), 880 '' /* no error */, 881 sprintf(__('Unable to copy the index file from %s to the document root folder.'), files::real_path(dirname(__FILE__).'/../../index.php') )); 882 883 $checklist->addTest('prepend-php', 884 files::is_success($f->copyfile(files::real_path(dirname(__FILE__).'/../../prepend.php'), $website_path.'/prepend.php')) ? 1 : 2, 885 sprintf(__('Prepend file successfully copied from %s to the document root folder.'), files::real_path(dirname(__FILE__).'/../../prepend.php') ), 886 '' /* no error */, 887 sprintf(__('Unable to copy the prepend file from %s to the document root folder.'), files::real_path(dirname(__FILE__).'/../../prepend.php') )); 888 889 $checklist->addTest('rss-php', 890 files::is_success($f->copyfile(files::real_path(dirname(__FILE__).'/../../rss.php'), $website_path.'/rss.php')) ? 1 : 2, 891 sprintf(__('Rss file successfully copied from %s to the document root folder.'), files::real_path(dirname(__FILE__).'/../../rss.php') ), 892 '' /* no error */, 893 sprintf(__('Unable to copy the rss file from %s to the document root folder.'), files::real_path(dirname(__FILE__).'/../../rss.php') )); 894 895 $checklist->addTest('search-php', 896 files::is_success($f->copyfile(files::real_path(dirname(__FILE__).'/../../search.php'), $website_path.'/search.php')) ? 1 : 2, 897 sprintf(__('Search file successfully copied from %s to the document root folder.'), files::real_path(dirname(__FILE__).'/../../search.php') ), 898 '' /* no error */, 899 sprintf(__('Unable to copy the search file from %s to the document root folder.'), files::real_path(dirname(__FILE__).'/../../search.php') )); 900 901 // 5- Edit config.php for $_PX_config['manager_path'] and to 902 // load the good config file. 903 // open file for edition of the data 904 $cfg = new configfile($website_path.'/config.php'); 905 $cfg->prefix = '_PX_config'; 906 $cfg->editVar('manager_path', (string) files::real_path($_PX_config['manager_path'])); 907 $edit_config_success = 1; 908 if (!$cfg->saveFile()) { 909 $edit_config_success = 2; 910 } else { 911 if (!file_exists($website_path.'/config.php') or !is_writable($website_path.'/config.php')) { 912 $edit_config_success = 2; 913 } else { 914 $config_file = @join('', @file($website_path.'/config.php')); 915 $config_file = preg_replace('/configweb\_([A-Za-z0-9]+)\.php/', 'configweb_'.$id.'.php', $config_file); 916 $open = @fopen($website_path.'/config.php', 'w'); 917 @fwrite($open, $config_file); 918 @fclose($open); 919 } 920 } 921 $checklist->addTest('edit-config-php', $edit_config_success, 922 sprintf(__('Config file %s successfully updated.'), files::real_path($website_path.'/config.php') ), 923 '' /* no error */, 924 sprintf(__('Unable to update the config file %s.'), files::real_path($website_path.'/config.php') )); 925 926 } //end of if not 'default' 927 $path = ('default' != $id) ? 'themes/'.$GLOBALS['_px_theme'].'/images' : '../themes/default/images'; 928 $log_new_site = $checklist->getHtml($path); 929 930 } 931 $this->triggerMassUpdate(); 932 return true; 933 934 } 935 936 function delSite($id) 937 { 938 if (preg_match('/[^A-Za-z0-9]/', $id)) { 939 $this->setError(__('Error: Invalid id, it must contain only letters and digits.'),400); 940 return false; 941 } 942 943 // get the website with this id 944 $site = $this->getSites($id); 945 if ($site->nbRow() == 0) { 946 $this->setError(__('This site is not available.') , 400); 947 return false; 948 } 949 $date = $this->getEarlierDate('m', '', '', $id); 950 if (strlen($date) == 14) { 951 $this->setError(__('Error: The site can only be deleted if empty.') , 400); 952 return false; 953 } 954 955 956 if (!file_exists(dirname(__FILE__).'/../conf/configweb_'.$id.'.php') 957 || !is_writable(dirname(__FILE__).'/../conf/configweb_'.$id.'.php')) { 958 959 $this->setError(sprintf(__('Error: The configuration file %s is not writeable.'), 960 files::real_path(dirname(__FILE__).'/../conf/').'/configweb_'.$id.'.php'), 500); 961 return false; 962 } 963 964 965 $delReq = 'DELETE FROM '.$this->con->pfx.'websites WHERE website_id =\''.$this->con->escapeStr($id).'\''; 966 if (!$this->con->execute($delReq)) { 967 $this->setError('MySQL: '.$this->con->error(), 500); 968 return false; 969 } 970 $delReq = 'DELETE FROM '.$this->con->pfx.'grants WHERE website_id =\''.$this->con->escapeStr($id).'\''; 971 if (!$this->con->execute($delReq)) { 972 $this->setError('MySQL: '.$this->con->error(), 500); 973 return false; 974 } 975 $delReq = 'DELETE FROM '.$this->con->pfx.'userprefs WHERE website_id =\''.$this->con->escapeStr($id).'\''; 976 if (!$this->con->execute($delReq)) { 977 $this->setError('MySQL: '.$this->con->error(), 500); 978 return false; 979 } 980 @unlink(dirname(__FILE__).'/../conf/configweb_'.$id.'.php'); 981 return true; 982 } 983 984 985 /** 986 * Switch the theme of a website. 987 * 988 * @param string Id of the website 989 * @param string New theme for the website 990 * @return bool Success 991 */ 992 function switchSiteTheme($id, $theme) 993 { 994 if (!auth::asLevel(PX_AUTH_ADMIN, $id)) { 995 $this->setError(__('You do not have the rights to edit this website.') , 400); 996 return false; 997 } 998 // get the website with this id 999 $site = $this->getSites($id); 1000 if ($site->nbRow() == 0) { 1001 $this->setError(__('This site is not available.') , 400); 1002 return false; 1003 } 1004 if (preg_match('/[^A-Za-z0-9]/', $theme)) { 1005 $this->setError(__('The theme is invalid. It must contain only letters and digits.'),400); 1006 return false; 1007 } 1008 // Update the configuration file. 1009 include_once dirname(__FILE__).'/../extinc/class.configfile.php'; 1010 $cfg = new configfile(dirname(__FILE__).'/../conf/configweb_'.$id.'.php'); 1011 $cfg->prefix = '_PX_website_config'; 1012 $cfg->editVar('theme_id', (string) $theme); 1013 1014 if (!$cfg->saveFile()) { 1015 $this->setError(__('Impossible to save the configuration file.'), 500); 1016 return false; 1017 } 1018 // Copy the theme css files in the xmedia folder 1019 // Do not check the errors. This is only the style, the user can copy 1020 // by hand if needed. 1021 $f = new files(); 1022 $f->createfolder($site->f('website_xmedia_path').'/theme/'.$theme, 0777); 1023 $f->copyfolder(files::real_path(dirname(__FILE__).'/../templates/'.$theme.'/style'), 1024 files::real_path($site->f('website_xmedia_path').'/theme/'.$theme), 1025 PX_FILES_OVERWRITE_IF_NEWER); 1026 return true; 1027 1028 1029 } 1030 1031 /* ====================================================================== * 1032 * * 1033 * Category Management * 1034 * * 1035 * ====================================================================== * 1036 */ 1037 1038 /** 1039 * Load a category for the current website. 1040 * 1041 * @param &object Category object in which the category will be set 1042 * @param int Category id 1043 * @return bool Success 1044 */ 1045 function loadCategory(&$cat, $id) 1046 { 1047 if (false === $cat->load($id)) { 1048 return false; 1049 } 1050 if ($cat->f('website_id') != $this->user->website) { 1051 return false; 1052 } 1053 return true; 1054 } 1055 1056 1057 /** 1058 * Save a category. 1059 * 1060 * @param &object Category to be saved 1061 * @return Mixed Id of the category or false if error 1062 */ 1063 function saveCategory(&$cat) 1064 { 1065 if (!auth::asLevel(PX_USER_LEVEL_ADVANCED, $cat->f('website_id'))) { 1066 $this->setError(__('You do not have the rights to save a category'), 400); 1067 return false; 1068 } 1069 if (false === $cat->commit()) { 1070 return false; 1071 } 1072 $this->triggerMassUpdate(); 1073 return $cat->f('category_id'); 1074 } 1075 1076 /** 1077 * Remove a category. 1078 * 1079 * @param &object Category to be removed 1080 * @return bool Success 1081 */ 1082 function delCategory(&$cat) 1083 { 1084 if (!auth::asLevel(PX_USER_LEVEL_ADVANCED, $cat->f('website_id'))) { 1085 $this->setError(__('You do not have the rights to remove a category'), 400); 1086 return false; 1087 } 1088 if (false === $cat->remove()) { 1089 $this->bulkSetError($cat->error()); 1090 return false; 1091 } 1092 $this->triggerMassUpdate(); 1093 return true; 1094 } 1095 1096 1097 /* ====================================================================== * 1098 * * 1099 * Resource Management * 1100 * * 1101 * ====================================================================== * 1102 */ 1103 1104 /** 1105 * Check a resource. 1106 * 1107 * Check a resource, set the error of the manager from the results of 1108 * the check, if errors are found. 1109 * 1110 * @param &object Resource object 1111 * @return bool Success 1112 */ 1113 function check(&$res) 1114 { 1115 if (false === $res->check()) { 1116 $this->bulkSetError($res->error()); 1117 return false; 1118 } 1119 return true; 1120 } 1121 1122 /* ====================================================================== * 1123 * * 1124 * News Management * 1125 * * 1126 * ====================================================================== * 1127 */ 1128 1129 /** 1130 * Save a news. 1131 * 1132 * @param &object News object 1133 * @return mixed Id of the news or false 1134 */ 1135 function saveNews(&$news) 1136 { 1137 // first check the integrity of the news 1138 if (true !== $this->check($news)) { 1139 return false; 1140 } 1141 if (true !== $this->asRightToEdit($news)) { 1142 $this->setError(__('Error: You do not have the rights to edit this news.'), 400); 1143 return false; 1144 } 1145 if (false === $news->commit()) { 1146 $this->bulkSetError($news->error()); 1147 return false; 1148 } 1149 $this->indexResource($news); 1150 $this->triggerMassUpdate(); 1151 Hook::run('onNewsSave', array('news' => &$news, 'm' => &$m)); 1152 return $news->f('resource_id'); 1153 } 1154 1155 /** 1156 * Remove a news from the database. 1157 * 1158 * @param &object News object 1159 * @return bool Success 1160 */ 1161 function delNews(&$news) 1162 { 1163 if (true !== $this->asRightToEdit($news)) { 1164 $this->setError(__('Error: You do not have the rights to edit this news.'), 400); 1165 return false; 1166 } 1167 1168 $this->indexRemove($news); 1169 1170 if (false === $news->remove()) { 1171 $this->bulkSetError($news->error()); 1172 return false; 1173 } 1174 1175 $this->triggerMassUpdate(); 1176 return true; 1177 } 1178 1179 1180 /* ====================================================================== * 1181 * * 1182 * Article Management * 1183 * * 1184 * ====================================================================== * 1185 */ 1186 1187 1188 /** 1189 * Save an article. 1190 * 1191 * Automatically add a new or update an old. 1192 * 1193 * @param &object Article object 1194 * @return mixed Id of the article if success, else false 1195 */ 1196 function saveArticle(&$ar) 1197 { 1198 // first check the integrity of the article 1199 if (true !== $this->check($ar)) { 1200 return false; 1201 } 1202 if (true !== $this->asRightToEdit($ar)) { 1203 $this->setError(__('Error: You do not have the rights to edit this article.'), 400); 1204 return false; 1205 } 1206 if (false === $ar->commit()) { 1207 $this->bulkSetError($ar->error()); 1208 return false; 1209 } 1210 $this->indexResource($ar); 1211 $this->triggerMassUpdate(); 1212 Hook::run('onArticleSave', array('art' => &$ar, 'm' => &$m)); 1213 return $ar->f('resource_id'); 1214 } 1215 1216 1217 /** 1218 * Remove an article from the database. 1219 * 1220 * @param &object Article object 1221 * @return bool Success 1222 */ 1223 function delArticle(&$ar) 1224 { 1225 if (true !== $this->asRightToEdit($ar)) { 1226 $this->setError(__('Error: You do not have the rights to edit this article.'), 400); 1227 return false; 1228 } 1229 1230 $this->indexRemove($ar); 1231 1232 if (false === $ar->remove()) { 1233 $this->bulkSetError($ar->error()); 1234 return false; 1235 } 1236 1237 $this->triggerMassUpdate(); 1238 return true; 1239 } 1240 1241 1242 /** 1243 * Check an article page. 1244 * 1245 * Check a page, set the error of the manager from the results of 1246 * the check, if errors are found. 1247 * 1248 * @param &object Article object 1249 * @return bool Success 1250 */ 1251 function checkArticlePage(&$ar) 1252 { 1253 if (false === $ar->checkPage()) { 1254 $this->bulkSetError($ar->error()); 1255 return false; 1256 } 1257 return true; 1258 } 1259 1260 /** 1261 * Save the current page of an article. 1262 * 1263 * @param &object Article object 1264 * @return mixed Id of the page if success else false 1265 */ 1266 function saveArticlePage(&$ar) 1267 { 1268 if (true !== $this->asRightToEdit($ar)) { 1269 $this->setError(__('Error: You do not have the rights to edit this article.'), 400); 1270 return false; 1271 } 1272 if (false === $ar->commitPage()) { 1273 $this->bulkSetError($ar->error()); 1274 return false; 1275 } 1276 $this->indexResource($ar); 1277 $this->triggerMassUpdate(); 1278 return $ar->pages->f('page_id'); 1279 } 1280 1281 /** 1282 * Delete the current page of an article. 1283 * 1284 * @param &object Article object 1285 * @return bool Success 1286 */ 1287 function delArticlePage(&$ar) 1288 { 1289 if (true !== $this->asRightToEdit($ar)) { 1290 $this->setError(__('Error: You do not have the rights to edit this article.'), 400); 1291 return false; 1292 } 1293 if (false === $ar->removePage()) { 1294 $this->bulkSetError($ar->error()); 1295 return false; 1296 } 1297 $this->indexResource($ar); 1298 $this->triggerMassUpdate(); 1299 return true; 1300 } 1301 1302 /* ====================================================================== * 1303 * * 1304 * Comments Management * 1305 * * 1306 * ====================================================================== * 1307 */ 1308 1309 /** 1310 * Check if a user has the rights to edit a comment. 1311 * 1312 * A comment can be edited by a user if: 1313 * - The user is "owner" of the resource associated to the comment. 1314 * - The user is the "owner" of the comment. 1315 * - The user has at least an PX_USER_LEVEL_ADVANCED level. 1316 * 1317 * @param &object Comment object 1318 * @return bool 1319 */ 1320 function asRightToEditComment(&$ct) 1321 { 1322 1323 if (auth::asLevel(PX_USER_LEVEL_ADVANCED, $ct->f('website_id')) 1324 || ($ct->f('comment_user_id') == $this->user->getId()) 1325 || ($ct->f('user_id') == $this->user->getId()) 1326 ) { 1327 return true; 1328 } else { 1329 return false; 1330 } 1331 } 1332 1333 /** 1334 * Get the list of comments in the current website. 1335 * 1336 * @param int Resource id ('') 1337 * @param int Maximum number of comments (0) 1338 * @return mixed Comment object or false if errors. 1339 */ 1340 function getComments($resource_id='', $limit=0) 1341 { 1342 include_once dirname(__FILE__).'/class.comment.php'; 1343 $sql = SQL::getComments($this->user->website, $resource_id, '', 'DESC', $limit); 1344 if (false !== ($ct = $this->con->select($sql, 'Comment'))) { 1345 return $ct; 1346 } else { 1347 $this->setError('MySQL: '.$this->con->error(), 500); 1348 return false; 1349 } 1350 } 1351 1352 /** 1353 * Get a comment in the current website associated to a given resource. 1354 * 1355 * @param int Comment id 1356 * @param int Resource id 1357 * @return mixed Comment object or false if errors. 1358 */ 1359 function getComment($id, $resource_id) 1360 { 1361 include_once dirname(__FILE__).'/class.comment.php'; 1362 $sql = SQL::getCommentById($id, $resource_id); 1363 if (false !== ($ct = $this->con->select($sql, 'Comment'))) { 1364 if ($ct->isEmpty()) { 1365 $this->setError(__('This comment is not available.')); 1366 return false; 1367 } 1368 return $ct; 1369 } else { 1370 $this->setError('MySQL: '.$this->con->error(), 500); 1371 return false; 1372 } 1373 } 1374 1375 1376 /** 1377 * Save a comment. 1378 * 1379 * Automatically add a new or update an old. 1380 * 1381 * @param &object Comment object 1382 * @return mixed Id of the comment if success, else false 1383 */ 1384 function saveComment(&$ct) 1385 { 1386 if (true !== $this->check($ct)) { 1387 return false; 1388 } 1389 if (true !== $this->asRightToEditComment($ct)) { 1390 $this->setError(__('Error: You do not have the rights to edit this comment.'), 400); 1391 return false; 1392 } 1393 if (false === $ct->commit()) { 1394 $this->bulkSetError($ct->error()); 1395 return false; 1396 } 1397 $this->triggerMassUpdate(); 1398 return $ct->f('comment_id'); 1399 } 1400 1401 1402 /** 1403 * Remove a comment from the database. 1404 * 1405 * @param &object Comment object 1406 * @return bool Success 1407 */ 1408 function delComment(&$ct) 1409 { 1410 if (true !== $this->asRightToEditComment($ct)) { 1411 $this->setError(__('Error: You do not have the rights to edit this comment.'), 400); 1412 return false; 1413 } 1414 if (false === $ct->remove()) { 1415 $this->bulkSetError($ct->error()); 1416 return false; 1417 } 1418 $this->triggerMassUpdate(); 1419 return true; 1420 } 1421 1422 1423 /* ====================================================================== * 1424 * * 1425 * Help System Management * 1426 * * 1427 * ====================================================================== * 1428 */ 1429 1430 /** 1431 * Get a help file. Returned as a string containing only the HTML content 1432 * with the good locale and the encoding. 1433 * 1434 * @param string Id of the help to get 1435 * @param string Id of the plugin if the help is from a plugin 1436 * @param bool Get also the title and the id of the help 1437 * @return string The help 1438 */ 1439 function getHelp($id, $plugin='', $getall=false) 1440 { 1441 if (preg_match('/[^a-z_\-]/i', $id) 1442 or preg_match('/[^a-z_\-]/i', $plugin)) { 1443 return ''; 1444 } 1445 $lang = $this->user->lang; 1446 1447 if (empty($plugin)) { 1448 $file = config::f('manager_path'); 1449 } else { 1450 $file = config::f('manager_path').'/tools/'.$plugin; 1451 } 1452 $file .= '/help/'.$lang.'/'.$id.'.html'; 1453 1454 if (false !== ($help = $this->getHelpChapter($file))) { 1455 if ($getall) { 1456 return $help; 1457 } else { 1458 return $help[2]; 1459 } 1460 } else { 1461 return ''; 1462 } 1463 } 1464 1465 /** 1466 * Get all the help files, sorted by file name usefull to list the 1467 * possible themes in the help. 1468 * 1469 * @param string Id of the plugin if the help is from a plugin 1470 * @return array The help list 1471 */ 1472 function getHelpChapters($plugin='') 1473 { 1474 if (strlen($plugin) > 0 && preg_match('/[^a-z_\-]/i', $plugin)) { 1475 return false; 1476 } 1477 $lang = $this->user->lang; 1478 1479 if (empty($plugin)) { 1480 $helpfolder = config::f('manager_path'); 1481 } else { 1482 $helpfolder = config::f('manager_path').'/tools/'.$plugin; 1483 } 1484 $helpfolder .= '/help/'.$lang.'/'; 1485 1486 include_once dirname(__FILE__).'/class.files.php'; 1487 1488 $files = array(); 1489 files::listfiles($helpfolder, $files, '/\.html$/'); 1490 1491 sort($files); 1492 reset($files); 1493 $chapters = array(); 1494 foreach ($files as $file) { 1495 $chapters[] = $this->getHelpChapter($file); 1496 } 1497 return $chapters; 1498 } 1499 1500 /** 1501 * Get the id and the title of a help chapter from the file name and the 1502 * content encoded with the output encoding. 1503 * 1504 * @param string file name 1505 * @return array 0=id 1=title 2=content 1506 */ 1507 function getHelpChapter($file) 1508 { 1509 1510 if (!file_exists($file)) { 1511 $GLOBALS['_PX_debug_data']['help'][] = __('File not found: ').$file; 1512 return false; 1513 } 1514 $id = substr(basename($file), 0, -5); 1515 $html = file($file); 1516 $html[0] = ''; 1517 $htmlfile = implode('', $html); 1518 $title = substr($htmlfile, strpos($htmlfile,'<title>') + strlen('<title>')); 1519 $title = substr($title, 0, strpos($title, '</title>')); 1520 $htmlfile = substr($htmlfile, strpos($htmlfile,'<body>') + strlen('<body>')); 1521 $htmlfile = substr($htmlfile, 0, strpos($htmlfile, '</body>')); 1522 return array($id, $title, $htmlfile); 1523 } 1524 1525 /** 1526 * Returns the contextual help link 1527 * 1528 * @param string chapter, correspond to the file of the help 1529 * @param string section the part to see in the file 1530 * @param string plugin ('') 1531 * @return string Help link 1532 */ 1533 function HelpLink($chapter, $section, $plugin='') 1534 { 1535 $theme = $this->user->getTheme(); 1536 1537 if (strlen($plugin) > 0) $plugin = '&p='.$plugin; 1538 $link = 'help.php?c='.$chapter.$plugin; 1539 $linkpop = $link.'&mode=popup'; 1540 $link .= '#'.$section; 1541 $linkpop .= '#'.$section; 1542 $img = 'themes/'.$theme.'/images/ico_help_small.png'; 1543 $help = '<a title="'.__('Help').'" href="'.$link.'" onclick="popup(\''.$linkpop.'\'); return false;">'. 1544 '<img class="minihelp" src="'.$img.'" alt="'.__('Help').'" /></a>'; 1545 return $help; 1546 } 1547 1548 1549 /** 1550 * Send an email to the users of the website. 1551 * 1552 * @param string Subject of the email 1553 * @param string Content of the email 1554 * @param int Website id 1555 * @param int Minimum level of the user to get the email PX_AUTH_ADVANCED 1556 */ 1557 function sendEmail($subject, $content, $website, $level=PX_AUTH_ADVANCED) 1558 { 1559 $to_emails = array(); 1560 $users = $this->getUsers(); 1561 while(!$users->EOF()) { 1562 if ($users->getWebsiteLevel($website >= $level)) { 1563 $to_emails[] = $users->f('user_email'); 1564 } 1565 $users->moveNext(); 1566 } 1567 foreach ($to_emails as $to_email) { 1568 $email = new Plume_Mail('noreply@plume-cms.net', $to_email, 1569 $subject); 1570 $email->addMessage($content, 'text/plain'); 1571 $email->sendMail(); 1572 } 1573 } 1574 } 1575 1576 1577 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Mon Nov 26 11:57:01 2007 | par Balluche grâce à PHPXref 0.7 |
|