|
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 00030 class backup_nested_element extends base_nested_element implements processable { 00031 00032 protected $var_array; // To be used in case we pass one in-memory structure 00033 protected $table; // Table (without prefix) to fetch records from 00034 protected $sql; // Raw SQL to fetch records from 00035 protected $params; // Unprocessed params as specified in the set_source() call 00036 protected $procparams;// Processed (path resolved) params array 00037 protected $aliases; // Define DB->final element aliases 00038 protected $fileannotations; // array of file areas to be searched by file annotations 00039 protected $counter; // Number of instances of this element that have been processed 00040 00048 public function __construct($name, $attributes = null, $final_elements = null) { 00049 parent::__construct($name, $attributes, $final_elements); 00050 $this->var_array = null; 00051 $this->table = null; 00052 $this->sql = null; 00053 $this->params = null; 00054 $this->procparams= null; 00055 $this->aliases = array(); 00056 $this->fileannotations = array(); 00057 $this->counter = 0; 00058 } 00059 00060 public function process($processor) { 00061 if (!$processor instanceof base_processor) { // No correct processor, throw exception 00062 throw new base_element_struct_exception('incorrect_processor'); 00063 } 00064 00065 $iterator = $this->get_iterator($processor); // Get the iterator over backup-able data 00066 00067 foreach ($iterator as $key => $values) { // Process each "ocurrrence" of the nested element (recordset or array) 00068 00069 // Fill the values of the attributes and final elements with the $values from the iterator 00070 $this->fill_values($values); 00071 00072 // Perform pre-process tasks for the nested_element 00073 $processor->pre_process_nested_element($this); 00074 00075 // Delegate the process of each attribute 00076 foreach ($this->get_attributes() as $attribute) { 00077 $attribute->process($processor); 00078 } 00079 00080 // Main process tasks for the nested element, once its attributes have been processed 00081 $processor->process_nested_element($this); 00082 00083 // Delegate the process of each final_element 00084 foreach ($this->get_final_elements() as $final_element) { 00085 $final_element->process($processor); 00086 } 00087 00088 // Delegate the process to the optigroup 00089 if ($this->get_optigroup()) { 00090 $this->get_optigroup()->process($processor); 00091 } 00092 00093 // Delegate the process to each child nested_element 00094 foreach ($this->get_children() as $child) { 00095 $child->process($processor); 00096 } 00097 00098 // Perform post-process tasks for the nested element 00099 $processor->post_process_nested_element($this); 00100 00101 // Everything processed, clean values before next iteration 00102 $this->clean_values(); 00103 00104 // Increment counter for this element 00105 $this->counter++; 00106 00107 // For root element, check we only have 1 element 00108 if ($this->get_parent() === null && $this->counter > 1) { 00109 throw new base_element_struct_exception('root_only_one_ocurrence', $this->get_name()); 00110 } 00111 } 00112 // Close the iterator (DB recordset / array iterator) 00113 $iterator->close(); 00114 } 00115 00116 public function set_source_array($arr) { 00117 // TODO: Only elements having final elements can set source 00118 $this->var_array = $arr; 00119 } 00120 00121 public function set_source_table($table, $params) { 00122 if (!is_array($params)) { // Check we are passing array 00123 throw new base_element_struct_exception('setsourcerequiresarrayofparams'); 00124 } 00125 // TODO: Only elements having final elements can set source 00126 $this->table = $table; 00127 $this->procparams = $this->convert_table_params($params); 00128 } 00129 00130 public function set_source_sql($sql, $params) { 00131 if (!is_array($params)) { // Check we are passing array 00132 throw new base_element_struct_exception('setsourcerequiresarrayofparams'); 00133 } 00134 // TODO: Only elements having final elements can set source 00135 $this->sql = $sql; 00136 $this->procparams = $this->convert_sql_params($params); 00137 } 00138 00139 public function set_source_alias($dbname, $finalelementname) { 00140 // Get final element 00141 $finalelement = $this->get_final_element($finalelementname); 00142 if (!$finalelement) { // Final element incorrect, throw exception 00143 throw new base_element_struct_exception('incorrectaliasfinalnamenotfound', $finalelementname); 00144 } else { 00145 $this->aliases[$dbname] = $finalelement; 00146 } 00147 } 00148 00149 public function annotate_files($component, $filearea, $elementname, $filesctxid = null) { 00150 if (!array_key_exists($component, $this->fileannotations)) { 00151 $this->fileannotations[$component] = array(); 00152 } 00153 00154 if ($elementname !== null) { // Check elementname is valid 00155 $elementname = $this->find_element($elementname); //TODO: no warning here? (skodak) 00156 } 00157 00158 if (array_key_exists($filearea, $this->fileannotations[$component])) { 00159 throw new base_element_struct_exception('annotate_files_duplicate_annotation', "$component/$filearea/$elementname"); 00160 } 00161 00162 $info = new stdclass(); 00163 $info->element = $elementname; 00164 $info->contextid = $filesctxid; 00165 $this->fileannotations[$component][$filearea] = $info; 00166 } 00167 00168 public function annotate_ids($itemname, $elementname) { 00169 $element = $this->find_element($elementname); 00170 $element->set_annotation_item($itemname); 00171 } 00172 00177 public function get_file_annotations() { 00178 return $this->fileannotations; 00179 } 00180 00181 public function get_source_array() { 00182 return $this->var_array; 00183 } 00184 00185 public function get_source_table() { 00186 return $this->table; 00187 } 00188 00189 public function get_source_sql() { 00190 return $this->sql; 00191 } 00192 00193 public function get_counter() { 00194 return $this->counter; 00195 } 00196 00202 public function fill_values($values) { 00203 $values = (array)$values; 00204 00205 foreach ($values as $key => $value) { 00206 $found = 0; 00207 if ($attribute = $this->get_attribute($key)) { // Set value for attributes 00208 $attribute->set_value($value); 00209 $found++; 00210 } 00211 if ($final = $this->get_final_element($key)) { // Set value for final elements 00212 $final->set_value($value); 00213 $found++; 00214 } 00215 if (isset($this->aliases[$key])) { // Last chance, set value by processing final element aliases 00216 $this->aliases[$key]->set_value($value); 00217 $found++; 00218 } 00219 // Found more than once, notice 00220 // TODO: Route this through backup loggers 00221 if ($found > 1) { 00222 debugging('Key found more than once ' . $key, DEBUG_DEVELOPER); 00223 } 00224 } 00225 00226 } 00227 00228 // Protected API starts here 00229 00230 protected function convert_table_params($params) { 00231 return $this->convert_sql_params($params); 00232 } 00233 00234 protected function convert_sql_params($params) { 00235 $procparams = array(); // Reset processed params 00236 foreach ($params as $key => $param) { 00237 $procparams[$key] = $this->find_element($param); 00238 } 00239 return $procparams; 00240 } 00241 00242 protected function find_element($param) { 00243 if ($param == backup::VAR_PARENTID) { // Look for first parent having id attribute/final_element 00244 $param = $this->find_first_parent_by_name('id'); 00245 00246 // If the param is array, with key 'sqlparam', return the value without modifications 00247 } else if (is_array($param) && array_key_exists('sqlparam', $param)) { 00248 return $param['sqlparam']; 00249 00250 } else if (((int)$param) >= 0) { // Search by path if param isn't a backup::XXX candidate 00251 $param = $this->find_element_by_path($param); 00252 } 00253 return $param; // Return the param unmodified 00254 } 00255 00260 protected function get_new_attribute($name) { 00261 return new backup_attribute($name); 00262 } 00263 00268 protected function get_new_final_element($name) { 00269 return new backup_final_element($name); 00270 } 00271 00276 protected function get_iterator($processor) { 00277 return backup_structure_dbops::get_iterator($this, $this->procparams, $processor); 00278 } 00279 }