Dotclear

source: inc/core/class.dc.core.php @ 3761:849987324197

Revision 3761:849987324197, 51.9 KB checked in by franck <carnet.franck.paul@…>, 7 years ago (diff)

Apply SQL Statement in DC code, work in progress

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

Sites map