Dotclear

source: inc/core/class.dc.core.php @ 3122:198580bc3d80

Revision 3122:198580bc3d80, 38.7 KB checked in by franck <carnet.franck.paul@…>, 10 years ago (diff)

Enforce media exclusion extension control, thanks Tim Coen for report

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

Sites map