Dotclear

source: inc/core/class.dc.core.php @ 3157:9752ee4c8a5b

Revision 3157:9752ee4c8a5b, 39.2 KB checked in by franck <carnet.franck.paul@…>, 10 years ago (diff)

Make Session TTL adjustable (by defining DC_SESSION_TTL constant in config.php, ex : '120 minutes' ), closes #1941

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2015 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12
13/**
14@defgroup DC_CORE Dotclear Core Classes
15*/
16
17/**
18@ingroup DC_CORE
19@nosubgrouping
20@brief Dotclear core class
21
22True to its name dcCore is the core of Dotclear. It handles everything related
23to blogs, database connection, plugins...
24*/
25class dcCore
26{
27     public $con;        ///< <b>connection</b>        Database connection object
28     public $prefix;          ///< <b>string</b>            Database tables prefix
29     public $blog;       ///< <b>dcBlog</b>            dcBlog object
30     public $error;      ///< <b>dcError</b>           dcError object
31     public $auth;       ///< <b>dcAuth</b>            dcAuth object
32     public $session;    ///< <b>sessionDB</b>         sessionDB object
33     public $url;        ///< <b>urlHandler</b>        urlHandler object
34     public $wiki2xhtml; ///< <b>wiki2xhtml</b>        wiki2xhtml object
35     public $plugins;    ///< <b>dcModules</b>         dcModules object
36     public $media;      ///< <b>dcMedia</b>           dcMedia object
37     public $postmedia;  ///< <b>dcPostMedia</b>       dcPostMedia object
38     public $rest;       ///< <b>dcRestServer</b> dcRestServer object
39     public $log;        ///< <b>dcLog</b>             dcLog object
40     public $stime;      ///< <b>float</b>             starting time
41
42     private $versions = null;
43     private $formaters = array();
44     private $behaviors = array();
45     private $post_types = array();
46
47     /**
48     dcCore constructor inits everything related to Dotclear. It takes arguments
49     to init database connection.
50
51     @param    driver    <b>string</b>  Database driver name
52     @param    host      <b>string</b>  Database hostname
53     @param    db        <b>string</b>  Database name
54     @param    user      <b>string</b>  Database username
55     @param    password  <b>string</b>  Database password
56     @param    prefix    <b>string</b>  DotClear tables prefix
57     @param    persist   <b>boolean</b> Persistent database connection
58     */
59     public function __construct($driver, $host, $db, $user, $password, $prefix, $persist)
60     {
61          if (defined('DC_START_TIME')) {
62               $this->stime = DC_START_TIME;
63          } else {
64               $this->stime = microtime(true);
65          }
66
67          $this->con = dbLayer::init($driver,$host,$db,$user,$password,$persist);
68
69          # define weak_locks for mysql
70          if ($this->con instanceof mysqlConnection) {
71               mysqlConnection::$weak_locks = true;
72          } elseif ($this->con instanceof mysqliConnection) {
73               mysqliConnection::$weak_locks = true;
74          }
75
76          # define searchpath for postgresql
77          if ($this->con instanceof pgsqlConnection)
78          {
79               $searchpath = explode ('.',$prefix,2);
80               if (count($searchpath) > 1)
81               {
82                    $prefix = $searchpath[1];
83                    $sql = 'SET search_path TO '.$searchpath[0].',public;';
84                    $this->con->execute($sql);
85               }
86          }
87
88          $this->prefix = $prefix;
89
90          $ttl = DC_SESSION_TTL;
91          if (!is_null($ttl)) {
92               if (substr(trim($ttl),0,1) != '-') {
93                    // Clearbricks requires negative session TTL
94                    $ttl = '-'.trim($ttl);
95               }
96          }
97
98          $this->error = new dcError();
99          $this->auth = $this->authInstance();
100          $this->session = new sessionDB($this->con,$this->prefix.'session',DC_SESSION_NAME,'',null,DC_ADMIN_SSL,$ttl);
101          $this->url = new dcUrlHandlers();
102
103          $this->plugins = new dcPlugins($this);
104
105          $this->rest = new dcRestServer($this);
106
107          $this->meta = new dcMeta($this);
108
109          $this->log = new dcLog($this);
110     }
111
112     private function authInstance()
113     {
114          # You can set DC_AUTH_CLASS to whatever you want.
115          # Your new class *should* inherits dcAuth.
116          if (!defined('DC_AUTH_CLASS')) {
117               $c = 'dcAuth';
118          } else {
119               $c = DC_AUTH_CLASS;
120          }
121
122          if (!class_exists($c)) {
123               throw new Exception('Authentication class '.$c.' does not exist.');
124          }
125
126          if ($c != 'dcAuth' && !is_subclass_of($c,'dcAuth')) {
127               throw new Exception('Authentication class '.$c.' does not inherit dcAuth.');
128          }
129
130          return new $c($this);
131     }
132
133
134     /// @name Blog init methods
135     //@{
136     /**
137     Sets a blog to use in <var>blog</var> property.
138
139     @param    id        <b>string</b>       Blog ID
140     */
141     public function setBlog($id)
142     {
143          $this->blog = new dcBlog($this, $id);
144     }
145
146     /**
147     Unsets <var>blog</var> property.
148     */
149     public function unsetBlog()
150     {
151          $this->blog = null;
152     }
153     //@}
154
155
156     /// @name Blog status methods
157     //@{
158     /**
159     Returns an array of available blog status codes and names.
160
161     @return   <b>array</b> Simple array with codes in keys and names in value
162     */
163     public function getAllBlogStatus()
164     {
165          return array(
166               1 => __('online'),
167               0 => __('offline'),
168               -1 => __('removed')
169          );
170     }
171
172     /**
173     Returns a blog status name given to a code. This is intended to be
174     human-readable and will be translated, so never use it for tests.
175     If status code does not exist, returns <i>offline</i>.
176
177     @param    s    <b>integer</b> Status code
178     @return   <b>string</b> Blog status name
179     */
180     public function getBlogStatus($s)
181     {
182          $r = $this->getAllBlogStatus();
183          if (isset($r[$s])) {
184               return $r[$s];
185          }
186          return $r[0];
187     }
188     //@}
189
190     /// @name Admin nonce secret methods
191     //@{
192
193     public function getNonce()
194     {
195          return $this->auth->crypt(session_id());
196     }
197
198     public function checkNonce($secret)
199     {
200          if (!preg_match('/^([0-9a-f]{40,})$/i',$secret)) {
201               return false;
202          }
203
204          return $secret == $this->auth->crypt(session_id());
205     }
206
207     public function formNonce()
208     {
209          if (!session_id()) {
210               return;
211          }
212
213          return form::hidden(array('xd_check'),$this->getNonce());
214     }
215     //@}
216
217     /// @name Text Formatters methods
218     //@{
219     /**
220     Adds a new text formater which will call the function <var>$func</var> to
221     transform text. The function must be a valid callback and takes one
222     argument: the string to transform. It returns the transformed string.
223
224     @param    editor_id <b>string</b>  Editor id (dcLegacyEditor, dcCKEditor, ...)
225     @param    name      <b>string</b>  Formater name
226     @param    func      <b>callback</b>     Function to use, must be a valid and callable callback
227     */
228     public function addEditorFormater($editor_id,$name,$func)
229     {
230          if (is_callable($func)) {
231               $this->formaters[$editor_id][$name] = $func;
232          }
233     }
234
235     /// @name Text Formatters methods
236     //@{
237     /**
238     Adds a new text formater which will call the function <var>$func</var> to
239     transform text. The function must be a valid callback and takes one
240     argument: the string to transform. It returns the transformed string.
241
242     @param    name      <b>string</b>       Formater name
243     @param    func      <b>callback</b>     Function to use, must be a valid and callable callback
244     */
245     public function addFormater($name,$func)
246     {
247          $this->addEditorFormater('dcLegacyEditor',$name,$func);
248     }
249
250     /**
251     Returns editors list
252
253     @return   <b>array</b> An array of editors values.
254     */
255     public function getEditors()
256     {
257          $editors = array();
258
259          foreach (array_keys($this->formaters) as $editor_id) {
260               $editors[$editor_id] = $this->plugins->moduleInfo($editor_id,'name');
261          }
262
263          return $editors;
264     }
265
266     /**
267     Returns formaters list by editor
268
269     @param    editor_id <b>string</b>  Editor id (dcLegacyEditor, dcCKEditor, ...)
270     @return   <b>array</b> An array of formaters names in values.
271
272     /**
273     if @param editor_id is empty:
274     return all formaters sorted by actives editors
275
276     if @param editor_id is not empty
277     return formaters for an editor if editor is active
278     return empty() array if editor is not active.
279     It can happens when a user choose an editor and admin deactivate that editor later
280     */
281     public function getFormaters($editor_id='')
282     {
283          $formaters_list = array();
284
285          if (!empty($editor_id)) {
286            if (isset($this->formaters[$editor_id])) {
287                $formaters_list = array_keys($this->formaters[$editor_id]);
288            }
289          } else {
290               foreach ($this->formaters as $editor => $formaters) {
291                    $formaters_list[$editor] = array_keys($formaters);
292               }
293          }
294
295          return $formaters_list;
296     }
297
298     /**
299     If <var>$name</var> is a valid formater, it returns <var>$str</var>
300     transformed using that formater.
301
302     @param    editor_id <b>string</b>  Editor id (dcLegacyEditor, dcCKEditor, ...)
303     @param    name      <b>string</b>  Formater name
304     @param    str            <b>string</b>  String to transform
305     @return   <b>string</b>  String transformed
306     */
307     public function callEditorFormater($editor_id,$name,$str)
308     {
309          if (isset($this->formaters[$editor_id]) && isset($this->formaters[$editor_id][$name])) {
310               return call_user_func($this->formaters[$editor_id][$name],$str);
311          }
312
313          return $str;
314     }
315     //@}
316
317     /**
318     If <var>$name</var> is a valid formater, it returns <var>$str</var>
319     transformed using that formater.
320
321     @param    name      <b>string</b>       Formater name
322     @param    str           <b>string</b>        String to transform
323     @return   <b>string</b>  String transformed
324     */
325     public function callFormater($name,$str)
326     {
327          return $this->callEditorFormater('dcLegacyEditor',$name,$str);
328     }
329     //@}
330
331
332     /// @name Behaviors methods
333     //@{
334     /**
335     Adds a new behavior to behaviors stack. <var>$func</var> must be a valid
336     and callable callback.
337
338     @param    behavior  <b>string</b>       Behavior name
339     @param    func      <b>callback</b>     Function to call
340     */
341     public function addBehavior($behavior,$func)
342     {
343          if (is_callable($func)) {
344               $this->behaviors[$behavior][] = $func;
345          }
346     }
347
348     /**
349     Tests if a particular behavior exists in behaviors stack.
350
351     @param    behavior  <b>string</b>  Behavior name
352     @return   <b>boolean</b>
353     */
354     public function hasBehavior($behavior)
355     {
356          return isset($this->behaviors[$behavior]);
357     }
358
359     /**
360     Get behaviors stack (or part of).
361
362     @param    behavior  <b>string</b>       Behavior name
363     @return   <b>array</b>
364     */
365     public function getBehaviors($behavior='')
366     {
367          if (empty($this->behaviors)) return null;
368
369          if ($behavior == '') {
370               return $this->behaviors;
371          } elseif (isset($this->behaviors[$behavior])) {
372               return $this->behaviors[$behavior];
373          }
374
375          return array();
376     }
377
378     /**
379     Calls every function in behaviors stack for a given behavior and returns
380     concatened result of each function.
381
382     Every parameters added after <var>$behavior</var> will be pass to
383     behavior calls.
384
385     @param    behavior  <b>string</b>  Behavior name
386     @return   <b>string</b> Behavior concatened result
387     */
388     public function callBehavior($behavior)
389     {
390          if (isset($this->behaviors[$behavior]))
391          {
392               $args = func_get_args();
393               array_shift($args);
394
395               $res = '';
396
397               foreach ($this->behaviors[$behavior] as $f) {
398                    $res .= call_user_func_array($f,$args);
399               }
400
401               return $res;
402          }
403     }
404     //@}
405
406     /// @name Post types URLs management
407     //@{
408     public function getPostAdminURL($type,$post_id,$escaped=true)
409     {
410          if (!isset($this->post_types[$type])) {
411               $type = 'post';
412          }
413
414          $url = sprintf($this->post_types[$type]['admin_url'],$post_id);
415          return $escaped ? html::escapeURL($url) : $url;
416     }
417
418     public function getPostPublicURL($type,$post_url,$escaped=true)
419     {
420          if (!isset($this->post_types[$type])) {
421               $type = 'post';
422          }
423
424          $url = sprintf($this->post_types[$type]['public_url'],$post_url);
425          return $escaped ? html::escapeURL($url) : $url;
426     }
427
428     public function setPostType($type,$admin_url,$public_url,$label='')
429     {
430          $this->post_types[$type] = array(
431               'admin_url' => $admin_url,
432               'public_url' => $public_url,
433               'label' => ($label != '' ? $label : $type)
434          );
435     }
436
437     public function getPostTypes()
438     {
439          return $this->post_types;
440     }
441     //@}
442
443     /// @name Versions management methods
444     //@{
445     /**
446     Returns a given $module version.
447
448     @param    module    <b>string</b>  Module name
449     @return   <b>string</b>  Module version
450     */
451     public function getVersion($module='core')
452     {
453          # Fetch versions if needed
454          if (!is_array($this->versions))
455          {
456               $strReq = 'SELECT module, version FROM '.$this->prefix.'version';
457               $rs = $this->con->select($strReq);
458
459               while ($rs->fetch()) {
460                    $this->versions[$rs->module] = $rs->version;
461               }
462          }
463
464          if (isset($this->versions[$module])) {
465               return $this->versions[$module];
466          } else {
467               return null;
468          }
469     }
470
471     /**
472     Sets $version to given $module.
473
474     @param    module    <b>string</b>  Module name
475     @param    version   <b>string</b>  Module version
476     */
477     public function setVersion($module,$version)
478     {
479          $cur_version = $this->getVersion($module);
480
481          $cur = $this->con->openCursor($this->prefix.'version');
482          $cur->module = (string) $module;
483          $cur->version = (string) $version;
484
485          if ($cur_version === null) {
486               $cur->insert();
487          } else {
488               $cur->update("WHERE module='".$this->con->escape($module)."'");
489          }
490
491          $this->versions[$module] = $version;
492     }
493
494     /**
495     Removes given $module version entry.
496
497     @param    module    <b>string</b>  Module name
498     */
499     public function delVersion($module)
500     {
501          $strReq =
502          'DELETE FROM '.$this->prefix.'version '.
503          "WHERE module = '".$this->con->escape($module)."' ";
504
505          $this->con->execute($strReq);
506
507          if (is_array($this->versions)) {
508               unset($this->versions[$module]);
509          }
510     }
511
512     //@}
513
514     /// @name Users management methods
515     //@{
516     /**
517     Returns a user by its ID.
518
519     @param    id        <b>string</b>       User ID
520     @return   <b>record</b>
521     */
522     public function getUser($id)
523     {
524          $params['user_id'] = $id;
525
526          return $this->getUsers($params);
527     }
528
529     /**
530     Returns a users list. <b>$params</b> is an array with the following
531     optionnal parameters:
532
533      - <var>q</var>: search string (on user_id, user_name, user_firstname)
534      - <var>user_id</var>: user ID
535      - <var>order</var>: ORDER BY clause (default: user_id ASC)
536      - <var>limit</var>: LIMIT clause (should be an array ![limit,offset])
537
538     @param    params         <b>array</b>        Parameters
539     @param    count_only     <b>boolean</b>      Only counts results
540     @return   <b>record</b>
541     */
542     public function getUsers($params=array(),$count_only=false)
543     {
544          if ($count_only)
545          {
546               $strReq =
547               'SELECT count(U.user_id) '.
548               'FROM '.$this->prefix.'user U '.
549               'WHERE NULL IS NULL ';
550          }
551          else
552          {
553               $strReq =
554               'SELECT U.user_id,user_super,user_status,user_pwd,user_change_pwd,'.
555               'user_name,user_firstname,user_displayname,user_email,user_url,'.
556               'user_desc, user_lang,user_tz, user_post_status,user_options, '.
557               'count(P.post_id) AS nb_post '.
558               'FROM '.$this->prefix.'user U '.
559                    'LEFT JOIN '.$this->prefix.'post P ON U.user_id = P.user_id '.
560               'WHERE NULL IS NULL ';
561          }
562
563          if (!empty($params['q'])) {
564               $q = $this->con->escape(str_replace('*','%',strtolower($params['q'])));
565               $strReq .= 'AND ('.
566                    "LOWER(U.user_id) LIKE '".$q."' ".
567                    "OR LOWER(user_name) LIKE '".$q."' ".
568                    "OR LOWER(user_firstname) LIKE '".$q."' ".
569                    ') ';
570          }
571
572          if (!empty($params['user_id'])) {
573               $strReq .= "AND U.user_id = '".$this->con->escape($params['user_id'])."' ";
574          }
575
576          if (!$count_only) {
577               $strReq .= 'GROUP BY U.user_id,user_super,user_status,user_pwd,user_change_pwd,'.
578               'user_name,user_firstname,user_displayname,user_email,user_url,'.
579               'user_desc, user_lang,user_tz,user_post_status,user_options ';
580
581               if (!empty($params['order']) && !$count_only) {
582                    if (preg_match('`^([^. ]+) (?:asc|desc)`i',$params['order'],$matches)) {
583                         if (in_array($matches[1],array('user_id','user_name','user_firstname','user_displayname'))) {
584                              $table_prefix = 'U.';
585                         } else {
586                              $table_prefix = ''; // order = nb_post (asc|desc)
587                         }
588                         $strReq .= 'ORDER BY '.$table_prefix.$this->con->escape($params['order']).' ';
589                    } else {
590                         $strReq .= 'ORDER BY '.$this->con->escape($params['order']).' ';
591                    }
592               } else {
593                    $strReq .= 'ORDER BY U.user_id ASC ';
594               }
595          }
596
597          if (!$count_only && !empty($params['limit'])) {
598               $strReq .= $this->con->limit($params['limit']);
599          }
600          $rs = $this->con->select($strReq);
601          $rs->extend('rsExtUser');
602          return $rs;
603     }
604
605     /**
606     Create a new user. Takes a cursor as input and returns the new user ID.
607
608     @param    cur       <b>cursor</b>       User cursor
609     @return   <b>string</b>
610     */
611     public function addUser($cur)
612     {
613          if (!$this->auth->isSuperAdmin()) {
614               throw new Exception(__('You are not an administrator'));
615          }
616
617          if ($cur->user_id == '') {
618               throw new Exception(__('No user ID given'));
619          }
620
621          if ($cur->user_pwd == '') {
622               throw new Exception(__('No password given'));
623          }
624
625          $this->getUserCursor($cur);
626
627          if ($cur->user_creadt === null) {
628               $cur->user_creadt = date('Y-m-d H:i:s');
629          }
630
631          $cur->insert();
632
633          $this->auth->afterAddUser($cur);
634
635          return $cur->user_id;
636     }
637
638     /**
639     Updates an existing user. Returns the user ID.
640
641     @param    id        <b>string</b>       User ID
642     @param    cur       <b>cursor</b>       User cursor
643     @return   <b>string</b>
644     */
645     public function updUser($id,$cur)
646     {
647          $this->getUserCursor($cur);
648
649          if (($cur->user_id !== null || $id != $this->auth->userID()) &&
650          !$this->auth->isSuperAdmin()) {
651               throw new Exception(__('You are not an administrator'));
652          }
653
654          $cur->update("WHERE user_id = '".$this->con->escape($id)."' ");
655
656          $this->auth->afterUpdUser($id,$cur);
657
658          if ($cur->user_id !== null) {
659               $id = $cur->user_id;
660          }
661
662          # Updating all user's blogs
663          $rs = $this->con->select(
664               'SELECT DISTINCT(blog_id) FROM '.$this->prefix.'post '.
665               "WHERE user_id = '".$this->con->escape($id)."' "
666               );
667
668          while ($rs->fetch()) {
669               $b = new dcBlog($this,$rs->blog_id);
670               $b->triggerBlog();
671               unset($b);
672          }
673
674          return $id;
675     }
676
677     /**
678     Deletes a user.
679
680     @param    id        <b>string</b>       User ID
681     */
682     public function delUser($id)
683     {
684          if (!$this->auth->isSuperAdmin()) {
685               throw new Exception(__('You are not an administrator'));
686          }
687
688          if ($id == $this->auth->userID()) {
689               return;
690          }
691
692          $rs = $this->getUser($id);
693
694          if ($rs->nb_post > 0) {
695               return;
696          }
697
698          $strReq = 'DELETE FROM '.$this->prefix.'user '.
699                    "WHERE user_id = '".$this->con->escape($id)."' ";
700
701          $this->con->execute($strReq);
702
703          $this->auth->afterDelUser($id);
704     }
705
706     /**
707     Checks whether a user exists.
708
709     @param    id        <b>string</b>       User ID
710     @return   <b>boolean</b>
711     */
712     public function userExists($id)
713     {
714          $strReq = 'SELECT user_id '.
715                    'FROM '.$this->prefix.'user '.
716                    "WHERE user_id = '".$this->con->escape($id)."' ";
717
718          $rs = $this->con->select($strReq);
719
720          return !$rs->isEmpty();
721     }
722
723     /**
724     Returns all user permissions as an array which looks like:
725
726      - [blog_id]
727        - [name] => Blog name
728        - [url] => Blog URL
729        - [p]
730          - [permission] => true
731          - ...
732
733     @param    id        <b>string</b>       User ID
734     @return   <b>array</b>
735     */
736     public function getUserPermissions($id)
737     {
738          $strReq = 'SELECT B.blog_id, blog_name, blog_url, permissions '.
739                    'FROM '.$this->prefix.'permissions P '.
740                    'INNER JOIN '.$this->prefix.'blog B ON P.blog_id = B.blog_id '.
741                    "WHERE user_id = '".$this->con->escape($id)."' ";
742
743          $rs = $this->con->select($strReq);
744
745          $res = array();
746
747          while ($rs->fetch())
748          {
749               $res[$rs->blog_id] = array(
750                    'name' => $rs->blog_name,
751                    'url' => $rs->blog_url,
752                    'p' => $this->auth->parsePermissions($rs->permissions)
753               );
754          }
755
756          return $res;
757     }
758
759     /**
760     Sets user permissions. The <var>$perms</var> array looks like:
761
762      - [blog_id] => '|perm1|perm2|'
763      - ...
764
765     @param    id        <b>string</b>       User ID
766     @param    perms     <b>array</b>        Permissions array
767     */
768     public function setUserPermissions($id,$perms)
769     {
770          if (!$this->auth->isSuperAdmin()) {
771               throw new Exception(__('You are not an administrator'));
772          }
773
774          $strReq = 'DELETE FROM '.$this->prefix.'permissions '.
775                    "WHERE user_id = '".$this->con->escape($id)."' ";
776
777          $this->con->execute($strReq);
778
779          foreach ($perms as $blog_id => $p) {
780               $this->setUserBlogPermissions($id, $blog_id, $p, false);
781          }
782     }
783
784     /**
785     Sets user permissions for a given blog. <var>$perms</var> is an array with
786     permissions in values
787
788     @param    id             <b>string</b>       User ID
789     @param    blog_id        <b>string</b>       Blog ID
790     @param    perms          <b>array</b>        Permissions
791     @param    delete_first   <b>boolean</b>      Delete permissions before
792     */
793     public function setUserBlogPermissions($id, $blog_id, $perms, $delete_first=true)
794     {
795          if (!$this->auth->isSuperAdmin()) {
796               throw new Exception(__('You are not an administrator'));
797          }
798
799          $no_perm = empty($perms);
800
801          $perms = '|'.implode('|',array_keys($perms)).'|';
802
803          $cur = $this->con->openCursor($this->prefix.'permissions');
804
805          $cur->user_id = (string) $id;
806          $cur->blog_id = (string) $blog_id;
807          $cur->permissions = $perms;
808
809          if ($delete_first || $no_perm)
810          {
811               $strReq = 'DELETE FROM '.$this->prefix.'permissions '.
812                         "WHERE blog_id = '".$this->con->escape($blog_id)."' ".
813                         "AND user_id = '".$this->con->escape($id)."' ";
814
815               $this->con->execute($strReq);
816          }
817
818          if (!$no_perm) {
819               $cur->insert();
820          }
821     }
822
823     /**
824     Sets a user default blog. This blog will be selected when user log in.
825
826     @param    id             <b>string</b>       User ID
827     @param    blog_id        <b>string</b>       Blog ID
828     */
829     public function setUserDefaultBlog($id, $blog_id)
830     {
831          $cur = $this->con->openCursor($this->prefix.'user');
832
833          $cur->user_default_blog = (string) $blog_id;
834
835          $cur->update("WHERE user_id = '".$this->con->escape($id)."'");
836     }
837
838     private function getUserCursor($cur)
839     {
840          if ($cur->isField('user_id')
841          && !preg_match('/^[A-Za-z0-9@._-]{2,}$/',$cur->user_id)) {
842               throw new Exception(__('User ID must contain at least 2 characters using letters, numbers or symbols.'));
843          }
844
845          if ($cur->user_url !== null && $cur->user_url != '') {
846               if (!preg_match('|^http(s?)://|',$cur->user_url)) {
847                    $cur->user_url = 'http://'.$cur->user_url;
848               }
849          }
850
851          if ($cur->isField('user_pwd')) {
852               if (strlen($cur->user_pwd) < 6) {
853                    throw new Exception(__('Password must contain at least 6 characters.'));
854               }
855               $cur->user_pwd = $this->auth->crypt($cur->user_pwd);
856          }
857
858          if ($cur->user_lang !== null && !preg_match('/^[a-z]{2}(-[a-z]{2})?$/',$cur->user_lang)) {
859               throw new Exception(__('Invalid user language code'));
860          }
861
862          if ($cur->user_upddt === null) {
863               $cur->user_upddt = date('Y-m-d H:i:s');
864          }
865
866          if ($cur->user_options !== null) {
867               $cur->user_options = serialize((array) $cur->user_options);
868          }
869     }
870
871     /**
872     Returns user default settings in an associative array with setting names in
873     keys.
874
875     @return   <b>array</b>
876     */
877     public function userDefaults()
878     {
879          return array(
880               'edit_size' => 24,
881               'enable_wysiwyg' => true,
882               'toolbar_bottom' => false,
883               'editor' => array('xhtml' => 'dcCKEditor', 'wiki' => 'dcLegacyEditor'),
884               'post_format' => 'wiki'
885          );
886     }
887     //@}
888
889     /// @name Blog management methods
890     //@{
891     /**
892     Returns all blog permissions (users) as an array which looks like:
893
894      - [user_id]
895        - [name] => User name
896        - [firstname] => User firstname
897        - [displayname] => User displayname
898        - [super] => (true|false) super admin
899        - [p]
900          - [permission] => true
901          - ...
902
903     @param    id             <b>string</b>       Blog ID
904     @param    with_super     <b>boolean</b>      Includes super admins in result
905     @return   <b>array</b>
906     */
907     public function getBlogPermissions($id,$with_super=true)
908     {
909          $strReq =
910          'SELECT U.user_id AS user_id, user_super, user_name, user_firstname, '.
911          'user_displayname, user_email, permissions '.
912          'FROM '.$this->prefix.'user U '.
913          'JOIN '.$this->prefix.'permissions P ON U.user_id = P.user_id '.
914          "WHERE blog_id = '".$this->con->escape($id)."' ";
915
916          if ($with_super) {
917               $strReq .=
918               'UNION '.
919               'SELECT U.user_id AS user_id, user_super, user_name, user_firstname, '.
920               "user_displayname, user_email, NULL AS permissions ".
921               'FROM '.$this->prefix.'user U '.
922               'WHERE user_super = 1 ';
923          }
924
925          $rs = $this->con->select($strReq);
926
927          $res = array();
928
929          while ($rs->fetch())
930          {
931               $res[$rs->user_id] = array(
932                    'name' => $rs->user_name,
933                    'firstname' => $rs->user_firstname,
934                    'displayname' => $rs->user_displayname,
935                    'email' => $rs->user_email,
936                    'super' => (boolean) $rs->user_super,
937                    'p' => $this->auth->parsePermissions($rs->permissions)
938               );
939          }
940
941          return $res;
942     }
943
944     /**
945     Returns a blog of given ID.
946
947     @param    id        <b>string</b>       Blog ID
948     @return   <b>record</b>
949     */
950     public function getBlog($id)
951     {
952          $blog = $this->getBlogs(array('blog_id'=>$id));
953
954          if ($blog->isEmpty()) {
955               return false;
956          }
957
958          return $blog;
959     }
960
961     /**
962     Returns a record of blogs. <b>$params</b> is an array with the following
963     optionnal parameters:
964
965      - <var>blog_id</var>: Blog ID
966      - <var>q</var>: Search string on blog_id, blog_name and blog_url
967      - <var>limit</var>: limit results
968
969     @param    params         <b>array</b>        Parameters
970     @param    count_only     <b>boolean</b>      Count only results
971     @return   <b>record</b>
972     */
973     public function getBlogs($params=array(),$count_only=false)
974     {
975          $join = '';    // %1$s
976          $where = '';   // %2$s
977
978          if ($count_only)
979          {
980               $strReq = 'SELECT count(B.blog_id) '.
981                         'FROM '.$this->prefix.'blog B '.
982                         '%1$s '.
983                         'WHERE NULL IS NULL '.
984                         '%2$s ';
985          }
986          else
987          {
988               $strReq =
989               'SELECT B.blog_id, blog_uid, blog_url, blog_name, blog_desc, blog_creadt, '.
990               'blog_upddt, blog_status '.
991               'FROM '.$this->prefix.'blog B '.
992               '%1$s '.
993               'WHERE NULL IS NULL '.
994               '%2$s ';
995
996               if (!empty($params['order'])) {
997                    $strReq .= 'ORDER BY '.$this->con->escape($params['order']).' ';
998               } else {
999                    $strReq .= 'ORDER BY B.blog_id ASC ';
1000               }
1001
1002               if (!empty($params['limit'])) {
1003                    $strReq .= $this->con->limit($params['limit']);
1004               }
1005          }
1006
1007          if ($this->auth->userID() && !$this->auth->isSuperAdmin())
1008          {
1009               $join = 'INNER JOIN '.$this->prefix.'permissions PE ON B.blog_id = PE.blog_id ';
1010               $where =
1011               "AND PE.user_id = '".$this->con->escape($this->auth->userID())."' ".
1012               "AND (permissions LIKE '%|usage|%' OR permissions LIKE '%|admin|%' OR permissions LIKE '%|contentadmin|%') ".
1013               "AND blog_status IN (1,0) ";
1014          } elseif (!$this->auth->userID()) {
1015               $where = 'AND blog_status IN (1,0) ';
1016          }
1017
1018          if (!empty($params['blog_id'])) {
1019               $where .= "AND B.blog_id = '".$this->con->escape($params['blog_id'])."' ";
1020          }
1021
1022          if (!empty($params['q'])) {
1023               $params['q'] = strtolower(str_replace('*','%',$params['q']));
1024               $where .=
1025               'AND ('.
1026               "LOWER(B.blog_id) LIKE '".$this->con->escape($params['q'])."' ".
1027               "OR LOWER(B.blog_name) LIKE '".$this->con->escape($params['q'])."' ".
1028               "OR LOWER(B.blog_url) LIKE '".$this->con->escape($params['q'])."' ".
1029               ') ';
1030          }
1031
1032          $strReq = sprintf($strReq,$join,$where);
1033          return $this->con->select($strReq);
1034     }
1035
1036     /**
1037     Creates a new blog.
1038
1039     @param    cur            <b>cursor</b>       Blog cursor
1040     */
1041     public function addBlog($cur)
1042     {
1043          if (!$this->auth->isSuperAdmin()) {
1044               throw new Exception(__('You are not an administrator'));
1045          }
1046
1047          $this->getBlogCursor($cur);
1048
1049          $cur->blog_creadt = date('Y-m-d H:i:s');
1050          $cur->blog_upddt = date('Y-m-d H:i:s');
1051          $cur->blog_uid = md5(uniqid());
1052
1053          $cur->insert();
1054     }
1055
1056     /**
1057     Updates a given blog.
1058
1059     @param    id        <b>string</b>       Blog ID
1060     @param    cur       <b>cursor</b>       Blog cursor
1061     */
1062     public function updBlog($id,$cur)
1063     {
1064          $this->getBlogCursor($cur);
1065
1066          $cur->blog_upddt = date('Y-m-d H:i:s');
1067
1068          $cur->update("WHERE blog_id = '".$this->con->escape($id)."'");
1069     }
1070
1071     private function getBlogCursor($cur)
1072     {
1073          if (($cur->blog_id !== null
1074               && !preg_match('/^[A-Za-z0-9._-]{2,}$/',$cur->blog_id)) ||
1075               (!$cur->blog_id)) {
1076               throw new Exception(__('Blog ID must contain at least 2 characters using letters, numbers or symbols.'));
1077          }
1078
1079          if (($cur->blog_name !== null && $cur->blog_name == '') ||
1080               (!$cur->blog_name)) {
1081               throw new Exception(__('No blog name'));
1082          }
1083
1084          if (($cur->blog_url !== null && $cur->blog_url == '') ||
1085               (!$cur->blog_url)) {
1086               throw new Exception(__('No blog URL'));
1087          }
1088
1089          if ($cur->blog_desc !== null) {
1090               $cur->blog_desc = html::clean($cur->blog_desc);
1091          }
1092     }
1093
1094     /**
1095     Removes a given blog.
1096     @warning This will remove everything related to the blog (posts,
1097     categories, comments, links...)
1098
1099     @param    id        <b>string</b>       Blog ID
1100     */
1101     public function delBlog($id)
1102     {
1103          if (!$this->auth->isSuperAdmin()) {
1104               throw new Exception(__('You are not an administrator'));
1105          }
1106
1107          $strReq = 'DELETE FROM '.$this->prefix.'blog '.
1108                    "WHERE blog_id = '".$this->con->escape($id)."' ";
1109
1110          $this->con->execute($strReq);
1111     }
1112
1113     /**
1114     Checks if a blog exist.
1115
1116     @param    id        <b>string</b>       Blog ID
1117     @return   <b>boolean</b>
1118     */
1119     public function blogExists($id)
1120     {
1121          $strReq = 'SELECT blog_id '.
1122                    'FROM '.$this->prefix.'blog '.
1123                    "WHERE blog_id = '".$this->con->escape($id)."' ";
1124
1125          $rs = $this->con->select($strReq);
1126
1127          return !$rs->isEmpty();
1128     }
1129
1130     /**
1131     Count posts on a blog
1132
1133     @param    id        <b>string</b>       Blog ID
1134     @param    type      <b>string</b>       Post type
1135     @return   <b>boolean</b>
1136     */
1137     public function countBlogPosts($id,$type=null)
1138     {
1139          $strReq = 'SELECT COUNT(post_id) '.
1140                    'FROM '.$this->prefix.'post '.
1141                    "WHERE blog_id = '".$this->con->escape($id)."' ";
1142
1143          if ($type) {
1144               $strReq .= "AND post_type = '".$this->con->escape($type)."' ";
1145          }
1146
1147          return $this->con->select($strReq)->f(0);
1148     }
1149     //@}
1150
1151     /// @name HTML Filter methods
1152     //@{
1153     /**
1154     Calls HTML filter to drop bad tags and produce valid XHTML output (if
1155     tidy extension is present). If <b>enable_html_filter</b> blog setting is
1156     false, returns not filtered string.
1157
1158     @param    str  <b>string</b>       String to filter
1159     @return   <b>string</b> Filtered string.
1160     */
1161     public function HTMLfilter($str)
1162     {
1163          if ($this->blog instanceof dcBlog && !$this->blog->settings->system->enable_html_filter) {
1164               return $str;
1165          }
1166
1167          $filter = new htmlFilter;
1168          $str = trim($filter->apply($str));
1169          return $str;
1170     }
1171     //@}
1172
1173     /// @name wiki2xhtml methods
1174     //@{
1175     private function initWiki()
1176     {
1177          $this->wiki2xhtml = new wiki2xhtml;
1178     }
1179
1180     /**
1181     Returns a transformed string with wiki2xhtml.
1182
1183     @param    str       <b>string</b>       String to transform
1184     @return   <b>string</b>  Transformed string
1185     */
1186     public function wikiTransform($str)
1187     {
1188          if (!($this->wiki2xhtml instanceof wiki2xhtml)) {
1189               $this->initWiki();
1190          }
1191          return $this->wiki2xhtml->transform($str);
1192     }
1193
1194     /**
1195     Inits <var>wiki2xhtml</var> property for blog post.
1196     */
1197     public function initWikiPost()
1198     {
1199          $this->initWiki();
1200
1201          $this->wiki2xhtml->setOpts(array(
1202               'active_title' => 1,
1203               'active_setext_title' => 0,
1204               'active_hr' => 1,
1205               'active_lists' => 1,
1206               'active_quote' => 1,
1207               'active_pre' => 1,
1208               'active_empty' => 1,
1209               'active_auto_br' => 0,
1210               'active_auto_urls' => 0,
1211               'active_urls' => 1,
1212               'active_auto_img' => 0,
1213               'active_img' => 1,
1214               'active_anchor' => 1,
1215               'active_em' => 1,
1216               'active_strong' => 1,
1217               'active_br' => 1,
1218               'active_q' => 1,
1219               'active_code' => 1,
1220               'active_acronym' => 1,
1221               'active_ins' => 1,
1222               'active_del' => 1,
1223               'active_footnotes' => 1,
1224               'active_wikiwords' => 0,
1225               'active_macros' => 1,
1226               'parse_pre' => 1,
1227               'active_fr_syntax' => 0,
1228               'first_title_level' => 3,
1229               'note_prefix' => 'wiki-footnote',
1230               'note_str' => '<div class="footnotes"><h4>Notes</h4>%s</div>'
1231          ));
1232
1233          $this->wiki2xhtml->registerFunction('url:post',array($this,'wikiPostLink'));
1234
1235          # --BEHAVIOR-- coreWikiPostInit
1236          $this->callBehavior('coreInitWikiPost',$this->wiki2xhtml);
1237     }
1238
1239     /**
1240     Inits <var>wiki2xhtml</var> property for simple blog comment (basic syntax).
1241     */
1242     public function initWikiSimpleComment()
1243     {
1244          $this->initWiki();
1245
1246          $this->wiki2xhtml->setOpts(array(
1247               'active_title' => 0,
1248               'active_setext_title' => 0,
1249               'active_hr' => 0,
1250               'active_lists' => 0,
1251               'active_quote' => 0,
1252               'active_pre' => 0,
1253               'active_empty' => 0,
1254               'active_auto_br' => 1,
1255               'active_auto_urls' => 1,
1256               'active_urls' => 0,
1257               'active_auto_img' => 0,
1258               'active_img' => 0,
1259               'active_anchor' => 0,
1260               'active_em' => 0,
1261               'active_strong' => 0,
1262               'active_br' => 0,
1263               'active_q' => 0,
1264               'active_code' => 0,
1265               'active_acronym' => 0,
1266               'active_ins' => 0,
1267               'active_del' => 0,
1268               'active_footnotes' => 0,
1269               'active_wikiwords' => 0,
1270               'active_macros' => 0,
1271               'parse_pre' => 0,
1272               'active_fr_syntax' => 0
1273          ));
1274
1275          # --BEHAVIOR-- coreInitWikiSimpleComment
1276          $this->callBehavior('coreInitWikiSimpleComment',$this->wiki2xhtml);
1277     }
1278
1279     /**
1280     Inits <var>wiki2xhtml</var> property for blog comment.
1281     */
1282     public function initWikiComment()
1283     {
1284          $this->initWiki();
1285
1286          $this->wiki2xhtml->setOpts(array(
1287               'active_title' => 0,
1288               'active_setext_title' => 0,
1289               'active_hr' => 0,
1290               'active_lists' => 1,
1291               'active_quote' => 0,
1292               'active_pre' => 1,
1293               'active_empty' => 0,
1294               'active_auto_br' => 1,
1295               'active_auto_urls' => 1,
1296               'active_urls' => 1,
1297               'active_auto_img' => 0,
1298               'active_img' => 0,
1299               'active_anchor' => 0,
1300               'active_em' => 1,
1301               'active_strong' => 1,
1302               'active_br' => 1,
1303               'active_q' => 1,
1304               'active_code' => 1,
1305               'active_acronym' => 1,
1306               'active_ins' => 1,
1307               'active_del' => 1,
1308               'active_footnotes' => 0,
1309               'active_wikiwords' => 0,
1310               'active_macros' => 0,
1311               'parse_pre' => 0,
1312               'active_fr_syntax' => 0
1313          ));
1314
1315          # --BEHAVIOR-- coreInitWikiComment
1316          $this->callBehavior('coreInitWikiComment',$this->wiki2xhtml);
1317     }
1318
1319     public function wikiPostLink($url,$content)
1320     {
1321          if (!($this->blog instanceof dcBlog)) {
1322               return array();
1323          }
1324
1325          $post_id = abs((integer) substr($url,5));
1326          if (!$post_id) {
1327               return array();
1328          }
1329
1330          $post = $this->blog->getPosts(array('post_id'=>$post_id));
1331          if ($post->isEmpty()) {
1332               return array();
1333          }
1334
1335          $res = array('url' => $post->getURL());
1336          $post_title = $post->post_title;
1337
1338          if ($content != $url) {
1339               $res['title'] = html::escapeHTML($post->post_title);
1340          }
1341
1342          if ($content == '' || $content == $url) {
1343               $res['content'] = html::escapeHTML($post->post_title);
1344          }
1345
1346          if ($post->post_lang) {
1347               $res['lang'] = $post->post_lang;
1348          }
1349
1350          return $res;
1351     }
1352     //@}
1353
1354     /// @name Maintenance methods
1355     //@{
1356     /**
1357     Creates default settings for active blog. Optionnal parameter
1358     <var>defaults</var> replaces default params while needed.
1359
1360     @param    defaults       <b>array</b>   Default parameters
1361     */
1362     public function blogDefaults($defaults=null)
1363     {
1364          if (!is_array($defaults))
1365          {
1366               $defaults = array(
1367                    array('allow_comments','boolean',true,
1368                    'Allow comments on blog'),
1369                    array('allow_trackbacks','boolean',true,
1370                    'Allow trackbacks on blog'),
1371                    array('blog_timezone','string','Europe/London',
1372                    'Blog timezone'),
1373                    array('comments_nofollow','boolean',true,
1374                    'Add rel="nofollow" to comments URLs'),
1375                    array('comments_pub','boolean',true,
1376                    'Publish comments immediately'),
1377                    array('comments_ttl','integer',0,
1378                    'Number of days to keep comments open (0 means no ttl)'),
1379                    array('copyright_notice','string','','Copyright notice (simple text)'),
1380                    array('date_format','string','%A, %B %e %Y',
1381                    'Date format. See PHP strftime function for patterns'),
1382                    array('editor','string','',
1383                    'Person responsible of the content'),
1384                    array('enable_html_filter','boolean',0,
1385                    'Enable HTML filter'),
1386                    array('enable_xmlrpc','boolean',0,
1387                    'Enable XML/RPC interface'),
1388                    array('lang','string','en',
1389                    'Default blog language'),
1390                    array('media_exclusion','string','/\.(phps?|pht(ml)?|phl)[0-9]*$/i',
1391                    'File name exclusion pattern in media manager. (PCRE value)'),
1392                    array('media_img_m_size','integer',448,
1393                    'Image medium size in media manager'),
1394                    array('media_img_s_size','integer',240,
1395                    'Image small size in media manager'),
1396                    array('media_img_t_size','integer',100,
1397                    'Image thumbnail size in media manager'),
1398                    array('media_img_title_pattern','string','Title ;; Date(%b %Y) ;; separator(, )',
1399                    'Pattern to set image title when you insert it in a post'),
1400                    array('media_video_width','integer',400,
1401                    'Video width in media manager'),
1402                    array('media_video_height','integer',300,
1403                    'Video height in media manager'),
1404                    array('media_flash_fallback','boolean',true,
1405                    'Flash player fallback for audio and video media'),
1406                    array('nb_post_for_home','integer',20,
1407                    'Number of entries on first home page'),
1408                    array('nb_post_per_page','integer',20,
1409                    'Number of entries on home pages and category pages'),
1410                    array('nb_post_per_feed','integer',20,
1411                    'Number of entries on feeds'),
1412                    array('nb_comment_per_feed','integer',20,
1413                    'Number of comments on feeds'),
1414                    array('post_url_format','string','{y}/{m}/{d}/{t}',
1415                    'Post URL format. {y}: year, {m}: month, {d}: day, {id}: post id, {t}: entry title'),
1416                    array('public_path','string','public',
1417                    'Path to public directory, begins with a / for a full system path'),
1418                    array('public_url','string','/public',
1419                    'URL to public directory'),
1420                    array('robots_policy','string','INDEX,FOLLOW',
1421                    'Search engines robots policy'),
1422                    array('short_feed_items','boolean',false,
1423                    'Display short feed items'),
1424                    array('theme','string','berlin',
1425                    'Blog theme'),
1426                    array('themes_path','string','themes',
1427                    'Themes root path'),
1428                    array('themes_url','string','/themes',
1429                    'Themes root URL'),
1430                    array('time_format','string','%H:%M',
1431                    'Time format. See PHP strftime function for patterns'),
1432                    array('tpl_allow_php','boolean',false,
1433                    'Allow PHP code in templates'),
1434                    array('tpl_use_cache','boolean',true,
1435                    'Use template caching'),
1436                    array('trackbacks_pub','boolean',true,
1437                    'Publish trackbacks immediately'),
1438                    array('trackbacks_ttl','integer',0,
1439                    'Number of days to keep trackbacks open (0 means no ttl)'),
1440                    array('url_scan','string','query_string',
1441                    'URL handle mode (path_info or query_string)'),
1442                    array('use_smilies','boolean',false,
1443                    'Show smilies on entries and comments'),
1444                    array('no_search','boolean',false,
1445                    'Disable search'),
1446                    array('inc_subcats','boolean',false,
1447                    'Include sub-categories in category page and category posts feed'),
1448                    array('wiki_comments','boolean',false,
1449                    'Allow commenters to use a subset of wiki syntax')
1450               );
1451          }
1452
1453          $settings = new dcSettings($this,null);
1454          $settings->addNamespace('system');
1455
1456          foreach ($defaults as $v) {
1457               $settings->system->put($v[0],$v[2],$v[1],$v[3],false,true);
1458          }
1459     }
1460
1461     /**
1462     Recreates entries search engine index.
1463
1464     @param    start     <b>integer</b>      Start entry index
1465     @param    limit     <b>integer</b>      Number of entry to index
1466
1467     @return   <b>integer</b>      <var>$start</var> and <var>$limit</var> sum
1468     */
1469     public function indexAllPosts($start=null,$limit=null)
1470     {
1471          $strReq = 'SELECT COUNT(post_id) '.
1472                    'FROM '.$this->prefix.'post';
1473          $rs = $this->con->select($strReq);
1474          $count = $rs->f(0);
1475
1476          $strReq = 'SELECT post_id, post_title, post_excerpt_xhtml, post_content_xhtml '.
1477                    'FROM '.$this->prefix.'post ';
1478
1479          if ($start !== null && $limit !== null) {
1480               $strReq .= $this->con->limit($start,$limit);
1481          }
1482
1483          $rs = $this->con->select($strReq,true);
1484
1485          $cur = $this->con->openCursor($this->prefix.'post');
1486
1487          while ($rs->fetch())
1488          {
1489               $words = $rs->post_title.' '. $rs->post_excerpt_xhtml.' '.
1490               $rs->post_content_xhtml;
1491
1492               $cur->post_words = implode(' ',text::splitWords($words));
1493               $cur->update('WHERE post_id = '.(integer) $rs->post_id);
1494               $cur->clean();
1495          }
1496
1497          if ($start+$limit > $count) {
1498               return null;
1499          }
1500          return $start+$limit;
1501     }
1502
1503     /**
1504     Recreates comments search engine index.
1505
1506     @param    start     <b>integer</b>      Start comment index
1507     @param    limit     <b>integer</b>      Number of comments to index
1508
1509     @return   <b>integer</b>      <var>$start</var> and <var>$limit</var> sum
1510     */
1511     public function indexAllComments($start=null,$limit=null)
1512     {
1513          $strReq = 'SELECT COUNT(comment_id) '.
1514                    'FROM '.$this->prefix.'comment';
1515          $rs = $this->con->select($strReq);
1516          $count = $rs->f(0);
1517
1518          $strReq = 'SELECT comment_id, comment_content '.
1519                    'FROM '.$this->prefix.'comment ';
1520
1521          if ($start !== null && $limit !== null) {
1522               $strReq .= $this->con->limit($start,$limit);
1523          }
1524
1525          $rs = $this->con->select($strReq);
1526
1527          $cur = $this->con->openCursor($this->prefix.'comment');
1528
1529          while ($rs->fetch())
1530          {
1531               $cur->comment_words = implode(' ',text::splitWords($rs->comment_content));
1532               $cur->update('WHERE comment_id = '.(integer) $rs->comment_id);
1533               $cur->clean();
1534          }
1535
1536          if ($start+$limit > $count) {
1537               return null;
1538          }
1539          return $start+$limit;
1540     }
1541
1542     /**
1543     Reinits nb_comment and nb_trackback in post table.
1544     */
1545     public function countAllComments()
1546     {
1547
1548          $updCommentReq = 'UPDATE '.$this->prefix.'post P '.
1549               'SET nb_comment = ('.
1550                    'SELECT COUNT(C.comment_id) from '.$this->prefix.'comment C '.
1551                    'WHERE C.post_id = P.post_id AND C.comment_trackback <> 1 '.
1552                    'AND C.comment_status = 1 '.
1553               ')';
1554          $updTrackbackReq = 'UPDATE '.$this->prefix.'post P '.
1555               'SET nb_trackback = ('.
1556                    'SELECT COUNT(C.comment_id) from '.$this->prefix.'comment C '.
1557                    'WHERE C.post_id = P.post_id AND C.comment_trackback = 1 '.
1558                    'AND C.comment_status = 1 '.
1559               ')';
1560          $this->con->execute($updCommentReq);
1561          $this->con->execute($updTrackbackReq);
1562     }
1563
1564     /**
1565     Empty templates cache directory
1566     */
1567     public function emptyTemplatesCache()
1568     {
1569          if (is_dir(DC_TPL_CACHE.'/cbtpl')) {
1570               files::deltree(DC_TPL_CACHE.'/cbtpl');
1571          }
1572     }
1573
1574     /**
1575      Return elapsed time since script has been started
1576      @param     $mtime <b>float</b> timestamp (microtime format) to evaluate delta from
1577                                          current time is taken if null
1578      @return <b>float</b>          elapsed time
1579      */
1580     public function getElapsedTime ($mtime=null) {
1581          if ($mtime !== null) {
1582               return $mtime-$this->stime;
1583          } else {
1584               return microtime(true)-$this->stime;
1585          }
1586     }
1587     //@}
1588
1589
1590
1591}
Note: See TracBrowser for help on using the repository browser.

Sites map