| [ 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 define('PX_RESOURCE_CATEGORY_MAIN', 1); 25 define('PX_RESOURCE_CATEGORY_OTHER', 2); 26 27 define('PX_RESOURCE_CREATOR', 1); 28 define('PX_RESOURCE_CONTRIBUTOR', 2); 29 define('PX_RESOURCE_TRANSLATOR', 3); 30 31 define('PX_RESOURCE_STATUS_VALIDE', 1); 32 define('PX_RESOURCE_STATUS_OFFLINE', 2); 33 define('PX_RESOURCE_STATUS_DEPRECATED', 3); 34 define('PX_RESOURCE_STATUS_INEDITION', 4); 35 define('PX_RESOURCE_STATUS_TOBEVALIDATED', 5); 36 37 38 require_once dirname(__FILE__).'/../extinc/class.recordset.php'; 39 require_once dirname(__FILE__).'/class.category.php'; 40 require_once dirname(__FILE__).'/class.comment.php'; 41 42 /** 43 * A Resource is the basic class from which the news, article, etc. 44 * classes are extended. Take a look both at it and at either 45 * the article or news class to understand the use. 46 */ 47 class Resource extends RecordSet 48 { 49 var $con = null; /**< Connection object. */ 50 var $cats = null; /**< recordset of categories. */ 51 var $authors = null; /**< recordset of authors. */ 52 var $comments = null; /**< List of comments. */ 53 var $isModified = False; /**< is update of the DB needed. */ 54 55 /** 56 * Constructor. 57 */ 58 function Resource($data='') 59 { 60 parent::recordset($data); 61 $this->cats = new Category(); 62 $this->authors = new RecordSet(); 63 $this->comments = new Comment(); 64 $this->isModified = True; 65 } 66 67 /** 68 * Set the default values for the resources. 69 * Should be extended by each resource class to set all the default 70 * values from the preferences. 71 * 72 * @param object User object 73 * @return bool Success 74 */ 75 function setDefaults($user) 76 { 77 $this->setField('description', 78 '='.$user->getPref('content_format')."\n"); 79 $this->setField('enddate', date::EOT()); 80 $this->setField('noenddate', 1); 81 $this->setField('publicationdate', date::stamp()); 82 $this->setField('creationdate', date::stamp()); 83 $this->setField('modifdate', date::stamp()); 84 $this->setField('user_id', $user->f('user_id')); 85 $this->setField('website_id', $user->website); 86 return true; 87 } 88 89 /** 90 * Load all the "associated" data of the resource. 91 * When the Resource object is created from a SQL query against the 92 * `resources` table, only few of the data is available. For 93 * example $this->auhors and $this->cats are not set. This 94 * method do that. A resource object extending Resource should add 95 * its own specific data, like pages for articles. 96 * If an identifier or an id is given, the corresponding resource 97 * is loaded. 98 * 99 * @param mixed identifier or resource id ('') 100 * @return bool Sucess or failure 101 */ 102 function load($id='') 103 { 104 if (empty($id)) { 105 $id = $this->f('resource_id'); 106 } 107 if (!empty($id)) { 108 // SQL::getResourceByIdentifier accepts both the id or the 109 // identifier. If category id is empty, the LEFT JOIN is made 110 // on the main category. 111 $sql = SQL::getResourceByIdentifier($id, $this->f('category_id')); 112 $this->getConnection(); 113 if (($rs = $this->con->select($sql)) !== false) { 114 parent::recordset($rs->getData()); 115 } else { 116 $this->setError('MySQL: '.$this->con->error(), 500); 117 return false; 118 } 119 } 120 if (false === $this->loadCategories()) { 121 return false; 122 } 123 if (false === $this->loadAuthors()) { 124 return false; 125 } 126 if (false === $this->loadComments()) { 127 return false; 128 } 129 $this->isModified = False; 130 return true; 131 } 132 133 /** 134 * Run the onload hook. 135 * 136 * Each type of resource extending Resource must call this function 137 * before returning true after load() 138 */ 139 function runPostLoadHook() 140 { 141 Hook::run('onLoadResource', array('res' => &$this)); 142 } 143 144 /** 145 * Get the categories of a resources. 146 * Save the categories as a RecordSet into $this->categories 147 * 148 * @return bool Success 149 */ 150 function loadCategories() 151 { 152 $this->getConnection(); 153 $r = 'SELECT * FROM '.$this->con->pfx.'categoryasso 154 LEFT JOIN '.$this->con->pfx.'categories ON ' 155 .$this->con->pfx.'categoryasso.category_id=' 156 .$this->con->pfx.'categories.category_id 157 LEFT JOIN '.$this->con->pfx.'websites ON ' 158 .$this->con->pfx.'websites.website_id=' 159 .$this->con->pfx.'categories.website_id 160 WHERE identifier=\''.$this->f('identifier').'\' 161 ORDER BY categoryasso_type ASC'; 162 if (($rs = $this->con->select($r, 'Category')) !== false) { 163 $this->cats = $rs; 164 return true; 165 } else { 166 $this->setError('MySQL: '.$this->con->error(), 500); 167 return false; 168 } 169 } 170 171 /** 172 * Get the path to the resource. 173 * The function is context aware. It means that depending of 174 * the context it will return a full path or not, with nice 175 * urls or the simple format. 176 * 177 * @param string Force type of path ('') 178 * @return string The path 179 */ 180 function getPath($type='') 181 { 182 // Need to get the context: 183 // - 'website': Must return relative path 184 // - 'manager': Must return full path 185 // - 'external': Must return full path (this is the case for external 186 // use of the data, like in an RSS link.) 187 $context = config::f('context'); 188 if ($type == 'fullurl' 189 || $context == 'manager' || $context == 'external') { 190 $base = $this->f('website_url'); 191 } else { 192 $base = $this->f('website_reurl'); 193 } 194 195 //format 196 if (config::f('url_format') == 'simple') { 197 $base .= '/?'; 198 } 199 return $base.$this->f('category_path').$this->f('path'); 200 } 201 202 /** 203 * Get the authors of the resource. 204 * The authors are in the `users` table. The association author -> resource 205 * is done in the `authorasso` table. 206 * 207 * @return bool Success 208 */ 209 function loadAuthors() 210 { 211 $this->getConnection(); 212 $r = 'SELECT * FROM '.$this->con->pfx.'users LEFT JOIN 213 '.$this->con->pfx.'authorasso USING (user_id) 214 WHERE resource_id=\''.$this->f('resource_id').'\' 215 ORDER BY authorasso_type'; 216 if (($rs = $this->con->select($r)) !== false) { 217 $type[PX_RESOURCE_CREATOR] = 'creator'; 218 $type[PX_RESOURCE_CONTRIBUTOR] = 'contributor'; 219 $type[PX_RESOURCE_TRANSLATOR] = 'translator'; 220 while (!$rs->EOF()) { 221 $rs->setField('authorasso',$type[$rs->f('authorasso_type')]); 222 $rs->moveNext(); 223 } 224 $rs->moveStart(); 225 $this->authors = $rs; 226 return true; 227 } else { 228 $this->setError('MySQL: '.$this->con->error(), 500); 229 return false; 230 } 231 } 232 233 234 /** 235 * Get the comments of the resource. 236 * 237 * @return bool Success 238 */ 239 function loadComments() 240 { 241 $this->getConnection(); 242 $status = ''; 243 if (config::f('context') != 'manager') { 244 $status = PX_RESOURCE_STATUS_VALIDE; 245 } 246 $r = SQL::getComments('', $this->f('resource_id'), $status); 247 if (($rs = $this->con->select($r, 'Comment')) !== false) { 248 $this->comments = $rs; 249 return true; 250 } else { 251 $this->setError('MySQL: '.$this->con->error(), 500); 252 return false; 253 } 254 } 255 256 /** 257 * Check if a path is in use. 258 * 259 * Only the path given by the user when creating an article for 260 * example. 261 * 262 * @param string Path 263 * @param string Website id (The one of the current resource 264 * is used if none given) 265 * @return mixed False or id of the resource using it 266 */ 267 function isPathInUse($path, $website='') 268 { 269 if ($website == '') { 270 $website = $this->f('website_id'); 271 } 272 $this->getConnection(); 273 $r = SQL::getResourceByPath($path, $website); 274 if (($rs = $this->con->select($r)) !== false) { 275 if ($rs->nbRow() > 0) { 276 return $rs->f('resource_id'); 277 } else { 278 return false; 279 } 280 } else { 281 $this->setError('MySQL: '.$this->con->error(), 500); 282 return -1; //Equivalent to "path used" 283 } 284 } 285 286 287 /** 288 * Return the content of the resource as a string ready for indexation. 289 * Must be overwritten for each type of resource. 290 * 291 * @param string Format of the string (html, wiki, text) 292 * @return string The content of the news as a string 293 */ 294 function getAsString($format = 'html') 295 { 296 trigger_error('getAsString() not defined for the current resource object.', E_USER_WARNING); 297 return ''; 298 } 299 300 /** 301 * Get a Connection object for the resource. 302 * It reuses the main connexion object. After calling this method 303 * a Connection object is available as $this->con 304 * It is safe to call it many times. 305 */ 306 function getConnection() 307 { 308 if ($this->con === null) $this->con =& pxDBConnect(); 309 } 310 311 312 /** 313 * Get ids of resources with a prefix or not. 314 * 315 * @return array ids 316 * @param string prefix for ids ('') 317 */ 318 function getIDs($str='') 319 { 320 $res = array(); 321 foreach ($this->arry_data as $k => $v) { 322 $res[] = $str.$v['resource_id']; 323 } 324 return $res; 325 } 326 327 /* ===================================================================== * 328 * * 329 * Methods to get data for display and the forms. * 330 * * 331 * ===================================================================== */ 332 333 /** 334 * Get content of a field as text. 335 * No modification of the content is performed. 336 * 337 * @param string Field to get 338 * @param string Member variable name ('') 339 * @param bool Escape the & character (true) 340 * @return string Content 341 */ 342 function getTextContent($field, $var='', $escape=true) 343 { 344 if ($var == '') { 345 if ($escape) { 346 return str_replace('&', '&', $this->f($field)); 347 } 348 return $this->f($field); 349 } else { 350 if ($escape) { 351 return str_replace('&', '&', $this->$var->f($field)); 352 } 353 return $this->$var->f($field); 354 } 355 } 356 357 /** 358 * Get unformatted content of a field. 359 * It removes the content type and returns the content without 360 * parsing. 361 * 362 * @param string Field to get 363 * @param string Member variable name ('') 364 * @return string Content 365 */ 366 function getUnformattedContent($field, $var='') 367 { 368 if ($var == '') { 369 return text::getRawContent($this->f($field)); 370 } else { 371 return text::getRawContent($this->$var->f($field)); 372 } 373 } 374 375 /** 376 * Get parsed content. 377 * If content is wiki, transform it as HTML, etc. 378 * 379 * @param string Field to get 380 * @param string Output format ('html') 381 * @param string Member variable name ('') 382 * @return string Formatted content 383 */ 384 function getFormattedContent($field, $format='html', $var='') 385 { 386 if ($var == '') { 387 return text::parseContent($this->f($field), $format); 388 } else { 389 return text::parseContent($this->$var->f($field), $format); 390 } 391 } 392 393 /** 394 * Get the format of a content. 395 * 396 * @param string Field of the content 397 * @param string Member variable name ('') 398 * @return string Content format 399 */ 400 function getContentFormat($field, $var='') 401 { 402 if ($var == '') { 403 return text::getType($this->f($field)); 404 } else { 405 return text::getType($this->$var->f($field)); 406 } 407 } 408 409 /** 410 * Get date as array. 411 * Returns a date as an array ready to be used in the form::datetime 412 * field. 413 * 414 * @param string Date field 415 * @param string Member variable name ('') 416 * @return array array(h,m,s,M,D,Y) 417 */ 418 function getArrayDate($field, $var='') 419 { 420 if ($var == '') { 421 return date::explode($this->f($field)); 422 } else { 423 return date::explode($this->$var->f($field)); 424 } 425 } 426 427 /** 428 * Returns if a date is at the end of time 429 * 430 * @param string Date field 431 * @param string Member variable name ('') 432 * @return bool Date at end of time 433 */ 434 function isDateEOT($field, $var='') 435 { 436 if ($var == '') { 437 return date::isEOT($this->f($field)); 438 } else { 439 return date::isEOT($this->$var->f($field)); 440 } 441 } 442 443 /* ===================================================================== * 444 * * 445 * Methods modifying data in the database. * 446 * * 447 * ===================================================================== */ 448 449 450 /** 451 * Save the basic data. 452 * The common data are the one available in the `resources` table. 453 * Check the 'article' and 'news' class to see practical implementations. 454 * It is recommended to have a check() method to do the check 455 * and auto initialization of the data. 456 * 457 * @return bool Success 458 */ 459 function set() 460 { 461 trigger_error('set() not defined for the current resource object.', 462 E_USER_WARNING); 463 return false; 464 } 465 466 /** 467 * Check the basic data. 468 * 469 * @return bool Success 470 */ 471 function check() 472 { 473 trigger_error('check() not defined for the current resource object.', 474 E_USER_WARNING); 475 return false; 476 } 477 478 /** 479 * Save the data into the DB. Note that it does not save the category 480 * and author data, as those data are saved immediately. 481 * 482 * @return bool Success 483 */ 484 function commit() 485 { 486 trigger_error('commit() not defined for the current resource object.', 487 E_USER_WARNING); 488 return false; 489 } 490 491 /** 492 * Is just running the post commit hook. 493 */ 494 function runPostCommitHook() 495 { 496 Hook::run('onResourcePostCommit', array('res' => &$this)); 497 } 498 499 /** 500 * Associate the resource to a category. 501 * 502 * @see loadCategories() 503 * 504 * @param int Category id 505 * @param int Type of association (PX_RESOURCE_CATEGORY_MAIN) 506 * @return bool Success 507 */ 508 function addToCategory($catid, $type=PX_RESOURCE_CATEGORY_MAIN) 509 { 510 if (!preg_match('/^\d+$/', $catid)) { 511 $this->setError(__('The proposed category is invalid.'), 400); 512 return false; 513 } 514 515 $update = false; 516 if (in_array($catid, $this->cats->getIDs('category_id'))) { 517 $update = true; 518 } 519 520 //The association must ensure to keep one and only one main category. 521 $this->getConnection(); 522 if ($type == PX_RESOURCE_CATEGORY_MAIN) { 523 $insReq = 'UPDATE '.$this->con->pfx.'categoryasso SET 524 categoryasso_type=\''.PX_RESOURCE_CATEGORY_OTHER.'\' 525 WHERE identifier=\''.$this->con->escapeStr($this->f('identifier')).'\''; 526 if (!$this->con->execute($insReq)) { 527 $this->setError('MySQL: '.$this->con->error(), 500); 528 return false; 529 } 530 } elseif ($update && $this->cats->f('category_id') == $catid) { 531 //the first category in $cats is the main category 532 //try to set the cat as not main, but it is currently the main 533 //do nothing. 534 return true; 535 } 536 537 if ($update) { 538 $insReq = 'UPDATE '.$this->con->pfx.'categoryasso SET 539 categoryasso_type=\''.$this->con->escapeStr($type).'\' 540 WHERE category_id=\''.$this->con->escapeStr($catid).'\' 541 AND identifier=\''.$this->con->escapeStr($this->f('identifier')).'\''; 542 } else { 543 $insReq = 'INSERT INTO '.$this->con->pfx.'categoryasso SET 544 category_id=\''.$this->con->escapeStr($catid).'\', 545 identifier=\''.$this->con->escapeStr($this->f('identifier')).'\', 546 categoryasso_type=\''.$this->con->escapeStr($type).'\''; 547 } 548 549 if (!$this->con->execute($insReq)) { 550 $this->setError('MySQL: '.$this->con->error(), 500); 551 return false; 552 } 553 554 //Need to synchronize $this->cats 555 $this->loadCategories(); 556 557 return true; 558 } 559 560 /** 561 * Remove a resource from a category. 562 * The resource cannot be removed from the category if the 563 * category is the main category. 564 * 565 * @param int Category id 566 * @return bool Success 567 */ 568 function removeFromCategory($catid) 569 { 570 if (!preg_match('/^\d+$/', $catid)) { 571 $this->setError(__('The proposed category is invalid.'), 400); 572 return false; 573 } 574 if (!in_array($catid, $this->cats->getIDs('category_id'))) { 575 $this->setError(__('The resource is not in this category it must be removed from.'), 400); 576 return false; 577 } 578 if ($this->cats->f('category_id') == $catid) { 579 $this->setError(__('The resource cannot be removed from the main category'), 400); 580 return false; 581 } 582 583 $this->getConnection(); 584 $delReq = 'DELETE FROM '.$this->con->pfx.'categoryasso 585 WHERE category_id=\''.$this->con->escapeStr($catid).'\' 586 AND identifier=\''.$this->con->escapeStr($this->f('identifier')).'\''; 587 if (!$this->con->execute($delReq)) { 588 $this->setError('MySQL: '.$this->con->error(), 500); 589 return false; 590 } 591 592 $this->loadCategories(); //synchro 593 return true; 594 } 595 596 597 /** 598 * Add an author. 599 * The author cannot be associated 2 times. It means that an author is 600 * either author, contributor or translator but can't be both of them. 601 * 602 * @param int Author id 603 * @param int Author type (PX_RESOURCE_CREATOR) 604 * @return bool Success 605 */ 606 function addAuthor($id, $type=PX_RESOURCE_CREATOR) 607 { 608 if (!preg_match('/^\d+$/', $id)) { 609 $this->setError(__('Invalid author.'), 400); 610 return false; 611 } 612 613 $update = false; 614 if (in_array($id, $this->authors->getIDs('user_id'))) { 615 $update = true; 616 } 617 618 $this->getConnection(); 619 620 //Need to find if the author exists 621 if (($user = $this->con->select(SQL::getUser($id))) === false) { 622 $this->setError('MySQL: '.$this->con->error(), 500); 623 return false; 624 } 625 if ($id != $user->f('user_id')) { 626 $this->setError(__('Try to add a non existing author to the resource.'), 400); 627 return false; 628 } 629 630 //update or insert the author 631 if ($update) { 632 $insReq = 'UPDATE '.$this->con->pfx.'authorasso SET 633 authorasso_type=\''.$this->con->escapeStr($type).'\' 634 WHERE user_id=\''.$this->con->escapeStr($id).'\' AND 635 resource_id=\''.$this->con->escapeStr($this->f('resource_id')).'\''; 636 } else { 637 $insReq = 'INSERT INTO '.$this->con->pfx.'authorasso SET 638 user_id=\''.$this->con->escapeStr($id).'\', 639 resource_id=\''.$this->con->escapeStr($this->f('resource_id')).'\', 640 authorasso_type=\''.$this->con->escapeStr($type).'\', 641 authorasso_date=\''.date::stamp().'\''; 642 } 643 if (!$this->con->execute($insReq)) { 644 $this->setError('MySQL: '.$this->con->error(), 500); 645 return false; 646 } 647 648 $this->loadAuthors(); //Synchro 649 return true; 650 } 651 652 653 /** 654 * Remove an author. 655 * A resource need at least one author. If you try to remove the last 656 * author will get an error. Add the new author and them remove the old. 657 * 658 * @param int Author id 659 * @return bool Success 660 */ 661 function removeAuthor($id) 662 { 663 if (!preg_match('/^\d+$/', $id)) { 664 $this->setError(__('Invalid author.'), 400); 665 return false; 666 } 667 668 if (!in_array($id, $this->authors->getIDs('user_id'))) { 669 $this->setError(__('The author to be removed is not associated to the resource.'), 400); 670 return false; 671 } 672 673 if ($this->authors->nbRow() == 1) { 674 $this->setError(__('Impossible to remove the unique author of the resource.'), 400); 675 return false; 676 } 677 678 //Delete the author 679 $this->getConnection(); 680 $delReq = 'DELETE FROM '.$this->con->pfx.'authorasso 681 WHERE user_id=\''.$this->con->escapeStr($id).'\' AND 682 resource_id=\''.$this->con->escapeStr($this->f('resource_id')).'\''; 683 if (!$this->con->execute($delReq)) { 684 $this->setError('MySQL: '.$this->con->error(), 500); 685 return false; 686 } 687 688 $this->loadAuthors(); //Synchro 689 return true; 690 } 691 692 693 } 694 695 ?>
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 |
|