Textpattern | PHP Cross Reference | Content Management Systems |
Description: Textpattern Wrapper Class for Textpattern 4.0.x. Main goal for this class is to be used as a textpattern data wrapper by any code which needs to have access to the textpattern articles data, like XML-RPC, Atom, Moblogging or other external implementations.
1 <?php 2 3 /* 4 * Textpattern Content Management System 5 * http://textpattern.com 6 * 7 * Copyright (C) 2016 The Textpattern Development Team 8 * 9 * This file is part of Textpattern. 10 * 11 * Textpattern is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation, version 2. 14 * 15 * Textpattern is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with Textpattern. If not, see <http://www.gnu.org/licenses/>. 22 */ 23 24 /** 25 * Textpattern Wrapper Class for Textpattern 4.0.x. 26 * 27 * Main goal for this class is to be used as a textpattern data wrapper by 28 * any code which needs to have access to the textpattern articles data, 29 * like XML-RPC, Atom, Moblogging or other external implementations. 30 * 31 * This class requires including some Textpattern files in order to work 32 * properly. See RPC Server implementation to view an example of the required 33 * files and predefined variables. 34 * 35 * @link http://web.archive.org/web/20141201035729/http://txp.kusor.com/wrapper 36 * @author Pedro Palazón 37 * @copyright 2005-2008 The Textpattern Development Team - http://textpattern.com 38 */ 39 40 if (!defined('txpath')) { 41 die('txpath is undefined.'); 42 } 43 44 include_once txpath.'/include/txp_auth.php'; 45 46 if (!defined('LEAVE_TEXT_UNTOUCHED')) { 47 /** 48 * @ignore 49 */ 50 51 define('LEAVE_TEXT_UNTOUCHED', 0); 52 } 53 54 if (!defined('USE_TEXTILE')) { 55 /** 56 * @ignore 57 */ 58 59 define('USE_TEXTILE', 1); 60 } 61 62 if (!defined('CONVERT_LINEBREAKS')) { 63 /** 64 * @ignore 65 */ 66 67 define('CONVERT_LINEBREAKS', 2); 68 } 69 70 /** 71 * Wrapper for Textpattern. 72 * 73 * @package Wrapper 74 */ 75 76 class TXP_Wrapper 77 { 78 /** 79 * The current user. 80 * 81 * Remember to always use $this->txp_user when checking 82 * for permissions with this class. 83 * 84 * @var string 85 */ 86 87 public $txp_user = null; 88 89 /** 90 * Authenticated connection. 91 * 92 * @var bool 93 */ 94 95 public $loggedin = false; 96 97 /** 98 * Predefined Textpattern variables to be populated. 99 * 100 * @var array 101 */ 102 103 public $vars = array( 104 'ID', 105 'Title', 106 'Title_html', 107 'Body', 108 'Body_html', 109 'Excerpt', 110 'Excerpt_html', 111 'textile_excerpt', 112 'Image', 113 'textile_body', 114 'Keywords', 115 'Status', 116 'Posted', 117 'Section', 118 'Category1', 119 'Category2', 120 'Annotate', 121 'AnnotateInvite', 122 'AuthorID', 123 'Posted', 124 'override_form', 125 'url_title', 126 'custom_1', 127 'custom_2', 128 'custom_3', 129 'custom_4', 130 'custom_5', 131 'custom_6', 132 'custom_7', 133 'custom_8', 134 'custom_9', 135 'custom_10', 136 ); 137 138 /** 139 * Constructor. 140 * 141 * This is used to pass user credentials 142 * to the wrapper. 143 * 144 * @param string $txp_user The user login name 145 * @param string $txpass User password 146 * @example 147 * $wrapper = new TXP_wrapper('username', 'password'); 148 */ 149 150 public function __construct($txp_user, $txpass = null) 151 { 152 if ($this->_validate($txp_user, $txpass)) { 153 $this->txp_user = $txp_user; 154 $this->loggedin = true; 155 } 156 } 157 158 /** 159 * Deletes an article with the given ID. 160 * 161 * @param int $article_id The article 162 * @return bool TRUE on success 163 */ 164 165 public function deleteArticleID($article_id) 166 { 167 $article_id = assert_int($article_id); 168 169 if ($this->loggedin && has_privs('article.delete', $this->txp_user)) { 170 return safe_delete('textpattern', "ID = $article_id"); 171 } elseif ($this->loggedin && has_privs('article.delete.own', $this->txp_user)) { 172 $r = safe_field("ID", 'textpattern', "ID = $article_id AND AuthorID = '".doSlash($this->txp_user)."'"); 173 174 if ($r || has_privs('article.delete', $this->txp_user)) { 175 return safe_delete('textpattern', "ID = $article_id"); 176 } 177 } 178 179 return false; 180 } 181 182 /** 183 * Retrieves a list of articles matching the given criteria. 184 * 185 * This method forms an SQL query from the given arguments and returns an 186 * array of resulting articles. 187 * 188 * This method requires authentication and at least 'article.edit.own' 189 * privileges. If the user doesn't have 'article.edit' privileges, 190 * only the user's own articles can be accessed. 191 * 192 * @param string $what The select clause 193 * @param string $where The where clause 194 * @param int $offset The offset 195 * @param int $limit The limit 196 * @param bool $slash If TRUE, escapes $where and $what 197 * @return array|bool Array of artilces, or FALSE on failure 198 */ 199 200 public function getArticleList($what = '*', $where = '1', $offset = 0, $limit = 10, $slash = true) 201 { 202 if ($this->loggedin && has_privs('article.edit.own', $this->txp_user)) { 203 $offset = assert_int($offset); 204 $limit = assert_int($limit); 205 206 if ($slash) { 207 $where = doSlash($where); 208 $what = doSlash($what); 209 } 210 211 if (has_privs('article.edit', $this->txp_user)) { 212 $rs = safe_rows_start($what, 'textpattern', $where." ORDER BY Posted DESC LIMIT $offset, $limit"); 213 } else { 214 $rs = safe_rows_start($what, 'textpattern', $where." AND AuthorID = '".doSlash($this->txp_user)."' ORDER BY Posted DESC LIMIT $offset, $limit"); 215 } 216 217 $out = array(); 218 219 if ($rs) { 220 while ($a = nextRow($rs)) { 221 $out[] = $a; 222 } 223 } 224 225 return $out; 226 } 227 228 return false; 229 } 230 231 /** 232 * Retrieves an article matching the given criteria. 233 * 234 * This method forms an SQL query from the given arguments and returns an 235 * article as an assocative array. 236 * 237 * This method requires authentication and at least 'article.edit.own' 238 * privileges. If the user doesn't have 'article.edit' privileges, 239 * only the user's own articles can be accessed. 240 * 241 * @param string $what Select clause 242 * @param string $where Where clause 243 * @param bool $slash If TRUE, escapes $where and $what 244 * @return array|bool An article, or FALSE on failure 245 * @see TXP_Wrapper::getArticleList() 246 * @example 247 * $wrapper = new TXP_wrapper('username', 'password'); 248 * if ($r = $wrapper->getArticle()) 249 * { 250 * echo "Returned an article by the title '{$r['Title']}'."; 251 * } 252 */ 253 254 public function getArticle($what = '*', $where = '1', $slash = true) 255 { 256 if ($this->loggedin && has_privs('article.edit.own', $this->txp_user)) { 257 if ($slash) { 258 $what = doSlash($what); 259 $where = doSlash($where); 260 } 261 262 // Higher user groups should be able to edit any article. 263 if (has_privs('article.edit', $this->txp_user)) { 264 return safe_row($what, 'textpattern', $where); 265 } else { 266 // While restricted users should be able to edit their own 267 // articles only. 268 return safe_row($what, 'textpattern', $where." AND AuthorID = '".doSlash($this->txp_user)."'"); 269 } 270 } 271 272 return false; 273 } 274 275 /** 276 * Gets an article with the given ID. 277 * 278 * This method is an shortcut for TXP_Wrapper::getArticle(). 279 * 280 * @param int $article_id The article 281 * @param string $what The SQL select clause 282 * @return array|bool The article, or FALSE on failure 283 * @see TXP_Wrapper::getArticle() 284 * @example 285 * $wrapper = new TXP_wrapper('username', 'password'); 286 * if ($r = $wrapper->getArticleID(11)) 287 * { 288 * echo "Returned an article by the ID of '{$r['ID']}'."; 289 * } 290 */ 291 292 public function getArticleID($article_id, $what = '*') 293 { 294 if ($this->loggedin && has_privs('article.edit.own', $this->txp_user)) { 295 $article_id = assert_int($article_id); 296 297 if (has_privs('article.edit', $this->txp_user)) { 298 return safe_row(doSlash($what), 'textpattern', "ID = $article_id"); 299 } else { 300 return safe_row(doSlash($what), 'textpattern', "ID = $article_id AND AuthorID = '".doSlash($this->txp_user)."'"); 301 } 302 } 303 304 return false; 305 } 306 307 /** 308 * Updates an existing article. 309 * 310 * This method takes an array of article fields, and updates an article with 311 * the given ID. Supplied values are sanitised and prepared internally. 312 * 313 * @param int $article_id The article 314 * @param array $params The article fields to update 315 * @return int|bool The article id, or FALSE on failure 316 * @example 317 * $wrapper = new TXP_wrapper('username', 'password'); 318 * if (($id = $wrapper->updateArticleID(11, array( 319 * 'Title' => 'New title', 320 * 'Body' => 'Body text.', 321 * )) !== false) 322 * { 323 * echo "Updated article '{$id}'."; 324 * } 325 */ 326 327 public function updateArticleID($article_id, $params) 328 { 329 $article_id = assert_int($article_id); 330 $r = safe_field("ID", 'textpattern', "AuthorID = '".doSlash($this->txp_user)."' AND ID = $article_id"); 331 332 if ($this->loggedin && $r && has_privs('article.edit.own', $this->txp_user)) { 333 // Unprivileged user, check if they can edit published articles. 334 $r = assert_int($r); 335 $oldstatus = safe_field("Status", 'textpattern', "ID = $r"); 336 337 if (($oldstatus == 4 || $oldstatus == 5) && !has_privs('article.edit.published', $this->txp_user)) { 338 return false; 339 } 340 341 // If they can, let's go. 342 return $this->_setArticle($params, $article_id); 343 } elseif ($this->loggedin && has_privs('article.edit', $this->txp_user)) { 344 // Admin editing. Desires are behest. 345 return $this->_setArticle($params, $article_id); 346 } 347 348 return false; 349 } 350 351 /** 352 * Creates a new article. 353 * 354 * @param array $params The article fields 355 * @return int|bool Article ID, or FALSE on failure 356 * @example 357 * $wrapper = new TXP_wrapper('username', 'password'); 358 * if (($id = $wrapper->newArticle(array( 359 * 'Title' => 'My article', 360 * 'Body' => 'My body text', 361 * )) !== false) 362 * { 363 * echo "Created a new article with the ID of '{$id}'."; 364 * } 365 */ 366 367 public function newArticle($params) 368 { 369 if ($this->loggedin && has_privs('article', $this->txp_user)) { 370 if (($params['Status'] == 4 || $params['Status'] == 5) && !has_privs('article.publish', $this->txp_user)) { 371 $params['Status'] = 3; 372 } 373 374 return $this->_setArticle($params); 375 } 376 377 return false; 378 } 379 380 /** 381 * Gets a list of sections as an assocative array. 382 * 383 * This method requires authentication and 'article' privileges. 384 * 385 * @return array|bool FALSE on failure 386 * @example 387 * $wrapper = new TXP_wrapper('username', 'password'); 388 * if ($sections = $wrapper->getSectionsList()) 389 * { 390 * foreach($sections as $section) 391 * { 392 * echo $section['title']; 393 * } 394 * } 395 */ 396 397 public function getSectionsList() 398 { 399 if ($this->loggedin && has_privs('article', $this->txp_user)) { 400 return safe_rows("*", 'txp_section', "name != 'default'"); 401 } 402 403 return false; 404 } 405 406 /** 407 * Gets a section as an assocative array. 408 * 409 * This method requires authentication and 'article' privileges. 410 * 411 * @param string $name The section name 412 * @return array|bool FALSE on failure 413 * @example 414 * $wrapper = new TXP_wrapper('username', 'password'); 415 * if ($section = $wrapper->getSection('my-section')) 416 * { 417 * echo $section['title']; 418 * } 419 */ 420 421 public function getSection($name) 422 { 423 if ($this->loggedin && has_privs('article', $this->txp_user)) { 424 $name = doSlash($name); 425 426 return safe_row("*", 'txp_section', "name = '$name'"); 427 } 428 429 return false; 430 } 431 432 /** 433 * Gets a list of categories as an assocative array. 434 * 435 * This method requires authentication and 'article' privileges. 436 * 437 * @return array|bool FALSE on failure 438 * @example 439 * $wrapper = new TXP_wrapper('username', 'password'); 440 * if ($categories = $wrapper->getCategoryList()) 441 * { 442 * foreach($categories as $category) 443 * { 444 * echo $category['title']; 445 * } 446 * } 447 */ 448 449 public function getCategoryList() 450 { 451 if ($this->loggedin && has_privs('article', $this->txp_user)) { 452 return safe_rows("*", 'txp_category', "name != 'root' AND type = 'article'"); 453 } 454 455 return false; 456 } 457 458 /** 459 * Gets a category as an assocative array. 460 * 461 * This method requires authentication and 'article' privileges. 462 * 463 * @param string $name The category name 464 * @return array|bool FALSE on failure 465 * @example 466 * $wrapper = new TXP_wrapper('username', 'password'); 467 * if ($category = $wrapper->getCategory('my-category')) 468 * { 469 * echo $category['title']; 470 * } 471 */ 472 473 public function getCategory($name) 474 { 475 if ($this->loggedin && has_privs('article', $this->txp_user)) { 476 $name = doSlash($name); 477 478 return safe_row("*", 'txp_category', "name = '$name' AND type = 'article'"); 479 } 480 481 return false; 482 } 483 484 /** 485 * Gets a category as an assocative array by ID. 486 * 487 * This method is an alternative to TXP_wrapper::getCategory(). 488 * 489 * This method requires authentication and 'article' privileges. 490 * 491 * @param string $id The category ID 492 * @return array|bool FALSE on failure 493 */ 494 495 public function getCategoryID($id) 496 { 497 if ($this->loggedin && has_privs('article', $this->txp_user)) { 498 $id = assert_int($id); 499 500 return safe_row("*", 'txp_category', "id = $id"); 501 } 502 503 return false; 504 } 505 506 /** 507 * Gets a category as an assocative array by title. 508 * 509 * This method is an alternative to TXP_wrapper::getCategory(). 510 * 511 * This method requires authentication and 'article' privileges. 512 * 513 * @param string $title The category title 514 * @return array|bool FALSE on failure 515 */ 516 517 public function getCategoryTitle($title) 518 { 519 if ($this->loggedin && has_privs('article', $this->txp_user)) { 520 $title = doSlash($title); 521 522 return safe_row("*", 'txp_category', "title = '$title' AND type = 'article'"); 523 } 524 525 return false; 526 } 527 528 /** 529 * Gets an array of information about the current user. 530 * 531 * This method requires authentication. Resulting array contains all columns 532 * from 'txp_users' database table. 533 * 534 * @return array|bool FALSE on failure 535 * @example 536 * $wrapper = new TXP_wrapper('username', 'password'); 537 * if ($user = $wrapper->getUser()) 538 * { 539 * echo $user['RealName'] . ' ' . $user['email']; 540 * } 541 */ 542 543 public function getUser() 544 { 545 if ($this->loggedin) { 546 return safe_row("*", 'txp_users', "name = '".$this->txp_user."'"); 547 } 548 549 return false; 550 } 551 552 /** 553 * Retrieves a page template contents with the given name. 554 * 555 * This method requires authentication and 'page' privileges. 556 * 557 * @param string $name The template 558 * @return string|bool The template, or FALSE on failure 559 */ 560 561 public function getTemplate($name) 562 { 563 if ($this->loggedin && has_privs('page', $this->txp_user)) { 564 $name = doSlash($name); 565 566 return safe_field("user_html", 'txp_page', "name = '$name'"); 567 } 568 569 return false; 570 } 571 572 /** 573 * Updates a page template with the given name. 574 * 575 * This method requires authentication and 'page' privileges. 576 * 577 * @param string $name The template name 578 * @param string $html The template contents 579 * @return bool TRUE on success 580 * @example 581 * $wrapper = new TXP_wrapper('username', 'password'); 582 * if ($wrapper->setTemplate('default', '<txp:site_name />')) 583 * { 584 * echo "Page template updated."; 585 * } 586 */ 587 588 public function setTemplate($name, $html) 589 { 590 if ($this->loggedin && has_privs('page', $this->txp_user)) { 591 $name = doSlash($name); 592 $html = doSlash($html); 593 594 return safe_update('txp_page', "user_html = '$html'", "name = '$name'"); 595 } 596 597 return false; 598 } 599 600 /** 601 * Intended for updating an article's non-content fields, like categories, 602 * sections or keywords. 603 * 604 * This method requires authentication and 'article.edit' privileges. 605 * 606 * @param int $article_id The article 607 * @param string $field The field to update 608 * @param mixed $value The new value 609 * @return bool TRUE on success 610 * @see TXP_wrapper::updateArticleID() 611 * @example 612 * $wrapper = new TXP_wrapper('username', 'password'); 613 * if ($wrapper->updateArticleField(11, 'Section', 'new-section')) 614 * { 615 * echo "Section updated."; 616 * } 617 */ 618 619 public function updateArticleField($article_id, $field, $value) 620 { 621 $disallow = array( 622 'Body', 623 'Body_html', 624 'Title', 625 'Title_html', 626 'Excerpt', 627 'Excerpt_html', 628 'textile_excerpt', 629 'textile_body', 630 'LastMod', 631 'LastModID', 632 'feed_time', 633 'uid', 634 ); 635 636 if ($this->loggedin && has_privs('article.edit', $this->txp_user) && !in_array(doSlash($field), $disallow)) { 637 $field = doSlash($field); 638 $value = doSlash($value); 639 640 if ($field == 'Posted') { 641 $value = strtotime($value) - tz_offset(); 642 $value = "FROM_UNIXTIME($value)"; 643 $sql = "Posted = $value"; 644 } elseif ($field == 'Status') { 645 $value = assert_int($value); 646 if (!has_privs('article.publish', $this->txp_user) && $value >= 4) { 647 $value = 3; 648 } 649 $sql = "Status = $value"; 650 } else { 651 $sql = "$field = '$value'"; 652 } 653 654 $sql .= ", LastMod = NOW(), LastModID = '".$this->txp_user."'"; 655 $article_id = assert_int($article_id); 656 $rs = safe_update('textpattern', $sql, "ID = $article_id"); 657 658 return $rs; 659 } 660 661 return false; 662 } 663 664 /** 665 * Creates and updates articles. 666 * 667 * @param array $incoming The article fields 668 * @param int $article_id The ID of the article to update 669 * @return int|bool The article ID on success, or FALSE on failure 670 * @access private 671 * @see TXP_wrapper::udpateArticleId() 672 * @see TXP_wrapper::newArticle() 673 */ 674 675 public function _setArticle($incoming, $article_id = null) 676 { 677 global $txpcfg; 678 679 $prefs = get_prefs(); 680 681 extract($prefs); 682 683 if (!empty($incoming['Section']) && !$this->getSection($incoming['Section'])) { 684 return false; 685 } 686 687 if (!empty($incoming['Category1']) && !$this->getCategory($incoming['Category1'])) { 688 return false; 689 } 690 691 if (!empty($incoming['Category2']) && !$this->getCategory($incoming['Category2'])) { 692 return false; 693 } 694 695 if ($article_id !== null) { 696 $article_id = assert_int($article_id); 697 } 698 699 // All validation rules assumed to be passed before this point. 700 // Do content processing here. 701 702 $incoming_with_markup = $this->textile_main_fields($incoming, $use_textile); 703 704 $incoming['Title'] = $incoming_with_markup['Title']; 705 706 if (empty($incoming['Body_html']) && !empty($incoming['Body'])) { 707 $incoming['Body_html'] = $incoming_with_markup['Body_html']; 708 } 709 710 if (empty($incoming['Excerpt_html']) && !empty($incoming['Excerpt'])) { 711 $incoming['Excerpt_html'] = $incoming_with_markup['Excerpt_html']; 712 } 713 714 unset($incoming_with_markup); 715 716 if (empty($incoming['Posted'])) { 717 if ($article_id === null) { 718 $when = (!$article_id) ? 'NOW()' : ''; 719 $incoming['Posted'] = $when; 720 } else { 721 // Do not override post time for existing articles unless Posted 722 // is present. 723 unset($incoming['Posted']); 724 } 725 } else { 726 $when = strtotime($incoming['Posted']) - tz_offset(); 727 $when = "FROM_UNIXTIME($when)"; 728 } 729 730 if ($incoming['Title'] || $incoming['Body'] || $incoming['Excerpt']) { 731 // Build SQL then and run query. 732 // Prevent data erase if not defined on the update action but it 733 // was on the database from a previous creation/edition time. 734 if ($article_id) { 735 $old = safe_row("*", 'textpattern', "ID = $article_id"); 736 737 if (!has_privs('article.publish', $this->txp_user) && $incoming['Status'] == 4 && $old['Status'] != 4) { 738 $incoming['Status'] = 3; 739 } 740 741 foreach ($old as $key => $val) { 742 if (!isset($incoming[$key])) { 743 $incoming[$key] = $val; 744 } 745 } 746 } else { 747 if (!has_privs('article.publish', $this->txp_user) && $incoming['Status'] == 4) { 748 $incoming['Status'] = 3; 749 } 750 } 751 752 if (empty($incoming['Section']) && $article_id) { 753 $incoming['Section'] = safe_field("Section", 'textpattern', "ID = $article_id"); 754 } 755 756 $incoming = $this->_check_keys($incoming, array( 757 'AuthorID' => $this->txp_user, 758 'Annotate' => $comments_on_default, 759 'AnnotateInvite' => $comments_default_invite, 760 'textile_body' => $use_textile, 761 'textile_excerpt' => $use_textile, 762 'url_title' => stripSpace($incoming['Title']), 763 )); 764 765 // Build the SQL query. 766 $sql = array(); 767 768 foreach ($incoming as $key => $val) { 769 if ($key == 'Posted' && $val == 'NOW()') { 770 $sql[] = "$key = $val"; 771 } elseif ($key != 'ID' && $key != 'uid' && $key != 'feed_time' && $key != 'LastMod' && $key != 'LastModID') { 772 $sql[] = "$key = '".doSlash($val)."'"; 773 } 774 } 775 776 $sql[] = "LastMod = NOW()"; 777 $sql[] = "LastModID = '".doSlash($this->txp_user)."'"; 778 779 if (!$article_id) { 780 $sql[] = "uid = '".doSlash(md5(uniqid(rand(), true)))."'"; 781 } 782 783 if (!$article_id) { 784 if (empty($incoming['Posted'])) { 785 $sql[] = "feed_time = CURDATE()"; 786 } else { 787 $when = strtotime($incoming['Posted']) - tz_offset(); 788 $when = strftime("%Y-%m-%d", $when); 789 $sql[] = "feed_time = '".doSlash($when)."'"; 790 } 791 } 792 793 $sql = join(', ', $sql); 794 795 $rs = ($article_id) ? safe_update('textpattern', $sql, "ID = $article_id") : safe_insert('textpattern', $sql); 796 797 $oldstatus = ($article_id) ? $old['Status'] : ''; 798 799 if (!$article_id && $rs) { 800 $article_id = $rs; 801 } 802 803 if (($incoming['Status'] >= 4 && !$article_id) || ($oldstatus != 4 && $article_id)) { 804 safe_update('txp_prefs', "val = NOW()", "name = 'lastmod'"); 805 //@$this->_sendPings(); 806 } 807 808 return $article_id; 809 } 810 811 return false; 812 } 813 814 /** 815 * Validates the given user credentials. 816 * 817 * @param string $user The username 818 * @param string $password The password 819 * @return bool TRUE on success 820 * @access private 821 */ 822 823 public function _validate($user, $password = null) 824 { 825 if ($password !== null) { 826 $r = txp_validate($user, $password); 827 } else { 828 $r = true; 829 } 830 831 if ($r) { 832 // Update the last access time. 833 $safe_user = addslashes($user); 834 safe_update('txp_users', "last_access = NOW()", "name = '$safe_user'"); 835 836 return true; 837 } 838 839 return false; 840 } 841 842 /** 843 * Pings Ping-O-Matic when an article is published. 844 * 845 * This is duplicated code from txp_article.php. 846 * 847 * @access private 848 */ 849 850 public function _sendPings() 851 { 852 global $prefs, $txpcfg; 853 extract($prefs); 854 855 include_once txpath.'/lib/IXRClass.php'; 856 857 if ($ping_weblogsdotcom == 1) { 858 $wl_client = new IXR_Client('http://rpc.pingomatic.com/'); 859 $wl_client->query('weblogUpdates.ping', $sitename, hu); 860 } 861 } 862 863 /** 864 * Validates and filters the given article fields. 865 * 866 * Checks if the given parameters are appropriate for the article. 867 * 868 * @param array $incoming The incoming associative array 869 * @param array $default An associative array containing default values for the desired keys 870 * @return array Filtered data array 871 * @access private 872 */ 873 874 public function _check_keys($incoming, $default = array()) 875 { 876 $out = array(); 877 878 // Strip off unsuited keys. 879 foreach ($incoming as $key => $val) { 880 if (in_array($key, $this->vars)) { 881 $out[$key] = $val; 882 } 883 } 884 885 foreach ($this->vars as $def_key) { 886 // Add those ones inexistent in the incoming array. 887 if (!array_key_exists($def_key, $out)) { 888 $out[$def_key] = ''; 889 } 890 891 // Setup the provided default value, if any, only when the incoming 892 // value is empty. 893 if (array_key_exists($def_key, $default) && empty($out[$def_key])) { 894 $out[$def_key] = $default[$def_key]; 895 } 896 } 897 898 return $out; 899 } 900 901 /** 902 * Apply Textile to the main article fields. 903 * 904 * This is duplicated from txp_article.php. 905 * 906 * @param array $incoming The incoming fields 907 * @param bool $use_textile Use Textile or not 908 * @return array The $incoming array formatted 909 * @access private 910 */ 911 912 public function textile_main_fields($incoming, $use_textile = 1) 913 { 914 global $txpcfg; 915 916 $textile = new \Textpattern\Textile\Parser(); 917 918 if (!empty($event) and $event == 'article') { 919 $incoming['Title_plain'] = $incoming['Title']; 920 } 921 922 if ($incoming['textile_body'] == USE_TEXTILE) { 923 $incoming['Title'] = $textile->textileThis($incoming['Title'], '', 1); 924 } 925 926 $incoming['url_title'] = preg_replace('|[\x00-\x1f#%+/?\x7f]|', '', $incoming['url_title']); 927 $incoming['Body_html'] = TXP_Wrapper::format_field($incoming['Body'], $incoming['textile_body'], $textile); 928 $incoming['Excerpt_html'] = TXP_Wrapper::format_field($incoming['Excerpt'], $incoming['textile_excerpt'], $textile); 929 930 return $incoming; 931 } 932 933 /** 934 * Formats a article field according to the given options. 935 * 936 * @param string $field The field contents 937 * @param int $format Either LEAVE_TEXT_UNTOUCHED, CONVERT_LINEBREAKS, USE_TEXTILE 938 * @param Textile An instance of Textile 939 * @return string HTML formatted field 940 * @access private 941 */ 942 943 public function format_field($field, $format, $textile) 944 { 945 switch ($format) { 946 case LEAVE_TEXT_UNTOUCHED: 947 $html = trim($field); 948 break; 949 case CONVERT_LINEBREAKS: 950 $html = nl2br(trim($field)); 951 break; 952 case USE_TEXTILE: 953 $html = $textile->textileThis($field); 954 break; 955 } 956 957 return $html; 958 } 959 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title