[ 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.manager.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  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 = '&amp;p='.$plugin;
1538          $link = 'help.php?c='.$chapter.$plugin;
1539          $linkpop = $link.'&amp;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  ?>


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