Dotclear

source: inc/core/class.dc.core.php @ 1698:add60e1e9451

Revision 1698:add60e1e9451, 35.7 KB checked in by Anne Kozlika <kozlika@…>, 11 years ago (diff)

Utilisateurs du blog: distribution horizontale des blocs, ajout d'un lien mailto à la demande générale de Pep (pour super admin seulement), icône spécifique super admin, admin.

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

Sites map