1<?php 2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project 3// 4// All Rights Reserved. See copyright.txt for details and a complete list of authors. 5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. 6// $Id$ 7 8// This script may only be included - so its better to die if called directly. 9if (strpos($_SERVER["SCRIPT_NAME"], basename(__FILE__)) !== false) { 10 header("location: index.php"); 11 exit; 12} 13 14/** 15 * Class that handles all blog operations 16 * 17 * @uses TikiDb_Bridge 18 * @package Tiki 19 * @subpackage Blogs 20 * @version 21 * @license LGPL. See licence.txt for more details 22 */ 23class BlogLib extends TikiDb_Bridge 24{ 25 /** 26 * List all blogs 27 * 28 * @param int $offset 29 * @param int $maxRecords 30 * @param string @sort_mode 31 * @param string $find 32 * @param string $ref 33 * @param string $with 34 * 35 * @return array 36 */ 37 function list_blogs($offset = 0, $maxRecords = -1, $sort_mode = 'created_desc', $find = '', $ref = '', $with = '') 38 { 39 $tikilib = TikiLib::lib('tiki'); 40 $categlib = TikiLib::lib('categ'); 41 $bindvars = []; 42 $join = ''; 43 $where = ''; 44 45 if ($jail = $categlib->get_jail()) { 46 $categlib->getSqlJoin($jail, 'blog', '`tiki_blogs`.`blogId`', $join, $where, $bindvars); 47 } 48 49 if ($find) { 50 $findesc = '%' . $find . '%'; 51 $where .= ' and (`tiki_blogs`.`title` like ? or `tiki_blogs`.`description` like ?) '; 52 $bindvars = array_merge($bindvars, [$findesc, $findesc]); 53 } 54 if (isset($with['showlastpost'])) { 55 $query = "SELECT tb.*, tbp.`postId`, tbp.`created` as postCreated, tbp.`user` as postUser, tbp.`title` as postTitle, tbp.`data` as postData FROM `tiki_blogs` tb, `tiki_blog_posts` tbp $join where tb.`blogId` = tbp.`blogId` and tbp.`created` = (select max(`created`) from `tiki_blog_posts` tbp2 where tbp2.`blogId`=tb.`blogId` order by `created` desc) $where order by tb." . $this->convertSortMode($sort_mode); 56 } else { 57 $query = "select * from `tiki_blogs` $join WHERE 1=1 $where order by `tiki_blogs`." . $this->convertSortMode($sort_mode); 58 } 59 $result = $this->fetchAll($query, $bindvars); 60 61 $ret = []; 62 $cant = 0; 63 $nb = 0; 64 $i = 0; 65 66 switch($ref) { 67 case 'post': 68 $perm = ['read_blog', 'blog_post_view_ref']; 69 break; 70 case 'blog': 71 $perm = ['read_blog', 'blog_view_ref']; 72 break; 73 default: 74 $perm = 'read_blog'; 75 } 76 77 $result = Perms::filter(['type' => 'blog'], 'object', $result, ['object' => 'blogId'], $perm); 78 79 foreach ($result as $res) { 80 ++$cant; 81 if ($maxRecords == - 1 || ($i >= $offset && $nb < $maxRecords)) { 82 $ret[] = $res; 83 ++$nb; 84 } 85 ++$i; 86 } 87 88 $retval = []; 89 $retval["data"] = $ret; 90 $retval["cant"] = $cant; 91 return $retval; 92 } 93 94 95 /** 96 * Return all blog information 97 * 98 * @param int $blogId 99 * @return array 100 */ 101 function get_blog($blogId) 102 { 103 global $prefs, $user; 104 $tikilib = TikiLib::lib('tiki'); 105 $categlib = TikiLib::lib('categ'); 106 $bindvars = []; 107 108 if ($jail = $categlib->get_jail()) { 109 $categlib->getSqlJoin($jail, 'blog', '`tiki_blogs`.`blogId`', $join, $where, $bindvars); 110 } else { 111 $join = ''; 112 $where = ''; 113 } 114 array_push($bindvars, $blogId); 115 if (! empty($where)) { 116 $where = '1=1 ' . $where . ' AND '; 117 } 118 $query = "SELECT * FROM `tiki_blogs` $join WHERE $where `blogId`=?"; 119 $result = $this->query($query, $bindvars); 120 if ($result->numRows()) { 121 $res = $result->fetchRow(); 122 } else { 123 return false; 124 } 125 126 if ($user != $res['user']) { 127 TikiLib::events()->trigger( 128 'tiki.blog.view', 129 [ 130 'type' => 'blog', 131 'object' => $blogId, 132 'user' => $user, 133 'author' => $res['user'], 134 ] 135 ); 136 } 137 138 return $res; 139 } 140 141 /** 142 * Return a blog by its title 143 * 144 * @param string $blogTitle 145 * @return array or false if no blog is found 146 */ 147 function get_blog_by_title($blogTitle) 148 { 149 // Avoiding select by name so as to avoid SQL injection problems. 150 $query = "select `title`, `blogId` from `tiki_blogs`"; 151 $result = $this->fetchAll($query); 152 if (! empty($result)) { 153 foreach ($result as $res) { 154 if (TikiLib::strtolower($res['title']) == TikiLib::strtolower($blogTitle)) { 155 return $this->get_blog($res['blogId']); 156 } 157 } 158 } 159 160 return false; 161 } 162 163 /** 164 * Returns an array of blogs that belong to the user with the given name, 165 * or which are public, if $include_public is set to true. 166 * A blog is represented by an array like a tiki_blogs record. 167 * 168 * @param string $user 169 * @param bool $include_public whether or include public blogs (that belongs to other users) 170 * @return array 171 */ 172 function list_user_blogs($user, $include_public = false) 173 { 174 $tikilib = TikiLib::lib('tiki'); 175 176 $query = "select * from `tiki_blogs` where `user`=? "; 177 $bindvars = [$user]; 178 if ($include_public) { 179 $query .= " or `public`=?"; 180 $bindvars[] = 'y'; 181 } 182 $query .= "order by `title` asc"; 183 $result = $this->fetchAll($query, $bindvars); 184 $ret = []; 185 186 //FIXME Perm::filter ? 187 foreach ($result as $res) { 188 if ($tikilib->user_has_perm_on_object($user, $res['blogId'], 'blog', 'tiki_p_read_blog')) { 189 $ret[] = $res; 190 } 191 } 192 return $ret; 193 } 194 195 /** 196 * Return a list of blogs that the user has permission to post 197 * 198 * @return array 199 */ 200 function list_blogs_user_can_post() 201 { 202 global $tiki_p_blog_admin, $user; 203 $tikilib = TikiLib::lib('tiki'); 204 205 $query = "select * from `tiki_blogs` order by `title` asc"; 206 $result = $this->fetchAll($query); 207 $ret = []; 208 209 //FIXME Perm:filter ? 210 foreach ($result as $res) { 211 if ((! empty($user) and $user == $res['user']) || $tiki_p_blog_admin == 'y' || $tikilib->user_has_perm_on_object($user, $res['blogId'], 'blog', 'tiki_p_blog_admin') || ($res['public'] == 'y' && $tikilib->user_has_perm_on_object($user, $res['blogId'], 'blog', 'tiki_p_blog_post'))) { 212 $ret[] = $res; 213 } 214 } 215 return $ret; 216 } 217 218 /** 219 * List all posts 220 * 221 * @param int $offset 222 * @param int $maxRecords 223 * @param string $sort_mode 224 * @param string $find 225 * @param int $filterByBlogId 226 * @param string $author 227 * @param string $ref 228 * @param int $date_min 229 * @param int $data_max 230 * @return array 231 */ 232 function list_posts($offset = 0, $maxRecords = -1, $sort_mode = 'created_desc', $find = '', $filterByBlogId = -1, $author = '', $ref = '', $date_min = 0, $date_max = 0) 233 { 234 $tikilib = TikiLib::lib('tiki'); 235 $filterByBlogIds = explode(':', $filterByBlogId); 236 237 $authorized_blogs = $this->list_blogs(0, -1, 'created_desc', '', $ref); 238 $permit_blogs = []; 239 for ($i = 0; $i < $authorized_blogs["cant"]; $i++) { 240 $permit_blogs[] = $authorized_blogs["data"][$i]['blogId']; 241 } 242 243 if (count($filterByBlogIds) == 1 && $filterByBlogId >= 0) { // There is one single blog Id 244 // get posts for a given blogId: 245 $mid = " where ( `blogId` = ? ) "; 246 $bindvars = [$filterByBlogId]; 247 } elseif (count($filterByBlogIds) > 1) { // There is more than one blog Id 248 $multimid = []; 249 foreach ($filterByBlogIds as $blogId) { 250 if ($blogId > 0) { 251 $multimid[] = ' `blogId` = ? '; 252 $bindvars[] = (int)$blogId; 253 } 254 } 255 if (count($multimid) > 1) { 256 $mid = ' WHERE ( ' . implode(' or ', $multimid) . ' ) '; 257 } elseif (count($multimid) == 1) { 258 $mid = ' where ( ' . $multimid[0] . ' ) '; 259 } 260 } else { 261 // get posts from all blogs 262 $mid = ''; 263 $bindvars = []; 264 } 265 266 if ($find) { 267 $findesc = '%' . $find . '%'; 268 if ($mid == "") { 269 $mid = " where "; 270 } else { 271 $mid .= " and "; 272 } 273 $mid .= " ( `data` like ? ) "; 274 $bindvars[] = $findesc; 275 } 276 if ($date_min !== 0 || $date_max !== 0) { 277 if ($date_max <= 0) { 278 // show articles published today 279 $date_max = $tikilib->now; 280 } 281 if ($mid == '') { 282 $mid = ' where '; 283 } else { 284 $mid .= ' and '; 285 } 286 $mid .= '(`created`>=? and `created`<=?)'; 287 $bindvars[] = $date_min; 288 $bindvars[] = $date_max; 289 } 290 if (! empty($author)) { 291 if ($mid == '') { 292 $mid = ' where '; 293 } else { 294 $mid .= ' and '; 295 } 296 $mid .= 'user =?'; 297 $bindvars[] = $author; 298 } 299 300 $query = "select * from `tiki_blog_posts` $mid order by " . $this->convertSortMode($sort_mode); 301 $query_cant = "select count(*) from `tiki_blog_posts` $mid"; 302 $result = $this->fetchAll($query, $bindvars, $maxRecords, $offset); 303 $cant = $this->getOne($query_cant, $bindvars); 304 $ret = []; 305 306 foreach ($result as $res) { 307 $blogId = $res["blogId"]; 308 309 if (! in_array($blogId, $permit_blogs)) { 310 continue; 311 } 312 $query = "select `title` from `tiki_blogs` where `blogId`=?"; 313 $cant_com = $this->getOne( 314 "select count(*) from `tiki_comments` where `object`=? and `objectType` = ?", 315 [(string) $res["postId"],'blog'] 316 ); 317 $res["comments"] = $cant_com; 318 $res["blogTitle"] = $this->getOne($query, [(int)$blogId]); 319 $res["size"] = strlen($res["data"]); 320 $ret[] = $res; 321 } 322 $retval = []; 323 $retval["data"] = $ret; 324 $retval["cant"] = $cant; 325 return $retval; 326 } 327 328 /** 329 * get_number_of_pages Returns the number of pages 330 * 331 * @param string $data 332 * @access public 333 * @return int number of pages 334 */ 335 function get_number_of_pages($data) 336 { 337 $parts = explode("...page...", $data); 338 return count($parts); 339 } 340 341 /** 342 * get_page Returns a spcific page of a post 343 * 344 * @param string $data 345 * @param int $i 346 * @access public 347 * @return string the page $i of the post 348 */ 349 function get_page($data, $i) 350 { 351 $parts = explode("...page...", $data); 352 353 $ret = $parts[$i - 1]; 354 if (substr($parts[$i - 1], 1, 5) == "<br/>") { 355 $ret = substr($parts[$i - 1], 6); 356 } 357 if (substr($parts[$i - 1], 1, 6) == "<br />") { 358 $ret = substr($parts[$i - 1], 7); 359 } 360 361 return $ret; 362 } 363 364 /** 365 * add_blog_hit Add a hit for the blog $blogId 366 * 367 * @param int $blogId 368 * @access public 369 * @return boolean unconditionnal true 370 */ 371 function add_blog_hit($blogId) 372 { 373 global $prefs, $user; 374 if (StatsLib::is_stats_hit()) { 375 $query = "update `tiki_blogs` set `hits` = `hits`+1 where `blogId`=?"; 376 $result = $this->query($query, [(int) $blogId]); 377 } 378 return true; 379 } 380 381 /** 382 * add_blog_post_hit Add a hit for the blog post $postId 383 * 384 * @param int $postId 385 * @access public 386 * @return boolean unconditionnal true 387 */ 388 function add_blog_post_hit($postId) 389 { 390 global $prefs, $user; 391 if (StatsLib::is_stats_hit()) { 392 $query = "update `tiki_blog_posts` set `hits` = `hits`+1 where `postId`=?"; 393 $result = $this->query($query, [(int) $postId]); 394 } 395 return true; 396 } 397 398 399 /** 400 * get_post_image Returns the image $imgId 401 * 402 * @param mixed $imgId 403 * @access public 404 * @return array all fields that are associated with an image in tiki_blog_post_images database table 405 */ 406 function get_post_image($imgId) 407 { 408 $query = "select * from `tiki_blog_posts_images` where `imgId`=?"; 409 $result = $this->query($query, [$imgId]); 410 $res = $result->fetchRow(); 411 return $res; 412 } 413 414 /** 415 * get_post_images Returns all the images joined to a post 416 * 417 * @param int $postId 418 * @access public 419 * @return array with the permalink and the absolute link for each image 420 */ 421 function get_post_images($postId) 422 { 423 $tikilib = TikiLib::lib('tiki'); 424 $query = "select `postId`,`filename`,`filesize`,`imgId` from `tiki_blog_posts_images` where `postId`=?"; 425 426 $result = $this->query($query, [(int) $postId]); 427 $ret = []; 428 429 while ($res = $result->fetchRow()) { 430 $imgId = $res['imgId']; 431 $res['link'] = "<img src='tiki-view_blog_post_image.php?imgId=$imgId' alt='image' />"; 432 $parts = parse_url($_SERVER['REQUEST_URI']); 433 $path = str_replace('tiki-blog_post.php', 'tiki-view_blog_post_image.php', $parts['path']); 434 $res['absolute'] = $tikilib->httpPrefix() . $path . "?imgId=$imgId"; 435 $ret[] = $res; 436 } 437 438 return $ret; 439 } 440 441 /** 442 * remove_post_image Removes an image 443 * 444 * @param int $imgId 445 * @access public 446 * @return void 447 */ 448 function remove_post_image($imgId) 449 { 450 $query = "delete from `tiki_blog_posts_images` where `imgId`=?"; 451 452 $this->query($query, [$imgId]); 453 } 454 455 /** 456 * replace_blog Change the attributes of a blog 457 * 458 * @param string $title 459 * @param string $description 460 * @param string $user 461 * @param $public 462 * @param int $maxPosts 463 * @param int $blogId 464 * @param string $heading 465 * @param $use_title 466 * @param $use_title_in_post 467 * @param $use_description 468 * @param $use_breadcrumbs 469 * @param $use_author 470 * @param $add_date 471 * @param $use_find 472 * @param $allow_comments 473 * @param $show_avatar 474 * @param $alwaysOwner 475 * @param string $post_heading 476 * @param $show_related 477 * @param int $related_max control the maximum number of related posts displayed per post 478 * @param int $use_excerpt use a post excerpt instead of the main content when listing posts of a blog 479 * @param int $created if 0 use $tikilib->now 480 * @param int $lastModif if 0 use $tikilib->now 481 * @return int blogId 482 * @throws Exception 483 * @access public 484 */ 485 function replace_blog( 486 $title, 487 $description, 488 $user, 489 $public, 490 $maxPosts, 491 $blogId, 492 $heading, 493 $use_title, 494 $use_title_in_post, 495 $use_description, 496 $use_breadcrumbs, 497 $use_author, 498 $add_date, 499 $use_find, 500 $allow_comments, 501 $show_avatar, 502 $alwaysOwner, 503 $post_heading, 504 $show_related, 505 $related_max, 506 $use_excerpt, 507 $created = 0, 508 $lastModif = 0 509 ) { 510 511 //TODO: all the display parameters can be one single array parameter 512 global $prefs; 513 $tikilib = TikiLib::lib('tiki'); 514 515 if ($lastModif == 0) { 516 $lastModif = $tikilib->now; 517 } 518 519 if ($blogId) { 520 $query = "update `tiki_blogs` set `title`=? ,`description`=?,`user`=?,`public`=?,`lastModif`=?,`maxPosts`=?,`heading`=?,`use_title`=?,`use_title_in_post`=?,`use_description`=?,`use_breadcrumbs`=?,`use_author`=?,`add_date`=?,`use_find`=?,`allow_comments`=?,`show_avatar`=?,`always_owner`=?, `post_heading`=?, `show_related`=?, `related_max`=?, `use_excerpt`=? where `blogId`=?"; 521 522 $result = $this->query($query, [$title, $description, $user, $public, $lastModif, $maxPosts, $heading, $use_title, $use_title_in_post, $use_description, $use_breadcrumbs, $use_author, $add_date, $use_find, $allow_comments, $show_avatar, $alwaysOwner, $post_heading, $show_related, $related_max, $use_excerpt, $blogId]); 523 $tikilib->object_post_save(['type' => 'blog', 'object' => $blogId], ['content' => $heading]); 524 $query2 = "UPDATE `tiki_objects` SET `name`=? ,`description`=? WHERE `itemId`=? AND `type`='blog'"; 525 $this->query($query2, [$title, $description, $blogId]); 526 } else { 527 if ($created == 0) { 528 $created = $tikilib->now; 529 } 530 531 $query = "insert into `tiki_blogs`(`created`,`lastModif`,`title`,`description`,`user`,`public`,`posts`,`maxPosts`,`hits`,`heading`,`use_title`,`use_title_in_post`,`use_description`,`use_breadcrumbs`,`use_author`,`add_date`,`use_find`,`allow_comments`,`show_avatar`,`always_owner`,`post_heading`, `show_related`, `related_max`, `use_excerpt`) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; 532 533 $result = $this->query($query, [$created, $lastModif, $title, $description, $user, $public, 0, (int) $maxPosts, 0, $heading, $use_title, $use_title_in_post, $use_description, $use_breadcrumbs, $use_author, $add_date, $use_find, $allow_comments, $show_avatar, $alwaysOwner, $post_heading, $show_related, $related_max, $use_excerpt]); 534 $query2 = "select max(`blogId`) from `tiki_blogs` where `lastModif`=?"; 535 $blogId = $this->getOne($query2, [$lastModif]); 536 537 TikiLib::events()->trigger( 538 'tiki.blog.create', 539 [ 540 'type' => 'blog', 541 'object' => $blogId, 542 'user' => $user, 543 ] 544 ); 545 546 $tikilib->object_post_save(['type' => 'blog', 'object' => $blogId, 'description' => $description, 'name' => $title, 'href' => "tiki-view_blog.php?blogId=$blogId"], [ 'content' => $heading ]); 547 } 548 549 require_once(__DIR__ . '/../search/refresh-functions.php'); 550 refresh_index('blogs', $blogId); 551 552 return $blogId; 553 } 554 555 /** 556 * list_blog_posts Returns all the posts for the blog $blogId 557 * $blogId can express more than one blog like "1:11" 558 * but then own draft posts (private posts) are not shown (FIXME) 559 * 560 * @param int $blogId 561 * @param bool $allowDrafts 562 * @param int $offset 563 * @param int $maxRecords 564 * @param string $sort_mode 565 * @param string $find 566 * @param string $date_min 567 * @param string $date_max 568 * @param string $approved 569 * @access public 570 * @return array posts 571 */ 572 function list_blog_posts( 573 $blogId = 0, 574 $allowDrafts = false, 575 $offset = 0, 576 $maxRecords = -1, 577 $sort_mode = 'created_desc', 578 $find = '', 579 $date_min = '', 580 $date_max = '', 581 $approved = 'y' 582 ) { 583 584 global $tiki_p_admin, $tiki_p_blog_admin, $tiki_p_blog_post, $user, $prefs; 585 586 $parserlib = TikiLib::lib('parser'); 587 $categlib = TikiLib::lib('categ'); 588 $tikilib = TikiLib::lib('tiki'); 589 590 $mid = []; 591 $bindvars = []; 592 $blogIds = explode(':', $blogId); 593 594 $ownsblog = 'n'; 595 if (count($blogIds) == 1 && $blogIds[0] > 0) { // There is one single blog Id 596 $mid[] = "tbp.`blogId`=?"; 597 $bindvars[] = (int)$blogId; 598 599 $blog_data = $this->get_blog($blogId); 600 if ($user && $user == $blog_data["user"]) { 601 $ownsblog = 'y'; 602 } 603 } elseif (count($blogIds) > 1) { // There is more than one blog Id 604 $multimid = []; 605 foreach ($blogIds as $objId) { 606 if ($objId > 0) { 607 $multimid[] = ' tbp.`blogId`=? '; 608 $bindvars[] = (int)$objId; 609 // Note: when there is more than one blog Id, own draft posts (private posts) are not shown (FIXME) 610 } 611 } 612 if (count($multimid) > 1) { 613 $mid[] = ' ( ' . implode(' or ', $multimid) . ' ) '; 614 } elseif (count($multimid) == 1) { 615 $mid[] = $multimid[0]; 616 } 617 } 618 $mid[] = "tbp.blogId = tb.blogId"; 619 620 if (! $allowDrafts) { 621 $mid[] = "`priv`!='y'"; 622 } else { 623 /* Private posts can be accessed on the following conditions: 624 user has tiki_p_admin or tiki_p_blog_admin or has written the post 625 If blog is configured with 'Allow other user to post in this blog', then also if user has tiki_p_blog_post or is owner of this blog 626 627 Basically, if the user can post to the post's blog. */ 628 if (! ( 629 $tiki_p_blog_admin == 'y' 630 || (isset($blog_data["public"]) && $blog_data["public"] == 'y' && ($tiki_p_blog_post == 'y' || $ownsblog == 'y')) 631 ) 632 ) { 633 if (isset($user)) { // Is this needed? How can a user have a post in a blog without owning the blog nor tiki_p_blog_post? Chealer9 2017-12-07 634 $mid[] = "(tbp.`priv`!='y' or tbp.`user`=?)"; 635 $bindvars[] = "$user"; 636 } else { 637 $mid[] = "tbp.`priv`!='y'"; 638 } 639 } 640 } 641 642 if ($find) { 643 $findesc = '%' . $find . '%'; 644 $mid[] = "(tbp.`data` like ? or tbp.`title` like ?)"; 645 $bindvars[] = $findesc; 646 $bindvars[] = $findesc; 647 } 648 649 if ($date_min) { 650 $mid[] = "tbp.`created`>=?"; 651 $bindvars[] = (int)$date_min; 652 } 653 if ($date_max) { 654 $mid[] = "tbp.`created`<=?"; 655 $bindvars[] = (int)$date_max; 656 } 657 658 $mid = empty($mid) ? '' : 'where ' . implode(' and ', $mid); 659 660 $join = ''; 661 if ($jail = $categlib->get_jail()) { 662 $categlib->getSqlJoin($jail, 'blog post', '`tbp`.`postId`', $join, $mid, $bindvars); 663 } 664 665 $query = "select tbp.*,tb.title as blogTitle from `tiki_blog_posts` as tbp, `tiki_blogs` as tb $join $mid order by " . $this->convertSortMode($sort_mode); 666 $query_cant = "select count(*) from `tiki_blog_posts` as tbp, `tiki_blogs` as tb $join $mid"; 667 $result = $this->query($query, $bindvars, $maxRecords, $offset); 668 $cant = $this->getOne($query_cant, $bindvars); 669 $ret = []; 670 671 while ($res = $result->fetchRow()) { 672 $res["comments"] = TikiLib::lib('comments')->count_comments('blog post:' . $res['postId']); 673 $res['pages'] = $this->get_number_of_pages($res['data']); 674 $res['avatar'] = $tikilib->get_user_avatar($res['user']); 675 676 $is_html = $res['wysiwyg'] === 'y' && $prefs['wysiwyg_htmltowiki'] !== 'y'; 677 678 $res['parsed_excerpt'] = $parserlib->parse_data($res['excerpt'], ['is_html' => $is_html]); 679 $res['parsed_data'] = $parserlib->parse_data($res['data'], ['is_html' => $is_html]); 680 681 if ($prefs['feature_freetags'] == 'y') { // And get the Tags for the posts 682 $res['freetags'] = TikiLib::lib('freetag')->get_tags_on_object($res['postId'], 'blog post'); 683 } else { 684 $res['freetags'] = []; 685 } 686 687 $ret[] = $res; 688 } 689 690 $ret = Perms::filter([ 'type' => 'blog post' ], 'object', $ret, [ 'object' => 'postId' ], ['read_blog', 'blog_post_view_ref']); 691 692 $retval = []; 693 $retval['data'] = $ret; 694 $retval['cant'] = $cant; 695 696 return $retval; 697 } 698 699 /** 700 * list_blog_post_comments List all the comments in posts for all the blogs 701 * 702 * @param string $approved 703 * @param int $maxRecords 704 * @access public 705 * @return void 706 */ 707 function list_blog_post_comments($approved = 'y', $maxRecords = -1) 708 { 709 global $user, $tiki_p_admin, $tiki_p_blog_admin, $tiki_p_blog_post; 710 $userlib = TikiLib::lib('user'); 711 $tikilib = TikiLib::lib('tiki'); 712 713 // TODO: use commentslib instead of querying database directly 714 // Blog Recent Comments 715 $query = "SELECT b.`title`, b.`postId`, b.`priv`, blog.`user`, blog.`public`, c.`threadId`, c.`title` as commentTitle, c.`website`, `commentDate`, `userName` FROM `tiki_comments` c, `tiki_blog_posts` b, `tiki_blogs` blog WHERE `objectType`='blog post' AND b.`postId`=c.`object` AND blog.`blogId`=b.`blogId`"; 716 717 $bindvars = []; 718 $globalperms = Perms::get(); 719 if (! $globalperms->admin_comment) { 720 $query .= ' AND `approved`=?'; 721 $bindvars[] = $approved; 722 } else { 723 $approved = null; 724 } 725 726 $query .= " ORDER BY `commentDate` desc"; 727 $result = $this->fetchAll($query, $bindvars, $maxRecords); 728 $result = Perms::filter(['type' => 'blog post'], 'object', $result, ['object' => 'postId'], ['read_blog', 'blog_post_view_ref']); 729 730 $ret = []; 731 foreach ($result as $res) { 732 // Private posts can be accessed on the following conditions: 733 // user has tiki_p_admin or tiki_p_blog_admin or has written the post 734 // If blog is configured with 'Allow other user to post in this blog', then also if user has tiki_p_blog_post or is owner of this blog 735 if (($res['priv'] != 'y') 736 or ($tiki_p_admin == 'y' ) 737 or ($tiki_p_blog_admin == 'y') 738 or ( ($res["public"] == 'y') && ($user && $user == $res["user"]) ) 739 or ( ($res["public"] == 'y') && ($tiki_p_blog_post == 'y') ) ) { 740 $ret[] = $res; 741 } 742 } 743 744 // just to distinct between user and anonymous (should be done in commentslib and not here) 745 foreach ($ret as $key => $comment) { 746 if (! $userlib->user_exists($comment['userName'])) { 747 $ret[$key]['anonymous_name'] = $comment['userName']; 748 } 749 } 750 751 return ['data' => $ret, 'cant' => count($ret)]; 752 } 753 754 /** 755 * list_all_blog_posts Returns all the posts filtered by $date and $find 756 * 757 * @param int $offset 758 * @param int $maxRecords 759 * @param string $sort_mode 760 * @param string $find 761 * @param string $date 762 * @access public 763 * @return void 764 */ 765 function list_all_blog_posts($offset = 0, $maxRecords = -1, $sort_mode = 'created_desc', $find = '', $date = '') 766 { 767 768 if ($find) { 769 $findesc = '%' . $find . '%'; 770 771 $mid = " where (`data` like ?) "; 772 $bindvars = [$findesc]; 773 } else { 774 $mid = ""; 775 $bindvars = []; 776 } 777 778 if ($date) { 779 $bindvars[] = $date; 780 if ($mid) { 781 $mid .= " and `created`<=? "; 782 } else { 783 $mid .= " where `created`<=? "; 784 } 785 } 786 787 $query = "select * from `tiki_blog_posts` $mid order by " . $this->convertSortMode($sort_mode); 788 $query_cant = "select count(*) from `tiki_blog_posts` $mid"; 789 $result = $this->fetchAll($query, $bindvars, $maxRecords, $offset); 790 $cant = $this->getOne($query_cant, $bindvars); 791 $ret = []; 792 793 $result = Perms::filter(['type' => 'blog post'], 'object', $result, ['object' => 'postId'], ['read_blog', 'blog_post_view_ref']); 794 795 foreach ($result as $res) { 796 $query2 = "select `title` from `tiki_blogs` where `blogId`=?"; 797 $title = $this->getOne($query2, [$res["blogId"]]); 798 $res["blogtitle"] = $title; 799 $ret[] = $res; 800 } 801 802 $retval = []; 803 $retval["data"] = $ret; 804 $retval["cant"] = $cant; 805 return $retval; 806 } 807 808 /** 809 * blog_post Stores a blog post 810 * 811 * @param int $blogId 812 * @param string $data 813 * @param string $excerpt 814 * @param string $user 815 * @param string $title 816 * @param string $contributions 817 * @param string $priv 818 * @param bool $is_wysiwyg 819 * @access public 820 * @return int postId 821 */ 822 function blog_post($blogId, $data, $excerpt, $user, $title = '', $contributions = '', $priv = 'n', $created = 0, $is_wysiwyg = false) 823 { 824 // update tiki_blogs and call activity functions 825 global $prefs; 826 $tikilib = TikiLib::lib('tiki'); 827 $smarty = TikiLib::lib('smarty'); 828 829 if ($is_wysiwyg) { 830 $data = TikiFilter::get('purifier')->filter($data); 831 $excerpt = TikiFilter::get('purifier')->filter($excerpt); 832 } 833 834 $wysiwyg = $is_wysiwyg == true ? 'y' : 'n'; 835 if (! $created) { 836 $created = $tikilib->now; 837 } 838 839 $query = "insert into `tiki_blog_posts`(`blogId`,`data`,`excerpt`,`created`,`user`,`title`,`priv`,`wysiwyg`) values(?,?,?,?,?,?,?,?)"; 840 $result = $this->query($query, [(int) $blogId, $data, $excerpt, (int) $created, $user, $title, $priv, $wysiwyg]); 841 $query = "select max(`postId`) from `tiki_blog_posts` where `created`=? and `user`=?"; 842 $id = $this->getOne($query, [(int) $created, $user]); 843 $query = "update `tiki_blogs` set `lastModif`=?,`posts`=`posts`+1 where `blogId`=?"; 844 $result = $this->query($query, [(int) $created, (int) $blogId]); 845 $this->add_blog_activity($blogId); 846 847 $wikilib = TikiLib::lib('wiki'); 848 $wikilib->update_wikicontent_relations($data, 'post', $id); 849 $wikilib->update_wikicontent_links($data, 'post', $id); 850 851 if ($prefs['feature_user_watches'] == 'y' or $prefs['feature_group_watches'] == 'y') { 852 $nots = $tikilib->get_event_watches('blog_post', $blogId); 853 if (! isset($_SERVER["SERVER_NAME"])) { 854 $_SERVER["SERVER_NAME"] = $_SERVER["HTTP_HOST"]; 855 } 856 857 if ($prefs['user_blog_watch_editor'] != "y") { 858 for ($i = count($nots) - 1; $i >= 0; --$i) { 859 if ($nots[$i]['user'] == $user) { 860 unset($nots[$i]); 861 break; 862 } 863 } 864 } 865 866 if ($prefs['feature_daily_report_watches'] == 'y') { 867 $query = "select `title` from `tiki_blogs` where `blogId`=?"; 868 $blogTitle = $this->getOne($query, [(int)$blogId]); 869 $reportsManager = Reports_Factory::build('Reports_Manager'); 870 $reportsManager->addToCache($nots, ["event" => 'blog_post', "blogId" => $blogId, "blogTitle" => $blogTitle, "postId" => $id, "user" => $user]); 871 } 872 873 if (count($nots)) { 874 include_once("lib/notifications/notificationemaillib.php"); 875 $smarty->assign('mail_site', $_SERVER["SERVER_NAME"]); 876 $smarty->assign('mail_title', $this->get_title($blogId)); 877 $smarty->assign('mail_post_title', $title); 878 $smarty->assign('mail_blogid', $blogId); 879 $smarty->assign('mail_postid', $id); 880 $smarty->assign('mail_user', $user); 881 $smarty->assign('mail_data', $data); 882 883 if ($prefs['feature_contribution'] == 'y' && ! empty($contributions)) { 884 $contributionlib = TikiLib::lib('contribution'); 885 $smarty->assign('mail_contributions', $contributionlib->print_contributions($contributions)); 886 } 887 sendEmailNotification($nots, "watch", "user_watch_blog_post_subject.tpl", $_SERVER["SERVER_NAME"], "user_watch_blog_post.tpl"); 888 } 889 } 890 891 TikiLib::events()->trigger( 892 'tiki.blogpost.create', 893 [ 894 'type' => 'blog post', 895 'object' => $id, 896 'blog' => $blogId, 897 'user' => $user, 898 ] 899 ); 900 901 if ($prefs['feature_actionlog'] == 'y') { 902 $logslib = TikiLib::lib('logs'); 903 $logslib->add_action('Posted', $blogId, 'blog', "blogId=$blogId&postId=$id&add=" . strlen($data) . "#postId$id", '', '', '', '', $contributions); 904 } 905 906 require_once(__DIR__ . '/../search/refresh-functions.php'); 907 refresh_index('blog_posts', $id); 908 909 $tikilib->object_post_save(['type' => 'blog post', 'object' => $id, 'description' => substr($data, 0, 200), 'name' => $title, 'href' => "tiki-view_blog_post.php?postId=$id"], ['content' => $data]); 910 return $id; 911 } 912 913 /** 914 * remove_blog Removes a blog and all the posts of a blog 915 * 916 * @param int $blogId 917 * @access public 918 * @return boolean unconditionnal true 919 */ 920 function remove_blog($blogId) 921 { 922 global $user; 923 $tikilib = TikiLib::lib('tiki'); 924 925 $query = "delete from `tiki_blogs` where `blogId`=?"; 926 927 $result = $this->query($query, [(int) $blogId]); 928 929 $query = "select `postId` from `tiki_blog_posts` where `blogId`=?"; 930 $result = $this->query($query, [(int) $blogId]); 931 if ($res = $result->fetchRow()) { 932 $tikilib->remove_object('post', $res['postId']); 933 } 934 935 $query = "delete from `tiki_blog_posts` where `blogId`=?"; 936 $result = $this->query($query, [(int) $blogId]); 937 $tikilib->remove_object('blog', $blogId); 938 939 TikiLib::events()->trigger( 940 'tiki.blog.delete', 941 [ 942 'type' => 'blog', 943 'object' => $blogId, 944 'user' => $user, 945 ] 946 ); 947 948 return true; 949 } 950 951 /** 952 * remove_post Removes a post identified by $postId 953 * 954 * @param int $postId 955 * @access public 956 * @return boolean inconditionnal true 957 */ 958 function remove_post($postId) 959 { 960 $tikilib = TikiLib::lib('tiki'); 961 $objectlib = TikiLib::lib('object'); 962 963 $query = "select `blogId`, `data` from `tiki_blog_posts` where `postId`=?"; 964 $result = $this->query($query, [(int) $postId]); 965 if ($res = $result->fetchRow()) { 966 $blogId = $res['blogId']; 967 } else { 968 $blogId = 0; 969 } 970 971 global $prefs; 972 if ($prefs['feature_actionlog'] == 'y') { 973 $logslib = TikiLib::lib('logs'); 974 $param = "blogId=$blogId&postId=$postId"; 975 if ($blogId) { 976 $param .= "&del=" . strlen($res['data']); 977 } 978 $logslib->add_action('Removed', $blogId, 'blog', $param); 979 } 980 if ($blogId) { 981 $tikilib->remove_object('post', (int)$postId); 982 $query = "delete from `tiki_blog_posts` where `postId`=?"; 983 984 $result = $this->query($query, [(int) $postId]); 985 $query = "update `tiki_blogs` set `posts`=`posts`-1 where `blogId`=?"; 986 $result = $this->query($query, [(int) $blogId]); 987 } 988 989 /* 990 * TODO: this should be a method in freetaglib or maybe even better $tikilib->remove_object() should 991 * remove the relation between the object and the tags, no? 992 */ 993 // When a post is deleted, all freetags asociated must also be deleted 994 $objectId = $objectlib->get_object_id('blog post', $postId); 995 $query = "DELETE FROM `tiki_freetagged_objects` WHERE `objectId` = ?"; 996 $this->query($query, [(int) $objectId]); 997 998 $query = "delete from `tiki_blog_posts_images` where `postId`=?"; 999 $this->query($query, [(int) $postId]); 1000 1001 $tikilib->remove_object('blog post', $postId); 1002 1003 TikiLib::events()->trigger( 1004 'tiki.blogpost.delete', 1005 [ 1006 'type' => 'blog post', 1007 'object' => $postId, 1008 'blog' => $blogId, 1009 'user' => $GLOBALS['user'], 1010 ] 1011 ); 1012 1013 return true; 1014 } 1015 1016 /** 1017 * get_post Returns the post identfied by $postId 1018 * Returns false if the post does not exist 1019 * 1020 * @param mixed $postId 1021 * @param bool $adjacent whether to return or not adjacent posts 1022 * @access public 1023 * @return The post 1024 */ 1025 function get_post($postId, $adjacent = false) 1026 { 1027 $tikilib = TikiLib::lib('tiki'); 1028 1029 $query = "select * from `tiki_blog_posts` where `postId`=?"; 1030 $result = $this->query($query, [(int) $postId]); 1031 if ($result->numRows()) { 1032 $res = $result->fetchRow(); 1033 $res['avatar'] = $tikilib->get_user_avatar($res['user']); 1034 1035 if ($adjacent) { 1036 $res['adjacent'] = $this->_get_adjacent_posts($res['blogId'], $res['created']); 1037 } 1038 } else { 1039 return false; 1040 } 1041 return $res; 1042 } 1043 1044 /** 1045 * Get post related content using $freetaglib->get_similar() 1046 * 1047 * @param int $postId 1048 * @param int $maxResults 1049 * @return array 1050 */ 1051 function get_related_posts($postId, $maxResults = 5) 1052 { 1053 $freetaglib = TikiLib::lib('freetag'); 1054 $related_posts = $freetaglib->get_similar('blog post', $postId, $maxResults); 1055 1056 // extract 'postId' from href to be able to use {self_link} 1057 foreach ($related_posts as $key => $post) { 1058 $related_posts[$key]['postId'] = str_replace('tiki-view_blog_post.php?postId=', '', $post['href']); 1059 } 1060 1061 return $related_posts; 1062 } 1063 1064 /** 1065 * Get adjacent posts (previous and next by created date) 1066 * 1067 * @param int $blogId which blog the post belongs to 1068 * @param int $created when the post was created 1069 * @return array 1070 */ 1071 function _get_adjacent_posts($blogId, $created, $publishDate = null, $user = null, $allowprivate = null) 1072 { 1073 $res = []; 1074 1075 $next_query = 'SELECT postId, title FROM `tiki_blog_posts` WHERE `blogId` = ? AND `created` > ? '; 1076 $bindvars = [$blogId, $created]; 1077 if ($publishDate) { 1078 $next_query .= 'AND (`created` <= ? OR `user` = ?)'; 1079 $bindvars[] = $publishDate; 1080 $bindvars[] = $user; 1081 } 1082 if ($allowprivate == 'n') { 1083 $next_query .= ' AND `priv` = "n"'; 1084 } 1085 $next_query .= ' ORDER BY created ASC'; 1086 $result = $this->fetchAll($next_query, $bindvars, 1); 1087 $res['next'] = ! empty($result[0]) ? $result[0] : null; 1088 1089 $prev_query = 'SELECT postId, title FROM `tiki_blog_posts` WHERE `blogId` = ? AND `created` < ? '; 1090 $bindvars = [$blogId, $created]; 1091 if ($publishDate) { 1092 $prev_query .= 'AND (`created` <= ? OR `user` = ?)'; 1093 $bindvars[] = $publishDate; 1094 $bindvars[] = $user; 1095 } 1096 if ($allowprivate == 'n') { 1097 $prev_query .= ' AND `priv` = "n"'; 1098 } 1099 $prev_query .= ' ORDER BY created DESC'; 1100 $result = $this->fetchAll($prev_query, $bindvars, 1); 1101 $res['prev'] = ! empty($result[0]) ? $result[0] : null; 1102 1103 return $res; 1104 } 1105 1106 /** 1107 * Updates a blog post 1108 * 1109 * @param int $postId 1110 * @param int $blogId 1111 * @param string $data 1112 * @param string $excerpt 1113 * @param string $user 1114 * @param string $title 1115 * @param string $contributions 1116 * @param string $priv 1117 * @param bool $is_wysiwyg 1118 * @access public 1119 * @return void 1120 */ 1121 function update_post( 1122 $postId, 1123 $blogId, 1124 $data, 1125 $excerpt, 1126 $user, 1127 $title = '', 1128 $contributions = '', 1129 $priv = 'n', 1130 $created = 0, 1131 $is_wysiwyg = false 1132 ) { 1133 1134 global $prefs; 1135 $tikilib = TikiLib::lib('tiki'); 1136 1137 if ($is_wysiwyg) { 1138 $data = TikiFilter::get('purifier')->filter($data); 1139 $excerpt = TikiFilter::get('purifier')->filter($excerpt); 1140 } 1141 1142 $wysiwyg = $is_wysiwyg == true ? 'y' : 'n'; 1143 if ($prefs['feature_blog_edit_publish_date'] == 'y') { 1144 if (! $created) { 1145 $created = $tikilib->now; 1146 } 1147 $query = "update `tiki_blog_posts` set `blogId`=?,`data`=?,`excerpt`=?,`created`=?,`user`=?,`title`=?, `priv`=?, `wysiwyg`=? where `postId`=?"; 1148 $result = $this->query($query, [$blogId, $data, $excerpt, $created,$user, $title, $priv, $wysiwyg, $postId]); 1149 } else { 1150 $query = "update `tiki_blog_posts` set `blogId`=?,`data`=?,`excerpt`=?,`user`=?,`title`=?, `priv`=?, `wysiwyg`=? where `postId`=?"; 1151 $result = $this->query($query, [$blogId, $data, $excerpt, $user, $title, $priv, $wysiwyg, $postId]); 1152 } 1153 1154 $wikilib = TikiLib::lib('wiki'); 1155 $wikilib->update_wikicontent_relations($data, 'post', $postId); 1156 $wikilib->update_wikicontent_links($data, 'post', $postId); 1157 1158 if ($prefs['feature_actionlog'] == 'y') { 1159 $logslib = TikiLib::lib('logs'); 1160 $logslib->add_action('Updated', $blogId, 'blog', "blogId=$blogId&postId=$postId#postId$postId", '', '', '', '', $contributions); 1161 } 1162 1163 require_once('lib/search/refresh-functions.php'); 1164 refresh_index('blog_posts', $postId); 1165 1166 $tikilib->object_post_save(['type' => 'blog post', 'object' => $postId], ['content' => $data]); 1167 } 1168 1169 /** 1170 * list_user_posts Returns all the posts from a user 1171 * 1172 * @param string $user login name of the user 1173 * @param int $offset 1174 * @param int $maxRecords 1175 * @param string $sort_mode 1176 * @param string $find 1177 * @access public 1178 * @return void 1179 */ 1180 function list_user_posts($user, $offset = 0, $maxRecords = -1, $sort_mode = 'created_desc', $find = '') 1181 { 1182 1183 if ($find) { 1184 $findesc = '%' . $find . '%'; 1185 1186 $mid = " where `user`=? and (`data` like ?) "; 1187 $bindvars = [$user, $findesc]; 1188 } else { 1189 $mid = ' where `user`=? '; 1190 $bindvars = [$user]; 1191 } 1192 1193 $query = "select * from `tiki_blog_posts` $mid order by " . $this->convertSortMode($sort_mode); 1194 $query_cant = "select count(*) from `tiki_blog_posts` $mid"; 1195 $result = $this->query($query, $bindvars, $maxRecords, $offset); 1196 $cant = $this->getOne($query_cant, $bindvars); 1197 $ret = []; 1198 1199 while ($res = $result->fetchRow()) { 1200 $ret[] = $res; 1201 } 1202 1203 $retval = []; 1204 $retval["data"] = $ret; 1205 $retval["cant"] = $cant; 1206 return $retval; 1207 } 1208 1209 /** 1210 * add_blog_activity 1211 * 1212 * @param mixed $blogId 1213 * @access public 1214 * @return void 1215 */ 1216 function add_blog_activity($blogId) 1217 { 1218 $tikilib = TikiLib::lib('tiki'); 1219 1220 //Caclulate activity, update tiki_blogs and purge activity table 1221 $today = $tikilib->make_time(0, 0, 0, $tikilib->date_format("%m"), $tikilib->date_format("%d"), $tikilib->date_format("%Y")); 1222 1223 $day0 = $today - (24 * 60 * 60); 1224 $day1 = $today - (2 * 24 * 60 * 60); 1225 $day2 = $today - (3 * 24 * 60 * 60); 1226 // Purge old activity 1227 $query = "delete from `tiki_blog_activity` where `day`<?"; 1228 $result = $this->query($query, [(int) $day2]); 1229 1230 // Register new activity 1231 $query = "select count(*) from `tiki_blog_activity` where `blogId`=? and `day`=?"; 1232 $result = $this->getOne($query, [(int) $blogId, (int)$today]); 1233 1234 if ($result) { 1235 $query = "update `tiki_blog_activity` set `posts`=`posts`+1 where `blogId`=? and `day`=?"; 1236 } else { 1237 $query = "insert into `tiki_blog_activity`(`blogId`,`day`,`posts`) values(?,?,1)"; 1238 } 1239 1240 $result = $this->query($query, [(int) $blogId, (int) $today]); 1241 // Calculate activity 1242 $query = "select `posts` from `tiki_blog_activity` where `blogId`=? and `day`=?"; 1243 $vtoday = $this->getOne($query, [(int) $blogId, (int) $today]); 1244 $day0 = $this->getOne($query, [(int) $blogId, (int) $day0]); 1245 $day1 = $this->getOne($query, [(int) $blogId, (int) $day1]); 1246 $day2 = $this->getOne($query, [(int) $blogId, (int) $day2]); 1247 $activity = (2 * $vtoday) + ($day0) + (0.5 * $day1) + (0.25 * $day2); 1248 // Update tiki_blogs with activity information 1249 $query = "update `tiki_blogs` set `activity`=? where `blogId`=?"; 1250 $result = $this->query($query, [$activity, (int) $blogId]); 1251 } 1252 1253 /** 1254 * Returns the title of the blog "blogId" 1255 * 1256 * @param int $blogId 1257 * @access public 1258 * @return string the title of the blog 1259 */ 1260 function get_title($blogId) 1261 { 1262 $query = 'select `title` from `tiki_blogs` where `blogId`=?'; 1263 return $this->getOne($query, [(int)$blogId]); 1264 } 1265 1266 /** 1267 * Return true if blog exist or false if not 1268 * 1269 * @param int $blogId 1270 * @return bool true or false depending if blog exist or not 1271 */ 1272 function blog_exists($blogId) 1273 { 1274 $query = 'SELECT `blogId` FROM `tiki_blogs` WHERE `blogId`=?'; 1275 1276 if (is_null($this->getOne($query, [$blogId]))) { 1277 return false; 1278 } else { 1279 return true; 1280 } 1281 } 1282 1283 /** 1284 * Check if a blog exists 1285 * 1286 * @param int $blogId 1287 * @return bool true or false if blog exists or not 1288 */ 1289 function check_blog_exists($blogId) 1290 { 1291 $smarty = TikiLib::lib('smarty'); 1292 1293 if (! $this->blog_exists($blogId)) { 1294 $msg = tra('Blog cannot be found'); 1295 $smarty->assign('msg', $msg); 1296 $smarty->display('error.tpl'); 1297 die; 1298 } 1299 } 1300 1301 /** 1302 * Returns a list of posts that belongs to a particular blog 1303 * 1304 * @param int $blogId 1305 * @return array list of post ids 1306 */ 1307 function get_blog_posts_ids($blogId) 1308 { 1309 $query = 'SELECT `postId` FROM `tiki_blog_posts` WHERE `blogId`=?'; 1310 $result = $this->fetchMap($query, [$blogId]); 1311 1312 return array_keys($result); 1313 } 1314 function top_bloggers($limit, $blogId = null) 1315 { 1316 $mid = ''; 1317 $bindvars = []; 1318 if ($blogId) { 1319 $mid = 'where `blogId`=?'; 1320 $bindvars = [$blogId]; 1321 } 1322 $query = 'select distinct(`user`), count(`user`) as posts from `tiki_blog_posts` ' . $mid . ' group by `user` order by `posts` desc'; 1323 $result = $this->query($query, $bindvars, $limit, 0); 1324 $ret = []; 1325 while ($res = $result->fetchRow()) { 1326 $ret[] = $res; 1327 } 1328 $query = 'select count(distinct(`user`)) from `tiki_blog_posts`'; 1329 $nb = $this->getOne($query); 1330 return ['data' => $ret, 'count' => $nb]; 1331 } 1332 function mod_blog_posts(&$blogItems, $charCount, $wordBoundary = 'y', $ellipsis = 'y', $more = 'y') 1333 { 1334 $smarty = TikiLib::lib('smarty'); 1335 1336 /* The function takes an argument asking if the break should occur on a 1337 word boundary. The truncate function asks if words can be broken. 1338 The same question is asked inversely so the supplied parameter needs 1339 to be reversed to remain accurate. */ 1340 $breakword = ($wordBoundary == 'y') ? false : true; 1341 1342 $etc = ($ellipsis == 'y') ? ' ... ' : ' '; 1343 $numBlogs = count($blogItems["data"]); 1344 for ($i = 0; $i < $numBlogs; $i++) { 1345 $pos = 0; 1346 $counter = 'char'; 1347 $arrString = []; 1348 $tally = [ "char" => 0, "tags" => 0 ]; 1349// preg_match_all("[\s|\w]",$blogItems['data'][$i]['parsed_data'],$arrString); 1350 $arrString = $blogItems['data'][$i]['parsed_data']; 1351 1352 /* We don't want to stop this loop until we've counted sufficient displaying 1353 characters, not just string positions */ 1354 for ($pos = 0; $tally['char'] < $charCount; $pos++) { 1355 if ($arrString[$pos] == '<' && $counter == 'char') { 1356 $counter = 'tags'; 1357 } elseif ($arrString[$pos] == '>' && $counter == 'tags') { 1358 $counter = 'char'; 1359 } 1360 $tally[$counter]++; 1361 } 1362 $segLength = $charCount + $tally['tags']; 1363 $smarty->loadPlugin('smarty_modifier_truncate'); 1364 $blogItems['data'][$i]['parsed_data'] = 1365 smarty_modifier_truncate( 1366 $blogItems['data'][$i]['parsed_data'], 1367 $segLength, 1368 $etc, 1369 $breakword 1370 ); 1371 1372 if ($more == 'y') { 1373 $blogItems['data'][$i]['parsed_data'] .= 1374 '<a class="link" href="tiki-view_blog_post.php?postId=' . 1375 $blogItems['data'][$i]['postId'] . '"> <more></a>'; 1376 } 1377 unset($arrString); 1378 } 1379 return( $blogItems ); 1380 } 1381 1382 /** 1383 * Return blogId from postId 1384 * 1385 * @param int $postId 1386 * 1387 * @return int $blogId or false 1388 */ 1389 function get_blogId_from_post($postId) 1390 { 1391 $query = "SELECT `blogId` FROM `tiki_blog_posts` WHERE postId=?"; 1392 $result = $this->query($query, [$postId]); 1393 if ($result->numRows()) { 1394 $res = $result->fetchRow(); 1395 return $res['blogId']; 1396 } else { 1397 return false; 1398 } 1399 } 1400} 1401