Textpattern | PHP Cross Reference | Content Management Systems |
Description: Import Textpattern XML
1 <?php 2 3 /* 4 * Textpattern Content Management System 5 * https://textpattern.com/ 6 * 7 * Copyright (C) 2020 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 <https://www.gnu.org/licenses/>. 22 */ 23 24 /** 25 * Import Textpattern XML 26 * 27 * @since 4.7.0 28 * @package Import 29 */ 30 31 namespace Textpattern\Import; 32 33 class TxpXML 34 { 35 /** 36 * Default allow import all data types. 37 * 38 * @var array 39 */ 40 41 protected $importAllow = array('articles', 'category', 'section', 'link', 'skin', 'css', 'form', 'page'); 42 43 /** 44 * articleOptionalFields 45 * 46 * @var array 47 */ 48 49 protected $articleOptionalFields = array('status', 'keywords', 'description', 'annotate', 'annotateinvite', 50 'custom_1', 'custom_2', 'custom_3', 'custom_4', 'custom_5', 'custom_6', 'custom_7', 'custom_8', 'custom_9', 'custom_10'); 51 52 /** 53 * Constructor. 54 * 55 * @param string 56 */ 57 58 public function __construct($importAllow = '') 59 { 60 $this->setImportAllow($importAllow); 61 } 62 63 /** 64 * setImportAllow 65 * 66 * @param string 67 */ 68 69 public function setImportAllow($importAllow) 70 { 71 if (!empty($importAllow)) { 72 $this->importAllow = do_list($importAllow); 73 } 74 } 75 76 /** 77 * setArticleOptionalFields 78 * 79 * @param string 80 */ 81 82 public function setArticleOptionalFields($articleOptionalFields) 83 { 84 if (!empty($articleOptionalFields)) { 85 $this->articleOptionalFields = do_list($articleOptionalFields); 86 } 87 } 88 89 /** 90 * importXml 91 * 92 * Allowed a mix of different data types in one xml file. 93 * Import articles after the creation of all categories and sections. 94 */ 95 96 public function importXml($data, $importAllow = '') 97 { 98 $importAllow = empty($importAllow) ? $this->importAllow : do_list($importAllow); 99 100 $oldLoader = libxml_disable_entity_loader(true); 101 102 if ($xml = simplexml_load_string($data, "SimpleXMLElement", LIBXML_NOCDATA)) { 103 $articles = array(); 104 foreach ((array)$xml->children() as $key => $children) { 105 if (! in_array($key, $importAllow)) { 106 continue; 107 } 108 109 if ($key == 'articles') { 110 $articles[] = $children; 111 continue; 112 } 113 114 // Permit data to be imported into plugin tables. 115 $keyPrefix = preg_match('/^[a-z]{3,3}\_/', $key) ? '' : 'txp_'; 116 117 foreach ($children->item as $item) { 118 safe_insert($keyPrefix.$key, $this->makeSqlSet($item)); 119 } 120 } 121 foreach ($articles as $a) { 122 $this->importXmlArticles($a); 123 } 124 } else { 125 // error XML 126 } 127 128 libxml_disable_entity_loader($oldLoader); 129 } 130 131 /** 132 * importXmlArticles 133 */ 134 135 private function importXmlArticles($xml) 136 { 137 global $prefs, $txp_user; 138 139 $textile = new \Netcarver\Textile\Parser('html5'); 140 141 foreach ($xml->article as $a) { 142 $article = array(); 143 $article['status'] = STATUS_LIVE; 144 $article['annotate'] = 1; 145 $article['annotateinvite'] = $prefs['comments_default_invite']; 146 147 foreach ($this->articleOptionalFields as $field) { 148 if (!empty($a->$field)) { 149 $article[$field] = $a->$field; 150 } 151 } 152 153 $article['Title'] = trim($a->title); 154 $article['url_title'] = stripSpace($article['Title'], 1); 155 $article['section'] = @$a->section; 156 $article['Category1'] = @$a->category[0]; 157 $article['Category2'] = @$a->category[1]; 158 159 $article['Body'] = @trim($this->replaceUrls($a->body)); 160 $format = $a->body->attributes()->format; 161 if ($format == 'textile') { 162 $article['Body_html'] = $textile->parse($article['Body']); 163 $article['textile_body'] = 1; 164 } else { 165 $article['Body_html'] = $article['Body']; 166 $article['textile_body'] = 0; 167 } 168 169 $article['Excerpt'] = @trim($this->replaceUrls($a->excerpt)); 170 $format = $a->excerpt->attributes()->format; 171 if ($format == 'textile') { 172 $article['Excerpt_html'] = $textile->parse($article['Excerpt']); 173 $article['textile_excerpt'] = 1; 174 } else { 175 $article['Excerpt_html'] = $article['Excerpt']; 176 $article['textile_excerpt'] = 0; 177 } 178 179 $article['AuthorID'] = $txp_user; 180 $article['Posted'] = $article['LastMod'] = $article['feed_time'] = 'NOW()'; 181 $article['uid'] = md5(uniqid(rand(), true)); 182 183 $id = safe_insert('textpattern', $this->makeSqlSet($article)); 184 185 if ($id && !empty($a->comment)) { 186 foreach ($a->comment as $c) { 187 $name = empty($c->name) ? $txp_user : $c->name; 188 $email = empty($c->email) ? stripSpace($name, 1).'@example.com' : $c->email; 189 safe_insert('txp_discuss', " 190 parentid = '$id', 191 name = '".doSlash($name)."', 192 email = '".doSlash($email)."', 193 web = '".doSlash($c->web)."', 194 message = '".doSlash($c->message)."', 195 posted = NOW(), 196 visible = 1" 197 ); 198 } 199 update_comments_count($id); 200 } 201 } 202 } 203 204 /** 205 * replaceUrls 206 * Used in importXmlArticles() 207 */ 208 209 private function replaceUrls($txt) 210 { 211 global $adminurl, $siteurl; 212 213 $adminpath = preg_replace('#^[^/]+#', '', $adminurl); 214 $sitepath = preg_replace('#^[^/]+#', '', $siteurl); 215 216 $txt = str_replace('adminurl', $adminpath, $txt); 217 $txt = str_replace('siteurl', $sitepath, $txt); 218 219 return $txt; 220 } 221 222 /** 223 * Make sql set string from array 224 */ 225 226 public function makeSqlSet($array) 227 { 228 $out = array(); 229 foreach (doSlash((array)$array) as $field=>$data) { 230 if (in_array(trim($data), array('NOW()', 'NULL'), true)) { 231 $out[]="`{$field}`=".trim($data); 232 } else { 233 $out[]="`{$field}`='$data'"; 234 } 235 } 236 237 return implode(', ', $out); 238 } 239 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title