[ Index ]
 

Code source de Plume CMS 1.2.2

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/manager/inc/ -> class.resource.php (source)

   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('&', '&amp;', $this->f($field));
 347              }
 348              return $this->f($field);
 349          } else {
 350              if ($escape) {
 351                  return str_replace('&', '&amp;', $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  ?>


Généré le : Mon Nov 26 11:57:01 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics