Dotclear

source: inc/core/class.dc.core.php @ 3565:7b120898d2bd

Revision 3565:7b120898d2bd, 40.2 KB checked in by franck <carnet.franck.paul@…>, 8 years ago (diff)

Add MySQL UTF8-MB4 support

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

Sites map