|
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 abstract class base_nested_element extends base_final_element { 00031 00033 private $final_elements; 00034 00036 private $children; 00037 00039 private $optigroup; 00040 00042 private $used; 00043 00051 public function __construct($name, $attributes = null, $final_elements = null) { 00052 parent::__construct($name, $attributes); 00053 $this->final_elements = array(); 00054 if (!empty($final_elements)) { 00055 $this->add_final_elements($final_elements); 00056 } 00057 $this->children = array(); 00058 $this->optigroup = null; 00059 $this->used[] = $name; 00060 } 00061 00065 public function destroy() { 00066 // Before reseting anything, call destroy recursively 00067 foreach ($this->children as $child) { 00068 $child->destroy(); 00069 } 00070 foreach ($this->final_elements as $element) { 00071 $element->destroy(); 00072 } 00073 if ($this->optigroup) { 00074 $this->optigroup->destroy(); 00075 } 00076 // Everything has been destroyed recursively, now we can reset safely 00077 $this->children = array(); 00078 $this->final_elements = array(); 00079 $this->optigroup = null; 00080 // Delegate to parent to destroy other bits 00081 parent::destroy(); 00082 } 00083 00084 protected function get_used() { 00085 return $this->used; 00086 } 00087 00088 protected function set_used($used) { 00089 $this->used = $used; 00090 } 00091 00092 protected function add_used($element) { 00093 $this->used = array_merge($this->used, $element->get_used()); 00094 } 00095 00096 protected function check_and_set_used($element) { 00097 // First of all, check the element being added doesn't conflict with own final elements 00098 if (array_key_exists($element->get_name(), $this->final_elements)) { 00099 throw new base_element_struct_exception('baseelementchildnameconflict', $element->get_name()); 00100 } 00101 $grandparent = $this->get_grandoptigroupelement_or_grandparent(); 00102 if ($existing = array_intersect($grandparent->get_used(), $element->get_used())) { // Check the element isn't being used already 00103 throw new base_element_struct_exception('baseelementexisting', implode($existing)); 00104 } 00105 $grandparent->add_used($element); 00106 // If the parent is one optigroup, add the element useds to it too 00107 if ($grandparent->get_parent() instanceof base_optigroup) { 00108 $grandparent->get_parent()->add_used($element); 00109 } 00110 00111 } 00112 00114 00115 public function get_final_elements() { 00116 return $this->final_elements; 00117 } 00118 00119 public function get_final_element($name) { 00120 if (array_key_exists($name, $this->final_elements)) { 00121 return $this->final_elements[$name]; 00122 } else { 00123 return null; 00124 } 00125 } 00126 00127 public function get_children() { 00128 return $this->children; 00129 } 00130 00131 public function get_child($name) { 00132 if (array_key_exists($name, $this->children)) { 00133 return $this->children[$name]; 00134 } else { 00135 return null; 00136 } 00137 } 00138 00139 public function get_optigroup() { 00140 return $this->optigroup; 00141 } 00142 00143 public function add_final_elements($final_elements) { 00144 if ($final_elements instanceof base_final_element || is_string($final_elements)) { // Accept 1 final_element, object or string 00145 $final_elements = array($final_elements); 00146 } 00147 if (is_array($final_elements)) { 00148 foreach ($final_elements as $final_element) { 00149 if (is_string($final_element)) { // Accept string final_elements 00150 $final_element = $this->get_new_final_element($final_element); 00151 } 00152 if (!($final_element instanceof base_final_element)) { 00153 throw new base_element_struct_exception('baseelementnofinalelement', get_class($final_element)); 00154 } 00155 if (array_key_exists($final_element->get_name(), $this->final_elements)) { 00156 throw new base_element_struct_exception('baseelementexists', $final_element->get_name()); 00157 } 00158 $this->final_elements[$final_element->get_name()] = $final_element; 00159 $final_element->set_parent($this); 00160 } 00161 } else { 00162 throw new base_element_struct_exception('baseelementincorrect'); 00163 } 00164 } 00165 00166 public function add_child($element) { 00167 if (!($element instanceof base_nested_element)) { // parameter must be a base_nested_element 00168 if (!$found = get_class($element)) { 00169 $found = 'non object'; 00170 } 00171 throw new base_element_struct_exception('nestedelementincorrect', $found); 00172 } 00173 $this->check_and_set_used($element); 00174 $this->children[$element->get_name()] = $element; 00175 $element->set_parent($this); 00176 } 00177 00178 public function add_optigroup($optigroup) { 00179 if (!($optigroup instanceof base_optigroup)) { // parameter must be a base_optigroup 00180 if (!$found = get_class($optigroup)) { 00181 $found = 'non object'; 00182 } 00183 throw new base_element_struct_exception('optigroupincorrect', $found); 00184 } 00185 if ($this->optigroup !== null) { 00186 throw new base_element_struct_exception('optigroupalreadyset', $found); 00187 } 00188 $this->check_and_set_used($optigroup); 00189 $this->optigroup = $optigroup; 00190 $optigroup->set_parent($this); 00191 } 00192 00193 public function get_value() { 00194 throw new base_element_struct_exception('nestedelementnotvalue'); 00195 } 00196 00197 public function set_value($value) { 00198 throw new base_element_struct_exception('nestedelementnotvalue'); 00199 } 00200 00201 public function clean_value() { 00202 throw new base_element_struct_exception('nestedelementnotvalue'); 00203 } 00204 00205 public function clean_values() { 00206 parent::clean_values(); 00207 if (!empty($this->final_elements)) { 00208 foreach ($this->final_elements as $final_element) { 00209 $final_element->clean_values(); 00210 } 00211 } 00212 if (!empty($this->children)) { 00213 foreach ($this->children as $child) { 00214 $child->clean_values(); 00215 } 00216 } 00217 if (!empty($this->optigroup)) { 00218 $this->optigroup->clean_values(); 00219 } 00220 } 00221 00222 public function to_string($showvalue = false) { 00223 $output = parent::to_string($showvalue); 00224 if (!empty($this->final_elements)) { 00225 foreach ($this->final_elements as $final_element) { 00226 $output .= PHP_EOL . $final_element->to_string($showvalue); 00227 } 00228 } 00229 if (!empty($this->children)) { 00230 foreach ($this->children as $child) { 00231 $output .= PHP_EOL . $child->to_string($showvalue); 00232 } 00233 } 00234 if (!empty($this->optigroup)) { 00235 $output .= PHP_EOL . $this->optigroup->to_string($showvalue); 00236 } 00237 return $output; 00238 } 00239 00240 // Implementable API 00241 00246 abstract protected function get_new_final_element($name); 00247 } 00248 00256 class base_element_struct_exception extends base_atom_exception { 00257 00265 public function __construct($errorcode, $a = null, $debuginfo = null) { 00266 parent::__construct($errorcode, $a, $debuginfo); 00267 } 00268 }