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