4 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
\r
5 * Copyright (C) 2002-2012 The Nucleus Group
\r
7 * This program is free software; you can redistribute it and/or
\r
8 * modify it under the terms of the GNU General Public License
\r
9 * as published by the Free Software Foundation; either version 2
\r
10 * of the License, or (at your option) any later version.
\r
11 * (see nucleus/documentation/index.html#license for more info)
\r
14 * This class contains two classes that can be used for importing and
\r
15 * exporting Nucleus skins: SKINIMPORT and SKINEXPORT
\r
17 * @license http://nucleuscms.org/license.txt GNU General Public License
\r
18 * @copyright Copyright (C) 2002-2012 The Nucleus Group
\r
19 * @version $Id: skinie.php 1624 2012-01-09 11:36:20Z sakamocchi $
\r
24 // hardcoded value (see constructor). When 1, interesting info about the
\r
25 // parsing process is sent to the output
\r
28 // parser/file pointer
\r
32 // parset internal charset, US-ASCII/ISO-8859-1/UTF-8
\r
33 private $parse_charset = 'UTF-8';
\r
35 // which data has been read?
\r
36 private $metaDataRead;
\r
44 // to maintain track of where we are inside the XML file
\r
49 private $inTemplate;
\r
50 private $currentName;
\r
51 private $currentPartName;
\r
55 * constructor initializes data structures
\r
57 public function __construct()
\r
59 // disable magic_quotes_runtime if it's turned on
\r
60 //set_magic_quotes_runtime(0);
\r
61 if ( version_compare(PHP_VERSION, '5.3.0', '<') )
\r
63 ini_set('magic_quotes_runtime', '0');
\r
73 public function __destruct()
\r
78 public function reset()
\r
80 if ( $this->parser )
\r
82 xml_parser_free($this->parser);
\r
88 // which data has been read?
\r
89 $this->metaDataRead = 0;
\r
92 // to maintain track of where we are inside the XML file
\r
97 $this->inTemplate = 0;
\r
98 $this->currentName = '';
\r
99 $this->currentPartName = '';
\r
101 // character data pile
\r
104 // list of skinnames and templatenames (will be array of array)
\r
105 $this->skins = array();
\r
106 $this->templates = array();
\r
108 // extra info included in the XML files (e.g. installation notes)
\r
111 // init XML parser, this parser deal with characters as encoded by UTF-8
\r
112 $this->parser = xml_parser_create($this->parse_charset);
\r
113 xml_set_object($this->parser, $this);
\r
114 xml_set_element_handler($this->parser, 'start_element', 'end_element');
\r
115 xml_set_character_data_handler($this->parser, 'character_data');
\r
116 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
\r
122 * Reads an XML file into memory
\r
125 * Which file to read
\r
127 * Set to 1 when only the metadata needs to be read (optional, default 0)
\r
129 public function readFile($filename, $metaOnly = 0)
\r
132 $this->fp = @fopen($filename, 'r');
\r
135 return _SKINIE_ERROR_FAILEDOPEN_FILEURL;
\r
141 $tempbuffer = null;
\r
143 while ( !feof($this->fp) )
\r
145 $tempbuffer .= fread($this->fp, 4096);
\r
150 * NOTE: conver character set.
\r
151 * We hope all characters in the file also includes UTF-8 coded character set,
\r
152 * because this PHP extension implements support for James Clark's expat in PHP
\r
153 * and it supports juust US-ASCII, ISO-8859-1, UTF-8 character coding scheme.
\r
155 if ( i18n::get_current_charset() != $this->parse_charset )
\r
157 $tempbuffer = i18n::convert($tempbuffer, i18n::get_current_charset(), $this->parse_charset);
\r
161 fwrite($temp, $tempbuffer);
\r
164 while ( ($buffer = fread($temp, 4096) )
\r
165 && (!$metaOnly || ($metaOnly && !$this->metaDataRead)) )
\r
167 $err = xml_parse( $this->parser, $buffer, feof($temp) );
\r
168 if ( !$err && $this->debug )
\r
170 echo 'ERROR: ', xml_error_string(xml_get_error_code($this->parser)), '<br />';
\r
182 * Returns the list of skin names
\r
184 public function getSkinNames()
\r
186 return array_keys($this->skins);
\r
190 * Returns the list of template names
\r
192 public function getTemplateNames()
\r
194 return array_keys($this->templates);
\r
198 * Returns the extra information included in the XML file
\r
200 public function getInfo()
\r
202 return $this->info;
\r
206 * Writes the skins and templates to the database
\r
208 * @param $allowOverwrite
\r
209 * set to 1 when allowed to overwrite existing skins with the same name
\r
212 public function writeToDatabase($allowOverwrite = 0)
\r
214 $existingSkins = $this->checkSkinNameClashes();
\r
215 $existingTemplates = $this->checkTemplateNameClashes();
\r
216 $invalidSkinNames = $this->checkSkinNamesValid();
\r
217 $invalidTemplateNames = $this->checkTemplateNamesValid();
\r
219 // if there are invalid skin or template names, stop executioin and return and error
\r
220 if ( (sizeof($invalidSkinNames) > 0) || (sizeof($invalidTemplateNames) > 0) )
\r
222 $inames_error = "<p>"._SKINIE_INVALID_NAMES_DETECTED."</p>\n";
\r
223 $inames_error .= "<ul>";
\r
224 foreach( $invalidSkinNames as $sName )
\r
226 $inames_error .= "<li>".Entity::hsc($sName)."</li>";
\r
228 foreach( $invalidTemplateNames as $sName )
\r
230 $inames_error .= "<li>".Entity::hsc($sName)."</li>";
\r
232 $inames_error .= "</ul>";
\r
233 return $inames_error;
\r
236 // if not allowed to overwrite, check if any nameclashes exists
\r
237 if ( !$allowOverwrite )
\r
239 if ( (sizeof($existingSkins) > 0) || (sizeof($existingTemplates) > 0) )
\r
241 return _SKINIE_NAME_CLASHES_DETECTED;
\r
245 foreach ( $this->skins as $skinName => $data )
\r
247 // 1. if exists: delete all part data, update desc data
\r
248 // if not exists: create desc
\r
249 if ( in_array($skinName, $existingSkins) )
\r
251 $skinObj = SKIN::createFromName($skinName);
\r
253 // delete all parts of the skin
\r
254 $skinObj->deleteAllParts();
\r
256 // update general info
\r
257 $skinObj->updateGeneralInfo(
\r
259 $data['description'],
\r
261 $data['includeMode'],
\r
262 $data['includePrefix']
\r
267 $skinid = SKIN::createNew(
\r
269 $data['description'],
\r
271 $data['includeMode'],
\r
272 $data['includePrefix']
\r
274 $skinObj = new SKIN($skinid);
\r
278 foreach ( $data['parts'] as $partName => $partContent )
\r
280 $skinObj->update($partName, $partContent);
\r
284 foreach ( $this->templates as $templateName => $data )
\r
286 // 1. if exists: delete all part data, update desc data
\r
287 // if not exists: create desc
\r
288 if ( in_array($templateName, $existingTemplates) )
\r
290 $templateObj = Template::createFromName($templateName);
\r
292 // delete all parts of the template
\r
293 $templateObj->deleteAllParts();
\r
295 // update general info
\r
296 $templateObj->updateGeneralInfo($templateName, $data['description']);
\r
300 $templateid = Template::createNew($templateName, $data['description']);
\r
301 $templateObj = new Template($templateid);
\r
305 foreach ( $data['parts'] as $partName => $partContent )
\r
307 $templateObj->update($partName, $partContent);
\r
314 * returns an array of all the skin nameclashes (empty array when no name clashes)
\r
316 public function checkSkinNameClashes()
\r
318 $clashes = array();
\r
320 foreach ( $this->skins as $skinName => $data )
\r
322 if ( SKIN::exists($skinName) )
\r
324 array_push($clashes, $skinName);
\r
331 * returns an array of all the template nameclashes
\r
332 * (empty array when no name clashes)
\r
334 public function checkTemplateNameClashes()
\r
336 $clashes = array();
\r
338 foreach ( $this->templates as $templateName => $data )
\r
340 if ( Template::exists($templateName) )
\r
342 array_push($clashes, $templateName);
\r
349 * returns an array of all the invalid skin names (empty array when no invalid names )
\r
351 private function checkSkinNamesValid()
\r
353 $notValid = array();
\r
355 foreach ( $this->skins as $skinName => $data )
\r
357 if ( !isValidSkinName($skinName) )
\r
359 array_push($notValid, $skinName);
\r
366 * returns an array of all the invalid template names (empty array when no invalid names )
\r
368 private function checkTemplateNamesValid()
\r
370 $notValid = array();
\r
372 foreach ( $this->templates as $templateName => $data )
\r
374 if ( !isValidTemplateName($templateName) )
\r
376 array_push($notValid, $templateName);
\r
383 * Called by XML parser for each new start element encountered
\r
385 private function start_element($parser, $name, $attrs)
\r
387 foreach( $attrs as $key=>$value )
\r
389 if ( $this->parse_charset != i18n::get_current_charset() )
\r
391 $name = i18n::convert($name, $this->parse_charset, i18n::get_current_charset());
\r
392 $value = i18n::convert($value, $this->parse_charset, i18n::get_current_charset());
\r
395 $attrs[$key] = $value;
\r
398 if ( $this->debug )
\r
400 echo 'START: ', Entity::hsc($name), '<br />';
\r
405 case 'nucleusskin':
\r
412 // no action needed
\r
415 if ( !$this->inMeta )
\r
418 $this->currentName = $attrs['name'];
\r
419 $this->skins[$this->currentName]['type'] = $attrs['type'];
\r
420 $this->skins[$this->currentName]['includeMode'] = $attrs['includeMode'];
\r
421 $this->skins[$this->currentName]['includePrefix'] = $attrs['includePrefix'];
\r
422 $this->skins[$this->currentName]['parts'] = array();
\r
426 $this->skins[$attrs['name']] = array();
\r
427 $this->skins[$attrs['name']]['parts'] = array();
\r
431 if ( !$this->inMeta )
\r
433 $this->inTemplate = 1;
\r
434 $this->currentName = $attrs['name'];
\r
435 $this->templates[$this->currentName]['parts'] = array();
\r
439 $this->templates[$attrs['name']] = array();
\r
440 $this->templates[$attrs['name']]['parts'] = array();
\r
443 case 'description':
\r
444 // no action needed
\r
447 $this->currentPartName = $attrs['name'];
\r
450 echo _SKINIE_SEELEMENT_UNEXPECTEDTAG . Entity::hsc($name) . '<br />';
\r
453 // character data never contains other tags
\r
454 $this->clear_character_data();
\r
459 * Called by the XML parser for each closing tag encountered
\r
461 private function end_element($parser, $name)
\r
463 if ( $this->debug )
\r
465 echo 'END: ' . Entity::hsc($name) . '<br />';
\r
468 if ( $this->parse_charset != i18n::get_current_charset() )
\r
470 $name = i18n::convert($name, $this->parse_charset, i18n::get_current_charset());
\r
471 $charset_data = i18n::convert($this->get_character_data(), $this->parse_charset, i18n::get_current_charset());
\r
475 $charset_data = $this->get_character_data();
\r
480 case 'nucleusskin':
\r
482 $this->allRead = 1;
\r
486 $this->metaDataRead = 1;
\r
489 $this->info = $charset_data;
\r
491 if ( !$this->inMeta )
\r
497 if ( !$this->inMeta )
\r
499 $this->inTemplate = 0;
\r
502 case 'description':
\r
503 if ( $this->inSkin )
\r
505 $this->skins[$this->currentName]['description'] = $charset_data;
\r
509 $this->templates[$this->currentName]['description'] = $charset_data;
\r
513 if ( $this->inSkin )
\r
515 $this->skins[$this->currentName]['parts'][$this->currentPartName] = $charset_data;
\r
519 $this->templates[$this->currentName]['parts'][$this->currentPartName] = $charset_data;
\r
523 echo _SKINIE_SEELEMENT_UNEXPECTEDTAG . Entity::hsc($name) . '<br />';
\r
526 $this->clear_character_data();
\r
531 * Called by XML parser for data inside elements
\r
533 private function character_data ($parser, $data)
\r
535 if ( $this->debug )
\r
537 echo 'NEW DATA: ' . Entity::hsc($data) . '<br />';
\r
539 $this->cdata .= $data;
\r
544 * Returns the data collected so far
\r
546 private function get_character_data()
\r
548 return $this->cdata;
\r
552 * Clears the data buffer
\r
554 private function clear_character_data()
\r
561 * Static method that looks for importable XML files in subdirs of the given dir
\r
563 static public function searchForCandidates($dir)
\r
565 $candidates = array();
\r
567 $dirhandle = opendir($dir);
\r
568 while ( $filename = readdir($dirhandle) )
\r
570 if ( @is_dir($dir . $filename) && ($filename != '.') && ($filename != '..') )
\r
572 $xml_file = $dir . $filename . '/skinbackup.xml';
\r
573 if ( file_exists($xml_file) && is_readable($xml_file) )
\r
576 $candidates[$filename] = $filename;
\r
579 // backwards compatibility
\r
580 $xml_file = $dir . $filename . '/skindata.xml';
\r
581 if ( file_exists($xml_file) && is_readable($xml_file) )
\r
584 $candidates[$filename] = $filename;
\r
588 closedir($dirhandle);
\r
589 return $candidates;
\r
595 private $templates;
\r
600 * Constructor initializes data structures
\r
602 public function __construct()
\r
604 // list of templateIDs to export
\r
605 $this->templates = array();
\r
607 // list of skinIDs to export
\r
608 $this->skins = array();
\r
610 // extra info to be in XML file
\r
615 * Adds a template to be exported
\r
619 * @result false when no such ID exists
\r
621 public function addTemplate($id)
\r
623 if ( !Template::existsID($id) )
\r
628 $this->templates[$id] = Template::getNameFromId($id);
\r
633 * Adds a skin to be exported
\r
637 * @result false when no such ID exists
\r
639 public function addSkin($id)
\r
641 if ( !SKIN::existsID($id) )
\r
646 $this->skins[$id] = SKIN::getNameFromId($id);
\r
651 * Sets the extra info to be included in the exported file
\r
653 public function setInfo($info)
\r
655 $this->info = $info;
\r
659 * Outputs the XML contents of the export file
\r
661 * @param $setHeaders
\r
662 * set to 0 if you don't want to send out headers
\r
663 * (optional, default 1)
\r
665 public function export($setHeaders = 1)
\r
669 // make sure the mimetype is correct, and that the data does not show up
\r
670 // in the browser, but gets saved into and XML file (popup download window)
\r
671 header('Content-Type: text/xml; charset=' . i18n::get_current_charset());
\r
672 header('Content-Disposition: attachment; filename="skinbackup.xml"');
\r
673 header('Expires: 0');
\r
674 header('Pragma: no-cache');
\r
677 echo "<nucleusskin>\n";
\r
682 foreach ( $this->skins as $skinId => $skinName )
\r
684 echo "\t\t" . '<skin name="' . Entity::hsc($skinName) . '" />' . "\n";
\r
687 foreach ( $this->templates as $templateId => $templateName )
\r
689 echo "\t\t" . '<template name="' . Entity::hsc($templateName) . '" />' . "\n";
\r
694 echo "\t\t<info><![CDATA[" . $this->info . "]]></info>\n";
\r
696 echo "\t</meta>\n\n\n";
\r
699 foreach ($this->skins as $skinId => $skinName)
\r
701 $skinId = intval($skinId);
\r
702 $skinObj = new SKIN($skinId);
\r
704 echo "\t" . '<skin name="' . Entity::hsc($skinName) . '" type="' . Entity::hsc($skinObj->getContentType()) . '" includeMode="' . Entity::hsc($skinObj->getIncludeMode()) . '" includePrefix="' . Entity::hsc($skinObj->getIncludePrefix()) . '">' . "\n";
\r
705 echo "\t\t<description>" . Entity::hsc($skinObj->getDescription()) . "</description>\n";
\r
707 $res = DB::getResult('SELECT stype, scontent FROM '. sql_table('skin') .' WHERE sdesc=' . $skinId);
\r
708 foreach ( $res as $row )
\r
710 echo "\t\t" . '<part name="',Entity::hsc($row['stype']) . '">';
\r
711 echo '<![CDATA[' . $this->escapeCDATA($row['scontent']) . ']]>';
\r
712 echo "</part>\n\n";
\r
714 echo "\t</skin>\n\n\n";
\r
717 // contents templates
\r
718 foreach ( $this->templates as $templateId => $templateName )
\r
720 $templateId = intval($templateId);
\r
722 echo "\t" . '<template name="' . Entity::hsc($templateName) . '">' . "\n";
\r
723 echo "\t\t<description>" . Entity::hsc(Template::getDesc($templateId)) . "</description>\n";
\r
725 $res = DB::getResult('SELECT tpartname, tcontent FROM '. sql_table('template') .' WHERE tdesc=' . $templateId);
\r
726 foreach ( $res as $row )
\r
728 echo "\t\t" . '<part name="' . Entity::hsc($row['tpartname']) . '">';
\r
729 echo '<![CDATA[' . $this->escapeCDATA($row['tcontent']) . ']]>';
\r
730 echo "</part>\n\n";
\r
733 echo "\t</template>\n\n\n";
\r
735 echo '</nucleusskin>';
\r
739 * Escapes CDATA content so it can be included in another CDATA section
\r
741 private function escapeCDATA($cdata)
\r
743 return preg_replace('/]]>/', ']]]]><![CDATA[>', $cdata);
\r
749 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
750 * Copyright (C) 2002-2009 The Nucleus Group
752 * This program is free software; you can redistribute it and/or
753 * modify it under the terms of the GNU General Public License
754 * as published by the Free Software Foundation; either version 2
755 * of the License, or (at your option) any later version.
756 * (see nucleus/documentation/index.html#license for more info)
759 * This class contains two classes that can be used for importing and
760 * exporting Nucleus skins: SKINIMPORT and SKINEXPORT
762 * @license http://nucleuscms.org/license.txt GNU General Public License
763 * @copyright Copyright (C) 2002-2009 The Nucleus Group
764 * @version $Id: skinie.php 1883 2012-06-17 07:55:47Z sakamocchi $
769 // hardcoded value (see constructor). When 1, interesting info about the
770 // parsing process is sent to the output
773 // parser/file pointer
777 // parset internal charset, US-ASCII/ISO-8859-1/UTF-8
778 private $parse_charset = 'UTF-8';
780 // which data has been read?
781 private $metaDataRead;
789 // to maintain track of where we are inside the XML file
795 private $currentName;
796 private $currentPartName;
800 * constructor initializes data structures
802 public function __construct()
804 // disable magic_quotes_runtime if it's turned on
805 //set_magic_quotes_runtime(0);
806 if ( version_compare(PHP_VERSION, '5.3.0', '<') )
808 ini_set('magic_quotes_runtime', '0');
818 public function __destruct()
823 public function reset()
827 xml_parser_free($this->parser);
833 // which data has been read?
834 $this->metaDataRead = 0;
837 // to maintain track of where we are inside the XML file
842 $this->inTemplate = 0;
843 $this->currentName = '';
844 $this->currentPartName = '';
846 // character data pile
849 // list of skinnames and templatenames (will be array of array)
850 $this->skins = array();
851 $this->templates = array();
853 // extra info included in the XML files (e.g. installation notes)
856 // init XML parser, this parser deal with characters as encoded by UTF-8
857 $this->parser = xml_parser_create($this->parse_charset);
858 xml_set_object($this->parser, $this);
859 xml_set_element_handler($this->parser, 'start_element', 'end_element');
860 xml_set_character_data_handler($this->parser, 'character_data');
861 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
867 * Reads an XML file into memory
872 * Set to 1 when only the metadata needs to be read (optional, default 0)
874 public function readFile($filename, $metaOnly = 0)
877 $this->fp = @fopen($filename, 'r');
880 return _SKINIE_ERROR_FAILEDOPEN_FILEURL;
888 while ( !feof($this->fp) )
890 $tempbuffer .= fread($this->fp, 4096);
895 * NOTE: conver character set.
896 * We hope all characters in the file also includes UTF-8 coded character set,
897 * because this PHP extension implements support for James Clark's expat in PHP
898 * and it supports juust US-ASCII, ISO-8859-1, UTF-8 character coding scheme.
900 if ( i18n::get_current_charset() != $this->parse_charset )
902 $tempbuffer = i18n::convert($tempbuffer, i18n::get_current_charset(), $this->parse_charset);
906 fwrite($temp, $tempbuffer);
909 while ( ($buffer = fread($temp, 4096) )
910 && (!$metaOnly || ($metaOnly && !$this->metaDataRead)) )
912 $err = xml_parse( $this->parser, $buffer, feof($temp) );
913 if ( !$err && $this->debug )
915 echo 'ERROR: ', xml_error_string(xml_get_error_code($this->parser)), '<br />';
927 * Returns the list of skin names
929 public function getSkinNames()
931 return array_keys($this->skins);
935 * Returns the list of template names
937 public function getTemplateNames()
939 return array_keys($this->templates);
943 * Returns the extra information included in the XML file
945 public function getInfo()
951 * Writes the skins and templates to the database
953 * @param $allowOverwrite
954 * set to 1 when allowed to overwrite existing skins with the same name
957 public function writeToDatabase($allowOverwrite = 0)
961 $existingSkins = $this->checkSkinNameClashes();
962 $existingTemplates = $this->checkTemplateNameClashes();
963 $invalidSkinNames = $this->checkSkinNamesValid();
964 $invalidTemplateNames = $this->checkTemplateNamesValid();
966 // if there are invalid skin or template names, stop executioin and return and error
967 if ( (sizeof($invalidSkinNames) > 0) || (sizeof($invalidTemplateNames) > 0) )
969 $inames_error = "<p>"._SKINIE_INVALID_NAMES_DETECTED."</p>\n";
970 $inames_error .= "<ul>";
971 foreach( $invalidSkinNames as $sName )
973 $inames_error .= "<li>".Entity::hsc($sName)."</li>";
975 foreach( $invalidTemplateNames as $sName )
977 $inames_error .= "<li>".Entity::hsc($sName)."</li>";
979 $inames_error .= "</ul>";
980 return $inames_error;
983 // if not allowed to overwrite, check if any nameclashes exists
984 if ( !$allowOverwrite )
986 if ( (sizeof($existingSkins) > 0) || (sizeof($existingTemplates) > 0) )
988 return _SKINIE_NAME_CLASHES_DETECTED;
992 foreach ( $this->skins as $skinName => $data )
994 // 1. if exists: delete all part data, update desc data
995 // if not exists: create desc
996 if ( in_array($skinName, $existingSkins) )
998 $skinObj = SKIN::createFromName($skinName);
1000 // delete all parts of the skin
1001 $skinObj->deleteAllParts();
1003 // update general info
1004 $skinObj->updateGeneralInfo(
1006 $data['description'],
1008 $data['includeMode'],
1009 $data['includePrefix']
1014 $skinid = SKIN::createNew(
1016 $data['description'],
1018 $data['includeMode'],
1019 $data['includePrefix']
1021 $skinObj =& $manager->getSkin($skinid);
1025 foreach ( $data['parts'] as $partName => $partContent )
1027 $skinObj->update($partName, $partContent);
1031 foreach ( $this->templates as $templateName => $data )
1033 // 1. if exists: delete all part data, update desc data
1034 // if not exists: create desc
1035 if ( in_array($templateName, $existingTemplates) )
1037 $templateObj = Template::createFromName($templateName);
1039 // delete all parts of the template
1040 $templateObj->deleteAllParts();
1042 // update general info
1043 $templateObj->updateGeneralInfo($templateName, $data['description']);
1047 $templateid = Template::createNew($templateName, $data['description']);
1048 $templateObj = new Template($templateid);
1052 foreach ( $data['parts'] as $partName => $partContent )
1054 $templateObj->update($partName, $partContent);
1061 * returns an array of all the skin nameclashes (empty array when no name clashes)
1063 public function checkSkinNameClashes()
1067 foreach ( $this->skins as $skinName => $data )
1069 if ( SKIN::exists($skinName) )
1071 array_push($clashes, $skinName);
1078 * returns an array of all the template nameclashes
1079 * (empty array when no name clashes)
1081 public function checkTemplateNameClashes()
1085 foreach ( $this->templates as $templateName => $data )
1087 if ( Template::exists($templateName) )
1089 array_push($clashes, $templateName);
1096 * returns an array of all the invalid skin names (empty array when no invalid names )
1098 private function checkSkinNamesValid()
1100 $notValid = array();
1102 foreach ( $this->skins as $skinName => $data )
1104 if ( !isValidSkinName($skinName) )
1106 array_push($notValid, $skinName);
1113 * returns an array of all the invalid template names (empty array when no invalid names )
1115 private function checkTemplateNamesValid()
1117 $notValid = array();
1119 foreach ( $this->templates as $templateName => $data )
1121 if ( !isValidTemplateName($templateName) )
1123 array_push($notValid, $templateName);
1130 * Called by XML parser for each new start element encountered
1132 private function start_element($parser, $name, $attrs)
1134 foreach( $attrs as $key=>$value )
1136 if ( $this->parse_charset != i18n::get_current_charset() )
1138 $name = i18n::convert($name, $this->parse_charset, i18n::get_current_charset());
1139 $value = i18n::convert($value, $this->parse_charset, i18n::get_current_charset());
1142 $attrs[$key] = $value;
1147 echo 'START: ', Entity::hsc($name), '<br />';
1162 if ( !$this->inMeta )
1165 $this->currentName = $attrs['name'];
1166 $this->skins[$this->currentName]['type'] = $attrs['type'];
1167 $this->skins[$this->currentName]['includeMode'] = $attrs['includeMode'];
1168 $this->skins[$this->currentName]['includePrefix'] = $attrs['includePrefix'];
1169 $this->skins[$this->currentName]['parts'] = array();
1173 $this->skins[$attrs['name']] = array();
1174 $this->skins[$attrs['name']]['parts'] = array();
1178 if ( !$this->inMeta )
1180 $this->inTemplate = 1;
1181 $this->currentName = $attrs['name'];
1182 $this->templates[$this->currentName]['parts'] = array();
1186 $this->templates[$attrs['name']] = array();
1187 $this->templates[$attrs['name']]['parts'] = array();
1194 $this->currentPartName = $attrs['name'];
1197 echo _SKINIE_SEELEMENT_UNEXPECTEDTAG . Entity::hsc($name) . '<br />';
1200 // character data never contains other tags
1201 $this->clear_character_data();
1206 * Called by the XML parser for each closing tag encountered
1208 private function end_element($parser, $name)
1212 echo 'END: ' . Entity::hsc($name) . '<br />';
1215 if ( $this->parse_charset != i18n::get_current_charset() )
1217 $name = i18n::convert($name, $this->parse_charset, i18n::get_current_charset());
1218 $charset_data = i18n::convert($this->get_character_data(), $this->parse_charset, i18n::get_current_charset());
1222 $charset_data = $this->get_character_data();
1233 $this->metaDataRead = 1;
1236 $this->info = $charset_data;
1238 if ( !$this->inMeta )
1244 if ( !$this->inMeta )
1246 $this->inTemplate = 0;
1250 if ( $this->inSkin )
1252 $this->skins[$this->currentName]['description'] = $charset_data;
1256 $this->templates[$this->currentName]['description'] = $charset_data;
1260 if ( $this->inSkin )
1262 $this->skins[$this->currentName]['parts'][$this->currentPartName] = $charset_data;
1266 $this->templates[$this->currentName]['parts'][$this->currentPartName] = $charset_data;
1270 echo _SKINIE_SEELEMENT_UNEXPECTEDTAG . Entity::hsc($name) . '<br />';
1273 $this->clear_character_data();
1278 * Called by XML parser for data inside elements
1280 private function character_data ($parser, $data)
1284 echo 'NEW DATA: ' . Entity::hsc($data) . '<br />';
1286 $this->cdata .= $data;
1291 * Returns the data collected so far
1293 private function get_character_data()
1295 return $this->cdata;
1299 * Clears the data buffer
1301 private function clear_character_data()
1308 * Static method that looks for importable XML files in subdirs of the given dir
1310 static public function searchForCandidates($dir)
1312 $candidates = array();
1314 $dirhandle = opendir($dir);
1315 while ( $filename = readdir($dirhandle) )
1317 if ( @is_dir($dir . $filename) && ($filename != '.') && ($filename != '..') )
1319 $xml_file = $dir . $filename . '/skinbackup.xml';
1320 if ( file_exists($xml_file) && is_readable($xml_file) )
1323 $candidates[$filename] = $filename;
1326 // backwards compatibility
1327 $xml_file = $dir . $filename . '/skindata.xml';
1328 if ( file_exists($xml_file) && is_readable($xml_file) )
1331 $candidates[$filename] = $filename;
1335 closedir($dirhandle);
1347 * Constructor initializes data structures
1349 public function __construct()
1351 // list of templateIDs to export
1352 $this->templates = array();
1354 // list of skinIDs to export
1355 $this->skins = array();
1357 // extra info to be in XML file
1362 * Adds a template to be exported
1366 * @result false when no such ID exists
1368 public function addTemplate($id)
1370 if ( !Template::existsID($id) )
1375 $this->templates[$id] = Template::getNameFromId($id);
1380 * Adds a skin to be exported
1384 * @result false when no such ID exists
1386 public function addSkin($id)
1388 if ( !SKIN::existsID($id) )
1393 $this->skins[$id] = SKIN::getNameFromId($id);
1398 * Sets the extra info to be included in the exported file
1400 public function setInfo($info)
1402 $this->info = $info;
1406 * Outputs the XML contents of the export file
1408 * @param $setHeaders
1409 * set to 0 if you don't want to send out headers
1410 * (optional, default 1)
1412 public function export($setHeaders = 1)
1418 // make sure the mimetype is correct, and that the data does not show up
1419 // in the browser, but gets saved into and XML file (popup download window)
1420 header('Content-Type: text/xml; charset=' . i18n::get_current_charset());
1421 header('Content-Disposition: attachment; filename="skinbackup.xml"');
1422 header('Expires: 0');
1423 header('Pragma: no-cache');
1426 echo "<nucleusskin>\n";
1431 foreach ( $this->skins as $skinId => $skinName )
1433 echo "\t\t" . '<skin name="' . Entity::hsc($skinName) . '" />' . "\n";
1436 foreach ( $this->templates as $templateId => $templateName )
1438 echo "\t\t" . '<template name="' . Entity::hsc($templateName) . '" />' . "\n";
1443 echo "\t\t<info><![CDATA[" . $this->info . "]]></info>\n";
1445 echo "\t</meta>\n\n\n";
1448 foreach ($this->skins as $skinId => $skinName)
1450 $skinId = (integer) $skinId;
1451 $skinObj =& $manager->getSkin($skinId);
1453 echo "\t" . '<skin name="' . Entity::hsc($skinName) . '" type="' . Entity::hsc($skinObj->getContentType()) . '" includeMode="' . Entity::hsc($skinObj->getIncludeMode()) . '" includePrefix="' . Entity::hsc($skinObj->getIncludePrefix()) . '">' . "\n";
1454 echo "\t\t<description>" . Entity::hsc($skinObj->getDescription()) . "</description>\n";
1456 $res = DB::getResult('SELECT stype, scontent FROM '. sql_table('skin') .' WHERE sdesc=' . $skinId);
1457 foreach ( $res as $row )
1459 echo "\t\t" . '<part name="',Entity::hsc($row['stype']) . '">';
1460 echo '<![CDATA[' . $this->escapeCDATA($row['scontent']) . ']]>';
1463 echo "\t</skin>\n\n\n";
1466 // contents templates
1467 foreach ( $this->templates as $templateId => $templateName )
1469 $templateId = intval($templateId);
1471 echo "\t" . '<template name="' . Entity::hsc($templateName) . '">' . "\n";
1472 echo "\t\t<description>" . Entity::hsc(Template::getDesc($templateId)) . "</description>\n";
1474 $res = DB::getResult('SELECT tpartname, tcontent FROM '. sql_table('template') .' WHERE tdesc=' . $templateId);
1475 foreach ( $res as $row )
1477 echo "\t\t" . '<part name="' . Entity::hsc($row['tpartname']) . '">';
1478 echo '<![CDATA[' . $this->escapeCDATA($row['tcontent']) . ']]>';
1482 echo "\t</template>\n\n\n";
1484 echo '</nucleusskin>';
1488 * Escapes CDATA content so it can be included in another CDATA section
1490 private function escapeCDATA($cdata)
1492 return preg_replace('/]]>/', ']]]]><![CDATA[>', $cdata);
1495 >>>>>>> skinnable-master