Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/backup/util/xml/parser/processors/grouped_parser_processor.class.php
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Enumerations