PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/CalendarArticles.php

http://mw-calendar.googlecode.com/
PHP | 714 lines | 586 code | 81 blank | 47 comment | 71 complexity | d7d33bbe47ebf44a542d1c7757c32955 MD5 | raw file
  1. <?php
  2. /*
  3. Class: CalendarArticle
  4. Purpose: Stucture to hold article/event data and
  5. then store into an array for future retrieval
  6. */
  7. require_once ("common.php");
  8. class CalendarArticle
  9. {
  10. var $day = "";
  11. var $month = "";
  12. var $year = "";
  13. var $page = ""; //full wiki page name
  14. var $eventname = ""; //1st line of body; unformated plain text
  15. var $body = ""; // everything except line 1 in the event page
  16. var $html = ""; // html link displayed in calendar
  17. var $isImage = false;
  18. function CalendarArticle($month, $day, $year){
  19. $this->month = $month;
  20. $this->day = $day;
  21. $this->year = $year;
  22. }
  23. }
  24. /*
  25. Class: CalendarArticles
  26. Purpose: Contains most of the functions to retrieve article
  27. information. It also is the primary container for
  28. the main array of class::CalendarArticle articles
  29. */
  30. class CalendarArticles
  31. {
  32. private $arrArticles = array();
  33. public $wikiRoot = "";
  34. private $arrTimeTrack = array();
  35. private $arrStyle = array();
  36. // build an event based on the 1st line or ==event== type
  37. public function addArticle($month, $day, $year, $page){
  38. $lines = array();
  39. $temp = "";
  40. $head = array();
  41. $article = new Article(Title::newFromText($page));
  42. if(!$article->exists()) return "";
  43. $redirectCount = 0;
  44. if( $article->isRedirect() && $this->setting('disableredirects') ) return '';
  45. while($article->isRedirect() && $redirectCount < 10){
  46. $redirectedArticleTitle = Title::newFromRedirect($article->getContent());
  47. $article = new Article($redirectedArticleTitle);
  48. $redirectCount += 1;
  49. }
  50. $body = $article->fetchContent(0,false,false);
  51. if(strlen(trim($body)) == 0) return "";
  52. $lines = split("\n",$body);
  53. $cntLines = count($lines);
  54. // dont use section events... only line 1 of the page
  55. if($this->setting('disablesectionevents')){
  56. $key = $lines[0]; //initalize the key
  57. $head[$key] = "";
  58. $cntLines = 0;
  59. }
  60. for($i=0; $i<$cntLines; $i++){
  61. $line = $lines[$i];
  62. if(substr($line,0,2) == '=='){
  63. $arr = split("==",$line);
  64. $key = $arr[1];
  65. $head[$key] = ""; $temp = "";
  66. }
  67. else{
  68. if($i == 0){ // $i=0 means this is a one event page no (==event==) data
  69. $key = $line; //initalize the key
  70. $head[$key] = "";
  71. }
  72. else{
  73. $temp .= "$line\n";
  74. $head[$key] = Common::cleanWiki($temp);
  75. }
  76. }
  77. }
  78. while (list($event,$body) = each($head)){
  79. $this->buildEvent($month, $day, $year, trim($event), $page, $body);
  80. }
  81. }
  82. // this is the main logic/format handler; the '$event' is checked for triggers here...
  83. public function buildEvent($month, $day, $year, $event, $page, $body, $eventType='addevent', $bRepeats=false){
  84. // user triggered yearly repeat event...
  85. if(substr($event,0,2) == '##'){
  86. $event = trim(str_replace("##", "", $event));
  87. $this->buildRecurrenceEvent($month, $day, $year, $event, $page);
  88. }
  89. //check for repeating events
  90. $arrEvent = split("#",$event);
  91. if( isset($arrEvent[1]) && ($arrEvent[0] != 0) && $this->setting('enablerepeatevents') ){
  92. for($i=0; $i<$arrEvent[0]; $i++) {
  93. $this->add($month, $day, $year, $arrEvent[1], $page, $body, false, true);
  94. Common::getNextValidDate($month, $day, $year);
  95. }
  96. }else{
  97. $this->add($month, $day, $year, $event, $page, $body, $eventType, $bRepeats);
  98. }
  99. }
  100. // this is the MAIN function that returns the events to the calendar...
  101. // there shouldn't be ANY formatting or logic done here....
  102. public function getArticleLinks($month, $day, $year){
  103. global $wgParser;
  104. $ret = $list = "";
  105. $bFound = false;
  106. // not using 'templates' array, but the purpose was to put all these events above other events...
  107. if(isset($this->arrArticles['templates'])){
  108. foreach($this->arrArticles['templates'] as $cArticle){
  109. if($cArticle->month == $month && $cArticle->day == $day && $cArticle->year == $year){
  110. $ret .= $cArticle->html;
  111. }
  112. }
  113. }
  114. // we want to format the normal 'add event' items in 1 table cell
  115. // this creates less spacing and creates a better <ul>
  116. $head = "<tr cellpadding=0 cellspacing=0 ><td class='calendarTransparent singleEvent'>";
  117. $head .= "<ul class='bullets'>";
  118. $foot = "</ul></td></tr>";
  119. if(isset($this->arrArticles['events'])){
  120. foreach($this->arrArticles['events'] as $cArticle){
  121. if($cArticle->month == $month && $cArticle->day == $day && $cArticle->year == $year){
  122. $image = Common::getImageURL($cArticle->eventname);
  123. if( $image ) {
  124. $list .= '<a href="'. $this->wikiRoot . $cArticle->page . '"><img src="' . $image . '"></a>';
  125. }
  126. else {
  127. $list .= "<li>" . $cArticle->html . "</li>";
  128. }
  129. $bFound = true;
  130. }
  131. }
  132. }
  133. if($bFound)
  134. $ret .= $head . $list . $foot;
  135. return $ret;
  136. }
  137. public function buildSimpleEvent($month, $day, $year, $event, $body, $page){
  138. $cArticle = new CalendarArticle($month, $day, $year);
  139. $temp = $this->checkTimeTrack($month, $day, $year, $event, '');
  140. $temp = trim($temp);
  141. $summaryLength = $this->setting('enablesummary',false);
  142. $html_link = $this->articleLink('', $temp, true);
  143. // format for different event types
  144. $class = "baseEvent ";
  145. //if($bRepeats) $class .= "repeatEvent ";
  146. //if($eventType == "recurrence") $class .= "recurrenceEvent ";
  147. $class = trim($class);
  148. $cArticle->month = $month;
  149. $cArticle->day = $day;
  150. $cArticle->year = $year;
  151. $cArticle->page = $page;
  152. $cArticle->eventname = $event;
  153. $cArticle->body = $body;
  154. // this will be the main link displayed in the calendar....
  155. $cArticle->html = "<span class='$class'>$html_link</span><br/>" . Common::limitText($cArticle->body, $summaryLength);
  156. $this->arrArticles['events'][] = $cArticle;
  157. }
  158. // when the calendar loads, we want to put all the template events into memory
  159. // so we dont have to read the wiki db for every day
  160. public function addTemplate($month, $year, $pagename){
  161. $displayText = "";
  162. $arrEvent = array();
  163. $articleName = $pagename . "/" . $month . "-" . $year . " -Template";
  164. $article = new Article(Title::newFromText($articleName));
  165. if (!$article->exists()) return "";
  166. $displayText = $article->fetchContent(0,false,false);
  167. $arrAllEvents=split(chr(10),$displayText);
  168. if (count($arrAllEvents) > 0){
  169. for($i=0; $i<count($arrAllEvents); $i++){
  170. $arrEvent = split("#",$arrAllEvents[$i]);
  171. if(!isset($arrEvent[1])) continue;//skip
  172. if(strlen($arrEvent[1]) > 0){
  173. $day = $arrEvent[0];
  174. $arrRepeat = split("-",$arrEvent[0]);
  175. if(count($arrRepeat) > 1){
  176. $day = $arrRepeat[0];
  177. while($day <= $arrRepeat[1]){
  178. $this->buildEvent($month, $day, $year, $arrEvent[1], $articleName, "", "templates", true);
  179. $day++;
  180. }
  181. }else{
  182. $this->buildEvent($month, $day, $year, $arrEvent[1], $articleName, "", "templates");
  183. }
  184. }
  185. }
  186. }
  187. }
  188. // this is the FINAL stop; the events are stored here then pulled out
  189. // and displayed later via "getArticleLinks()"...
  190. private function add($month, $day, $year, $eventname, $page, $body, $eventType='addevent', $bRepeats=false){
  191. // $eventType='default' -- addevent
  192. // $eventType='recurrence'
  193. // $eventType='template'
  194. global $wgParser;
  195. $cArticle = new CalendarArticle($month, $day, $year);
  196. $temp = $this->checkTimeTrack($month, $day, $year, $eventname, $eventType);
  197. $temp = trim($temp);
  198. // lets get the body char limit
  199. $summaryLength = $this->setting('enablesummary',false);
  200. $html_link = $this->articleLink($page, $temp);
  201. // format for different event types
  202. $class = "baseEvent ";
  203. if($bRepeats) $class .= "repeatEvent ";
  204. if($eventType == "recurrence") $class .= "recurrenceEvent ";
  205. $class = trim($class);
  206. $cArticle->month = $month;
  207. $cArticle->day = $day;
  208. $cArticle->year = $year;
  209. $cArticle->page = $page;
  210. $cArticle->eventname = $temp;
  211. $cArticle->body = $body;
  212. $cArticle->isImage = $eventType;
  213. // wik-a-fi the $body; however, cut off text could cause html issues... so try to
  214. // keep all required body wiki/html to the top
  215. $parsedBody = $wgParser->recursiveTagParse( Common::limitText($cArticle->body, $summaryLength) );
  216. // this will be the main link displayed in the calendar....
  217. $cArticle->html = "<span class='$class'>$html_link</span><br/>" . $parsedBody;
  218. $this->arrArticles['events'][] = $cArticle;
  219. }
  220. // this function checks a template event for a time trackable value
  221. private function checkTimeTrack($month, $day, $year, $event, $eventType){
  222. if((stripos($event,"::") === false) || $this->setting('disabletimetrack'))
  223. return $event;
  224. $arrEvent = split("::", $event);
  225. $arrType = split(":",$arrEvent[1]);
  226. if(count($arrType) == 1)
  227. $arrType = split("-",$arrEvent[1]);
  228. if(count($arrType) != 2) return $event;
  229. $type = trim(strtolower($arrType[0]));
  230. // we only want the displayed calendar year totals
  231. if($this->year == $year){
  232. if($eventType=='templates')
  233. $this->arrTimeTrack[$type.' (y)'][] = $arrType[1];
  234. else
  235. $this->arrTimeTrack[$type.' (m)'][] = $arrType[1];
  236. }
  237. //piece together any prefixes that the code may have added - like (r) for repeat events
  238. $ret = $arrType[0] . " <i>-(track)</i>";
  239. return $ret;
  240. }
  241. public function buildTrackTimeSummary(){
  242. if($this->setting('disabletimetrack')) return "";
  243. $ret = "";
  244. $cntValue = count($this->arrTimeTrack);
  245. if($cntValue == 0) return "";
  246. $cntHead = split(",", $this->setting('timetrackhead',false));
  247. $linktitle = "Time summaries of time specific enties. Prefix events with :: to track time values.";
  248. $html_head = "<hr><table title='$linktitle' width=15% border=1 cellpadding=0 cellspacing=0><th>$cntHead[0]</th><th>$cntHead[1]</th>";
  249. $html_foot = "</table><small>"
  250. . "(m) - total month only; doesn't add to year total <br/>"
  251. . "(y) - total year; must use monthly templates<br/></small><br>";
  252. while (list($key,$val) = each($this->arrTimeTrack)) {
  253. $ret .= "<tr><td align='center'>$key</td><td align='center'>" . array_sum($this->arrTimeTrack[$key]) . "</td></tr>";
  254. }
  255. return $html_head . $ret . $html_foot;
  256. }
  257. //find the number of current events and "build" the <add event> link
  258. public function buildAddEventLink($month, $day, $year, $text="") {
  259. if($day < 1) return "";
  260. $section_new = '';
  261. if($this->setting('disableaddevent') && strlen($text) == 0) return "";
  262. if($this->setting('disableaddevent') && strlen($text) > 0) return $day;
  263. $articleName = ""; // the name of the article to check for
  264. $articleCount = 1; // the article count
  265. if($text == "")
  266. $text = "<u>" . Common::translate("add_event") . "</u>";
  267. $tip = Common::translate('add_event_tip');
  268. if($this->setting('weekofyear')){
  269. $tip .= " (wk:" . $this->getWeekOfTheYear($month,$day,$year,true) . ")";
  270. }
  271. //$date = "$month-$day-$year";
  272. $date = $this->userDateFormat($month, $day, $year);
  273. $articleName = $this->getNextAvailableArticle($this->calendarPageName, $date);
  274. // if we're using multi-event mode, then default to section=new
  275. if( $this->setting('usesectionevents') )
  276. $section_new = "&section=new";
  277. $newURL = "<a title='$tip' href='" . $this->wikiRoot . wfUrlencode($articleName) . "&action=edit$section_new'>$text</a>";
  278. return $newURL;
  279. }
  280. public function getNextAvailableArticle($page, $date, $event_zero=false){
  281. $stop = false;
  282. $page = "$page/$date -Event ";
  283. $articleCount = 1;
  284. // for ical option and setting all icals to Event -0 (== event ==) style
  285. if($event_zero)
  286. return $page . "0";
  287. $max_articles = $this->setting('maxdailyevents',false);
  288. // bump up the max for iCal imports...but not to much in case of a runaway
  289. // we also want to ignore the inforced 'usesectionevents'..however, the
  290. // calendar will still only display the 'maxdailyevents' value
  291. if($this->setting('ical')){
  292. $max_articles += 5;
  293. }
  294. else{
  295. if($this->setting('usesectionevents') && !$this->setting('ical'))
  296. return $page . $articleCount;
  297. }
  298. $article = new Article(Title::newFromText($page . $articleCount));
  299. // dont care about the articles here, just need to get next available article
  300. while ($article->exists() && !$stop) {
  301. $displayText = $article->fetchContent(0,false,false);
  302. if(strlen($displayText) > 0){
  303. $articleCount++;
  304. $article = new Article(Title::newFromText($page . $articleCount));
  305. if($articleCount == $max_articles)
  306. $stop = true;
  307. }
  308. else $stop = true;
  309. }
  310. return $page . $articleCount;
  311. }
  312. function readStylepage(){
  313. $articleName = $this->calendarPageName . "/" . "style";
  314. $article = new Article(Title::newFromText($articleName));
  315. if ($article->exists()){
  316. $displayText = $article->fetchContent(0,false,false);
  317. $this->arrStyle = split(chr(10), $displayText);
  318. }
  319. }
  320. public function getConfig($pagename){
  321. $params = array();
  322. $articleName = "$pagename/config";
  323. $article = new Article(Title::newFromText($articleName));
  324. if ($article->exists()){
  325. $body = $article->fetchContent(0,false,false);
  326. $body = str_replace("\"", "", $body);
  327. $arr = split("\n", $body);
  328. $cnt = count($arr);
  329. for($i=0; $i<$cnt; $i++){
  330. $arrParams = split("=", $arr[$i]);
  331. $key = trim($arrParams[0]);
  332. if($key != 'useconfigpage'){ // we dont want users to lock themselves out of the config page....
  333. if(count($arrParams) == 2)
  334. $params[$key] = trim($arrParams[1]); // we have both $key and $value
  335. else
  336. $params[$key] = $key; // init the value with itself if $value is null
  337. }
  338. }
  339. }
  340. return $params;
  341. }
  342. // returns the link for an article, along with summary in the title tag, given a name
  343. private function articleLink($title, $text, $noLink=false){
  344. global $wgParser;
  345. if(strlen($text)==0) return "";
  346. //$text = $wgParser->recursiveTagParse( $text );
  347. $arrText = $this->buildTextAndHTMLString($text);
  348. $style = $arrText[2];
  349. //locked links
  350. if($this->setting('disablelinks') || $noLink)
  351. $ret = "<span $style>" . $arrText[1] . "</span>";
  352. else
  353. if($this->setting('defaultedit'))
  354. $ret = "<a $style title='$arrText[0]' href='" . $this->wikiRoot . wfUrlencode($title) . "&action=edit'>$arrText[1]</a>";
  355. else
  356. $ret = "<a $style title='$arrText[0]' href='" . $this->wikiRoot . wfUrlencode($title) . "'>$arrText[1]</a>";
  357. return $ret;
  358. }
  359. private function buildTextAndHTMLString($string){
  360. $string = Common::cleanWiki($string);
  361. $htmltext = $string;
  362. $plaintext = strip_tags($string);
  363. $charlimit = $this->setting('charlimit',false);
  364. if(strlen($plaintext) > $charlimit) {
  365. $temp = substr($plaintext,0,$charlimit) . "..."; //plaintext
  366. $ret[0] = $plaintext; //full plain text
  367. $ret[1] = str_replace($plaintext, $temp, $htmltext); //html
  368. $ret[2] = ""; //styles
  369. }
  370. else{
  371. $ret[0] = $plaintext; //full plain text
  372. $ret[1] = $htmltext;
  373. $ret[2] = ""; //styles
  374. }
  375. if(!$this->setting('disablestyles'))
  376. $ret[2] = $this->buildStyleBySearch($plaintext);
  377. return $ret;
  378. }
  379. private function buildStyleBySearch($text){
  380. $stylePage = '';
  381. // set default style if available, if not... use std windows defaults
  382. $defaultStyle = $this->setting('style', false);
  383. for($i=0; $i < count($this->arrStyle); $i++){
  384. $arr = split("::", $this->arrStyle[$i]);
  385. $cnt = count($arr);
  386. if(stripos($text, $arr[0]) !== false) {
  387. $stylePage = trim($arr[1]);
  388. }
  389. }
  390. //return "style='" . str_replace("'", "", "$defaultStyle;$stylePage") . "' ";
  391. return "style='$defaultStyle;$stylePage' ";
  392. }
  393. // creates a new page and populates it as required
  394. function createNewPage($page, $event, $description, $summary){
  395. $article = new Article(Title::newFromText($page));
  396. $event = $event . "\n\n" . $description;
  397. $article->doEdit($event, EDIT_NEW);
  398. }
  399. function createNewMultiPage($page, $event, $description, $summary, $overwrite=false){
  400. $article = new Article(Title::newFromText($page));
  401. $bExists = $article->exists();
  402. $event = "==$event==\n\n" . $description;
  403. if($bExists){
  404. if($overwrite){
  405. $article->doEdit($body.$event, $summary, EDIT_UPDATE);
  406. }
  407. else{
  408. $body = trim($article->fetchContent(0,false,false));
  409. if(strlen($body) > 0) $body = "$body\n\n";
  410. $article->doEdit($body.$event, $summary, EDIT_UPDATE);
  411. }
  412. }
  413. else{
  414. $article->doEdit($event, $summary, EDIT_NEW);
  415. }
  416. }
  417. private function buildRecurrenceEvent($month, $day, $year, $event, $page){
  418. $this->debug->set('buildRecurrenceEvent started');
  419. $recurrence_page = "$this->calendarPageName/recurrence";
  420. $article = new Article(Title::newFromText($page));
  421. $bExists = $article->exists();
  422. if($bExists){
  423. $article->doEdit('', 'recurrence event moved...', EDIT_UPDATE);
  424. unset($article);
  425. }
  426. $rrule = "RRULE:FREQ=YEARLY;INTERVAL=1"
  427. . ";BYMONTH=$month"
  428. . ";DAY=$day"
  429. . ";SUMMARY=$event";
  430. $this->updateRecurrence($recurrence_page, $rrule, $event, 'recurrence update');
  431. $this->invalidateCache = true;
  432. }
  433. function updateRecurrence($page, $rrule, $event, $summary, $overwrite=false){
  434. $article = new Article(Title::newFromText($page));
  435. $bExists = $article->exists();
  436. $ret = 0;
  437. $rrule = trim($rrule);
  438. if($bExists){
  439. if($overwrite){
  440. $article->doEdit("$rrule", $summary, EDIT_UPDATE);
  441. $ret = 1;
  442. }
  443. else{
  444. $body = trim($article->fetchContent(0,false,false));
  445. if((stripos($body, $rrule) === false)){ // lets not re-add duplicate rrule lines
  446. $article->doEdit("$body\n" . "$rrule", $summary, EDIT_UPDATE);
  447. $ret = 1;
  448. }
  449. }
  450. }
  451. else{
  452. $article->doEdit("$event", $summary, EDIT_NEW);
  453. $ret = 1;
  454. }
  455. return $ret;
  456. }
  457. // RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYDAY=2MO;MONTH=10;DAY=14;SUMMARY=Columbus Day
  458. public function addVCalEvents($page, $year, $month){
  459. $arrRRULES = array();
  460. $ical_short_day = array("SU"=>0,"MO"=>1,"TU"=>2,"WE"=>3,"TH"=>4,"FR"=>5,"SA"=>6);
  461. $articleName = "$page/recurrence";
  462. $article = new Article(Title::newFromText($articleName));
  463. $bExists = $article->exists();
  464. if($bExists){
  465. $body = trim($article->fetchContent(0,false,false));
  466. $arrRRULES = $this->convertRRULEs($body);
  467. } else return;
  468. foreach($arrRRULES as $rules){
  469. $bExpired = false;
  470. if(isset($rules['UNTIL'])){
  471. $bExpired = $this->checkExpiredRRULE($rules['UNTIL']);
  472. }
  473. if($bExpired) continue; // skip the rest of the current loop iteration
  474. if($rules['FREQ'] == 'YEARLY' && !isset($rules['BYDAY']) && $rules['BYMONTH'] == $month){ //std sameday recurrence
  475. $this->buildEvent($month, $rules['DAY'], $year, $rules['SUMMARY'], $articleName, "", 'recurrence');
  476. }
  477. else if ($rules['FREQ'] == 'YEARLY' && isset($rules['BYDAY']) && $rules['BYMONTH'] == $month){
  478. $num = $rules['BYDAY'];
  479. // parse the ical format for BYDAY (1MO, 4TH, 2WE, etc)
  480. settype($num, 'integer'); //get the numeric value of BYDAY
  481. $ical_weekday = str_replace($num, "", $rules['BYDAY']); //get the weekday text value of BYDAY
  482. $day = $ical_short_day[$ical_weekday]; // take the text and get the 0-6 numeric value (SU=0, MO=1, etc)
  483. $wday_info = Common::wdayOffset($month,$year,$day);
  484. $offset = $wday_info['offset'];
  485. // if we have something like -1SU; then handle it here...
  486. if($num < 0)
  487. $num = ($wday_info['weeks'] +1) + $num;
  488. // kick back the week count if needed
  489. if($offset > 0 && $num != 0) $num--;
  490. $theday = $offset + (7 * $num);
  491. $this->buildEvent($month, $theday, $year, $rules['SUMMARY'], $articleName, "", 'recurrence');
  492. }
  493. }
  494. unset($rules);
  495. }
  496. // filter out RRULE-'UNTIL' expired events
  497. function checkExpiredRRULE($date){
  498. $bRet = false;
  499. $expire_year = substr($date,0,4);
  500. $expire_month = substr($date,4,2);
  501. if($this->year > $expire_year){
  502. $bRet = true;
  503. }
  504. else if($this->year == $expire_year){
  505. if($this->month > $expire_month){
  506. $bRet = true;
  507. }
  508. }
  509. return $bRet;
  510. }
  511. // converts an RRULE line into an easy to use 2d-array
  512. function convertRRULEs($rrules){
  513. $arr_rrules = split("RRULE:", $rrules);
  514. $events = array();
  515. array_shift($arr_rrules); //1st array[0] is garbage because RRULE: in position 0(1st)
  516. foreach($arr_rrules as $rule){
  517. $arr_properties = split(";", $rule);
  518. foreach($arr_properties as $property){
  519. $arr_rule = split("=", $property);
  520. $rules[$arr_rule[0]] = $arr_rule[1]; //key and value
  521. }
  522. if(isset($rules['FREQ'])) //make sure we add valid rows
  523. $events[] = $rules;
  524. unset($rules); //clear array
  525. }
  526. return $events;
  527. }
  528. // any custom MW tags or code can be filtered out here...
  529. // this is only for calendar event display and doesn't edit the article itself
  530. private function cleanEventData($content){
  531. $ret = $content;
  532. // remove [[xyz]] type strings...
  533. $ret = preg_replace('[(\[\[)+.+(\]\])]', '', $ret);
  534. // remove __xyz__ type strings...
  535. $ret = preg_replace('[(__)+.+(__)]', '', $ret);
  536. // remove {{xyz}} type strings...
  537. $ret = preg_replace('[({{)+.+(}})]', '', $ret);
  538. return $ret;
  539. }
  540. /*
  541. public function chkConfigToolPage($configToolPage){
  542. $article = new Article(Title::newFromText($configToolPage));
  543. if(!$article->exists())
  544. $article->doEdit("<config/>", "", EDIT_NEW);
  545. elseif(trim($article->fetchContent()) == "")
  546. $article->doEdit("<config/>", "", EDIT_UPDATE);
  547. }
  548. */
  549. }