Dotclear

source: inc/core/class.dc.core.php @ 331:7b0a879d0dee

Revision 331:7b0a879d0dee, 35.6 KB checked in by xave, 14 years ago (diff)

Now handles non default postgres schemas.

Enter schema name in the database prefix using a period as separator: 'schema.prefix'

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

Sites map