|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00025 require_once($CFG->dirroot.'/backup/util/xml/parser/processors/simplified_parser_processor.class.php'); 00026 00041 abstract class grouped_parser_processor extends simplified_parser_processor { 00042 00043 protected $groupedpaths; // Paths we are requesting grouped 00044 protected $currentdata; // Where we'll be acummulating data 00045 00046 public function __construct(array $paths = array()) { 00047 $this->groupedpaths = array(); 00048 $this->currentdata = null; 00049 parent::__construct($paths); 00050 } 00051 00052 public function add_path($path, $grouped = false) { 00053 if ($grouped) { 00054 // Check there is no parent in the branch being grouped 00055 if ($found = $this->grouped_parent_exists($path)) { 00056 $a = new stdclass(); 00057 $a->path = $path; 00058 $a->parent = $found; 00059 throw new progressive_parser_exception('xml_grouped_parent_found', $a); 00060 } 00061 // Check there is no child in the branch being grouped 00062 if ($found = $this->grouped_child_exists($path)) { 00063 $a = new stdclass(); 00064 $a->path = $path; 00065 $a->child = $found; 00066 throw new progressive_parser_exception('xml_grouped_child_found', $a); 00067 } 00068 $this->groupedpaths[] = $path; 00069 } 00070 parent::add_path($path); 00071 } 00072 00078 public function before_path($path) { 00079 if (!$this->grouped_parent_exists($path)) { 00080 parent::before_path($path); 00081 } 00082 } 00083 00089 public function after_path($path) { 00090 // Have finished one grouped path, dispatch it 00091 if ($this->path_is_grouped($path)) { 00092 // Any accumulated information must be in 00093 // currentdata, properly built 00094 $data = $this->currentdata[$path]; 00095 unset($this->currentdata[$path]); 00096 // TODO: If running under DEBUG_DEVELOPER notice about >1MB grouped chunks 00097 $this->dispatch_chunk($data); 00098 } 00099 // Normal notification of path end 00100 // Only if path is selected and not child of grouped 00101 if (!$this->grouped_parent_exists($path)) { 00102 parent::after_path($path); 00103 } 00104 } 00105 00106 // Protected API starts here 00107 00112 protected function postprocess_chunk($data) { 00113 $path = $data['path']; 00114 // If the chunk is a grouped one, simply put it into currentdata 00115 if ($this->path_is_grouped($path)) { 00116 $this->currentdata[$path] = $data; 00117 00118 // If the chunk is child of grouped one, add it to currentdata 00119 } else if ($grouped = $this->grouped_parent_exists($path)) { 00120 $this->build_currentdata($grouped, $data); 00121 $this->chunks--; // not counted, as it's accumulated 00122 00123 // No grouped nor child of grouped, dispatch it 00124 } else { 00125 $this->dispatch_chunk($data); 00126 } 00127 } 00128 00129 protected function path_is_grouped($path) { 00130 return in_array($path, $this->groupedpaths); 00131 } 00132 00138 protected function grouped_parent_exists($path) { 00139 $parentpath = progressive_parser::dirname($path); 00140 while ($parentpath != '/') { 00141 if ($this->path_is_grouped($parentpath)) { 00142 return $parentpath; 00143 } 00144 $parentpath = progressive_parser::dirname($parentpath); 00145 } 00146 return false; 00147 } 00148 00154 protected function grouped_child_exists($path) { 00155 $childpath = $path . '/'; 00156 foreach ($this->groupedpaths as $groupedpath) { 00157 if (strpos($groupedpath, $childpath) === 0) { 00158 return $groupedpath; 00159 } 00160 } 00161 return false; 00162 } 00163 00168 protected function build_currentdata($grouped, $data) { 00169 // Check the grouped already exists into currentdata 00170 if (!array_key_exists($grouped, $this->currentdata)) { 00171 $a = new stdclass(); 00172 $a->grouped = $grouped; 00173 $a->child = $data['path']; 00174 throw new progressive_parser_exception('xml_cannot_add_to_grouped', $a); 00175 } 00176 $this->add_missing_sub($grouped, $data['path'], $data['tags']); 00177 } 00178 00182 protected function add_missing_sub($grouped, $path, $tags) { 00183 00184 // Remember tag being processed 00185 $processedtag = basename($path); 00186 00187 $info =& $this->currentdata[$grouped]['tags']; 00188 $hierarchyarr = explode('/', str_replace($grouped . '/', '', $path)); 00189 00190 $previouselement = ''; 00191 $currentpath = ''; 00192 00193 foreach ($hierarchyarr as $index => $element) { 00194 00195 $currentpath = $currentpath . '/' . $element; 00196 00197 // If element is already set and it's not 00198 // the processed one (with tags) fast move the $info 00199 // pointer and continue 00200 if ($element !== $processedtag && isset($info[$element])) { 00201 $previouselement = $element; 00202 $info =& $info[$element]; 00203 continue; 00204 } 00205 00206 // If previous element already has occurrences 00207 // we move $info pointer there (only if last is 00208 // numeric occurrence) 00209 if (!empty($previouselement) && is_array($info) && count($info) > 0) { 00210 end($info); 00211 $key = key($info); 00212 if ((int) $key === $key) { 00213 $info =& $info[$key]; 00214 } 00215 } 00216 00217 // Create element if not defined 00218 if (!isset($info[$element])) { 00219 // First into last element if present 00220 $info[$element] = array(); 00221 } 00222 00223 // If element is the current one, add information 00224 if ($element === $processedtag) { 00225 $info[$element][] = $tags; 00226 } 00227 00228 $previouselement = $element; 00229 $info =& $info[$element]; 00230 } 00231 } 00232 }