|
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 defined('MOODLE_INTERNAL') || die(); 00026 00036 class restore_decode_rule { 00037 00038 protected $linkname; // How the link has been encoded in backup (CHOICEVIEWBYID, COURSEVIEWBYID...) 00039 protected $urltemplate; // How the original URL looks like, with dollar placeholders 00040 protected $mappings; // Which backup_ids mappings do we need to apply for replacing the placeholders 00041 protected $restoreid; // The unique restoreid we are executing 00042 protected $sourcewwwroot; // The original wwwroot of the backup file 00043 protected $targetwwwroot; // The targer wwwroot of the restore operation 00044 00045 protected $cregexp; // Calculated regular expresion we'll be looking for matches 00046 00047 public function __construct($linkname, $urltemplate, $mappings) { 00048 // Validate all the params are ok 00049 $this->mappings = $this->validate_params($linkname, $urltemplate, $mappings); 00050 $this->linkname = $linkname; 00051 $this->urltemplate = $urltemplate; 00052 $this->restoreid = 0; 00053 $this->sourcewwwroot = ''; 00054 $this->targetwwwroot = ''; // yes, uses to be $CFG->wwwroot, and? ;-) 00055 $this->cregexp = $this->get_calculated_regexp(); 00056 } 00057 00058 public function set_restoreid($restoreid) { 00059 $this->restoreid = $restoreid; 00060 } 00061 00062 public function set_wwwroots($sourcewwwroot, $targetwwwroot) { 00063 $this->sourcewwwroot = $sourcewwwroot; 00064 $this->targetwwwroot = $targetwwwroot; 00065 } 00066 00067 public function decode($content) { 00068 if (preg_match_all($this->cregexp, $content, $matches) === 0) { // 0 matches, nothing to change 00069 return $content; 00070 } 00071 // Have found matches, iterate over them 00072 foreach ($matches[0] as $key => $tosearch) { 00073 $mappingsok = true; // To detect if any mapping has failed 00074 $placeholdersarr = array(); // The placeholders to be replaced 00075 $mappingssourcearr = array(); // To store the original mappings values 00076 $mappingstargetarr = array(); // To store the target mappings values 00077 $toreplace = $this->urltemplate;// The template used to build the replacement 00078 foreach ($this->mappings as $mappingkey => $mappingsource) { 00079 $source = $matches[$mappingkey][$key]; // get source 00080 $mappingssourcearr[$mappingkey] = $source; // set source arr 00081 $mappingstargetarr[$mappingkey] = 0; // apply default mapping 00082 $placeholdersarr[$mappingkey] = '$'.$mappingkey;// set the placeholders arr 00083 if (!$mappingsok) { // already missing some mapping, continue 00084 continue; 00085 } 00086 if (!$target = $this->get_mapping($mappingsource, $source)) {// mapping not found, mark and continue 00087 $mappingsok = false; 00088 continue; 00089 } 00090 $mappingstargetarr[$mappingkey] = $target; // store found mapping 00091 } 00092 $toreplace = $this->apply_modifications($toreplace, $mappingsok); // Apply other changes before replacement 00093 if (!$mappingsok) { // Some mapping has failed, apply original values to the template 00094 $toreplace = str_replace($placeholdersarr, $mappingssourcearr, $toreplace); 00095 00096 } else { // All mappings found, apply target values to the template 00097 $toreplace = str_replace($placeholdersarr, $mappingstargetarr, $toreplace); 00098 } 00099 // Finally, perform the replacement in original content 00100 $content = str_replace($tosearch, $toreplace, $content); 00101 } 00102 return $content; // return the decoded content, pointing to original or target values 00103 } 00104 00105 // Protected API starts here 00106 00110 protected function get_mapping($itemname, $itemid) { 00111 // Check restoreid is set 00112 if (!$this->restoreid) { 00113 throw new restore_decode_rule_exception('decode_rule_restoreid_not_set'); 00114 } 00115 if (!$found = restore_dbops::get_backup_ids_record($this->restoreid, $itemname, $itemid)) { 00116 return false; 00117 } 00118 return $found->newitemid; 00119 } 00120 00126 protected function apply_modifications($toreplace, $mappingsok) { 00127 // Check wwwroots are set 00128 if (!$this->targetwwwroot || !$this->sourcewwwroot) { 00129 throw new restore_decode_rule_exception('decode_rule_wwwroots_not_set'); 00130 } 00131 return ($mappingsok ? $this->targetwwwroot : $this->sourcewwwroot) . $toreplace; 00132 } 00133 00137 protected function validate_params($linkname, $urltemplate, $mappings) { 00138 // Check linkname is A-Z0-9 00139 if (empty($linkname) || preg_match('/[^A-Z0-9]/', $linkname)) { 00140 throw new restore_decode_rule_exception('decode_rule_incorrect_name', $linkname); 00141 } 00142 // Look urltemplate starts by / 00143 if (empty($urltemplate) || substr($urltemplate, 0, 1) != '/') { 00144 throw new restore_decode_rule_exception('decode_rule_incorrect_urltemplate', $urltemplate); 00145 } 00146 if (!is_array($mappings)) { 00147 $mappings = array($mappings); 00148 } 00149 // Look for placeholders in template 00150 $countph = preg_match_all('/(\$\d+)/', $urltemplate, $matches); 00151 $countma = count($mappings); 00152 // Check mappings number matches placeholders 00153 if ($countph != $countma) { 00154 $a = new stdClass(); 00155 $a->placeholders = $countph; 00156 $a->mappings = $countma; 00157 throw new restore_decode_rule_exception('decode_rule_mappings_incorrect_count', $a); 00158 } 00159 // Verify they are consecutive (starting on 1) 00160 $smatches = str_replace('$', '', $matches[1]); 00161 sort($smatches, SORT_NUMERIC); 00162 if (reset($smatches) != 1 || end($smatches) != $countma) { 00163 throw new restore_decode_rule_exception('decode_rule_nonconsecutive_placeholders', implode(', ', $smatches)); 00164 } 00165 // No dupes in placeholders 00166 if (count($smatches) != count(array_unique($smatches))) { 00167 throw new restore_decode_rule_exception('decode_rule_duplicate_placeholders', implode(', ', $smatches)); 00168 } 00169 00170 // Return one array of placeholders as keys and mappings as values 00171 return array_combine($smatches, $mappings); 00172 } 00173 00177 protected function get_calculated_regexp() { 00178 $regexp = '/\$@' . $this->linkname; 00179 foreach ($this->mappings as $key => $value) { 00180 $regexp .= '\*(\d+)'; 00181 } 00182 $regexp .= '@\$/'; 00183 return $regexp; 00184 } 00185 } 00186 00187 /* 00188 * Exception class used by all the @restore_decode_rule stuff 00189 */ 00190 class restore_decode_rule_exception extends backup_exception { 00191 00192 public function __construct($errorcode, $a=NULL, $debuginfo=null) { 00193 return parent::__construct($errorcode, $a, $debuginfo); 00194 } 00195 }