Dotclear

source: inc/core/class.dc.core.php @ 3731:3770620079d4

Revision 3731:3770620079d4, 50.1 KB checked in by franck <carnet.franck.paul@…>, 7 years ago (diff)

Simplify licence block at the beginning of each file

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

Sites map