1<?php 2/* 3 * $Id$ 4 * 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 6 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 7 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 8 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 9 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 10 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 11 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 12 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 13 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 14 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 15 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 * 17 * This software consists of voluntary contributions made by many individuals 18 * and is licensed under the LGPL. For more information, see 19 * <http://www.doctrine-project.org>. 20 */ 21 22/** 23 * Doctrine_Configurable 24 * the base for Doctrine_Table, Doctrine_Manager and Doctrine_Connection 25 * 26 * @package Doctrine 27 * @subpackage Configurable 28 * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 29 * @link www.doctrine-project.org 30 * @since 1.0 31 * @version $Revision$ 32 * @author Konsta Vesterinen <kvesteri@cc.hut.fi> 33 */ 34abstract class Doctrine_Configurable extends Doctrine_Locator_Injectable 35{ 36 /** 37 * @var array $attributes an array of containing all attributes 38 */ 39 protected $attributes = array(); 40 41 /** 42 * @var Doctrine_Configurable $parent the parent of this component 43 */ 44 protected $parent; 45 46 /** 47 * @var array $_impl an array containing concrete implementations for class templates 48 * keys as template names and values as names of the concrete 49 * implementation classes 50 */ 51 protected $_impl = array(); 52 53 /** 54 * @var array $_params an array of user defined parameters 55 */ 56 protected $_params = array(); 57 58 /** 59 * setAttribute 60 * sets a given attribute 61 * 62 * <code> 63 * $manager->setAttribute(Doctrine_Core::ATTR_PORTABILITY, Doctrine_Core::PORTABILITY_ALL); 64 * </code> 65 * 66 * @param mixed $attribute either a Doctrine_Core::ATTR_* integer constant or a string 67 * corresponding to a constant 68 * @param mixed $value the value of the attribute 69 * @see Doctrine_Core::ATTR_* constants 70 * @throws Doctrine_Exception if the value is invalid 71 * @return void 72 */ 73 public function setAttribute($attribute, $value) 74 { 75 switch ($attribute) { 76 case Doctrine_Core::ATTR_LISTENER: 77 $this->setEventListener($value); 78 break; 79 case Doctrine_Core::ATTR_COLL_KEY: 80 if ( ! ($this instanceof Doctrine_Table)) { 81 throw new Doctrine_Exception("This attribute can only be set at table level."); 82 } 83 if ($value !== null && ! $this->hasField($value)) { 84 throw new Doctrine_Exception("Couldn't set collection key attribute. No such field '$value'."); 85 } 86 break; 87 case Doctrine_Core::ATTR_CACHE: 88 case Doctrine_Core::ATTR_RESULT_CACHE: 89 case Doctrine_Core::ATTR_QUERY_CACHE: 90 case Doctrine_Core::ATTR_TABLE_CACHE: 91 if ($value !== null) { 92 if ( ! ($value instanceof Doctrine_Cache_Interface)) { 93 throw new Doctrine_Exception('Cache driver should implement Doctrine_Cache_Interface'); 94 } 95 } 96 break; 97 case Doctrine_Core::ATTR_SEQCOL_NAME: 98 if ( ! is_string($value)) { 99 throw new Doctrine_Exception('Sequence column name attribute only accepts string values'); 100 } 101 break; 102 case Doctrine_Core::ATTR_FIELD_CASE: 103 if ($value != 0 && $value != CASE_LOWER && $value != CASE_UPPER) 104 throw new Doctrine_Exception('Field case attribute should be either 0, CASE_LOWER or CASE_UPPER constant.'); 105 break; 106 case Doctrine_Core::ATTR_SEQNAME_FORMAT: 107 case Doctrine_Core::ATTR_IDXNAME_FORMAT: 108 case Doctrine_Core::ATTR_TBLNAME_FORMAT: 109 case Doctrine_Core::ATTR_FKNAME_FORMAT: 110 if ($this instanceof Doctrine_Table) { 111 throw new Doctrine_Exception('Sequence / index name format attributes cannot be set' 112 . 'at table level (only at connection or global level).'); 113 } 114 break; 115 } 116 117 $this->attributes[$attribute] = $value; 118 } 119 120 public function getParams($namespace = null) 121 { 122 if ($namespace == null) { 123 $namespace = $this->getAttribute(Doctrine_Core::ATTR_DEFAULT_PARAM_NAMESPACE); 124 } 125 126 if ( ! isset($this->_params[$namespace])) { 127 return null; 128 } 129 130 return $this->_params[$namespace]; 131 } 132 133 public function getParamNamespaces() 134 { 135 return array_keys($this->_params); 136 } 137 138 public function setParam($name, $value, $namespace = null) 139 { 140 if ($namespace == null) { 141 $namespace = $this->getAttribute(Doctrine_Core::ATTR_DEFAULT_PARAM_NAMESPACE); 142 } 143 144 $this->_params[$namespace][$name] = $value; 145 146 return $this; 147 } 148 149 public function getParam($name, $namespace = null) 150 { 151 if ($namespace == null) { 152 $namespace = $this->getAttribute(Doctrine_Core::ATTR_DEFAULT_PARAM_NAMESPACE); 153 } 154 155 if ( ! isset($this->_params[$namespace][$name])) { 156 if (isset($this->parent)) { 157 return $this->parent->getParam($name, $namespace); 158 } 159 return null; 160 } 161 162 return $this->_params[$namespace][$name]; 163 } 164 165 /** 166 * setImpl 167 * binds given class to given template name 168 * 169 * this method is the base of Doctrine dependency injection 170 * 171 * @param string $template name of the class template 172 * @param string $class name of the class to be bound 173 * @return Doctrine_Configurable this object 174 */ 175 public function setImpl($template, $class) 176 { 177 $this->_impl[$template] = $class; 178 179 return $this; 180 } 181 182 /** 183 * getImpl 184 * returns the implementation for given class 185 * 186 * @return string name of the concrete implementation 187 */ 188 public function getImpl($template) 189 { 190 if ( ! isset($this->_impl[$template])) { 191 if (isset($this->parent)) { 192 return $this->parent->getImpl($template); 193 } 194 return null; 195 } 196 return $this->_impl[$template]; 197 } 198 199 200 public function hasImpl($template) 201 { 202 if ( ! isset($this->_impl[$template])) { 203 if (isset($this->parent)) { 204 return $this->parent->hasImpl($template); 205 } 206 return false; 207 } 208 return true; 209 } 210 211 /** 212 * @param Doctrine_EventListener $listener 213 * @return void 214 */ 215 public function setEventListener($listener) 216 { 217 return $this->setListener($listener); 218 } 219 220 /** 221 * addRecordListener 222 * 223 * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener 224 * @return Doctrine_Configurable this object 225 */ 226 public function addRecordListener($listener, $name = null) 227 { 228 if ( ! isset($this->attributes[Doctrine_Core::ATTR_RECORD_LISTENER]) || 229 ! ($this->attributes[Doctrine_Core::ATTR_RECORD_LISTENER] instanceof Doctrine_Record_Listener_Chain)) { 230 231 $this->attributes[Doctrine_Core::ATTR_RECORD_LISTENER] = new Doctrine_Record_Listener_Chain(); 232 } 233 $this->attributes[Doctrine_Core::ATTR_RECORD_LISTENER]->add($listener, $name); 234 235 return $this; 236 } 237 238 /** 239 * getListener 240 * 241 * @return Doctrine_EventListener_Interface|Doctrine_Overloadable 242 */ 243 public function getRecordListener() 244 { 245 if ( ! isset($this->attributes[Doctrine_Core::ATTR_RECORD_LISTENER])) { 246 if (isset($this->parent)) { 247 return $this->parent->getRecordListener(); 248 } 249 return null; 250 } 251 return $this->attributes[Doctrine_Core::ATTR_RECORD_LISTENER]; 252 } 253 254 /** 255 * setListener 256 * 257 * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener 258 * @return Doctrine_Configurable this object 259 */ 260 public function setRecordListener($listener) 261 { 262 if ( ! ($listener instanceof Doctrine_Record_Listener_Interface) 263 && ! ($listener instanceof Doctrine_Overloadable) 264 ) { 265 throw new Doctrine_Exception("Couldn't set eventlistener. Record listeners should implement either Doctrine_Record_Listener_Interface or Doctrine_Overloadable"); 266 } 267 $this->attributes[Doctrine_Core::ATTR_RECORD_LISTENER] = $listener; 268 269 return $this; 270 } 271 272 /** 273 * addListener 274 * 275 * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener 276 * @return Doctrine_Configurable this object 277 */ 278 public function addListener($listener, $name = null) 279 { 280 if ( ! isset($this->attributes[Doctrine_Core::ATTR_LISTENER]) || 281 ! ($this->attributes[Doctrine_Core::ATTR_LISTENER] instanceof Doctrine_EventListener_Chain)) { 282 283 $this->attributes[Doctrine_Core::ATTR_LISTENER] = new Doctrine_EventListener_Chain(); 284 } 285 $this->attributes[Doctrine_Core::ATTR_LISTENER]->add($listener, $name); 286 287 return $this; 288 } 289 290 /** 291 * getListener 292 * 293 * @return Doctrine_EventListener_Interface|Doctrine_Overloadable 294 */ 295 public function getListener() 296 { 297 if ( ! isset($this->attributes[Doctrine_Core::ATTR_LISTENER])) { 298 if (isset($this->parent)) { 299 return $this->parent->getListener(); 300 } 301 return null; 302 } 303 return $this->attributes[Doctrine_Core::ATTR_LISTENER]; 304 } 305 306 /** 307 * setListener 308 * 309 * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener 310 * @return Doctrine_Configurable this object 311 */ 312 public function setListener($listener) 313 { 314 if ( ! ($listener instanceof Doctrine_EventListener_Interface) 315 && ! ($listener instanceof Doctrine_Overloadable) 316 ) { 317 throw new Doctrine_EventListener_Exception("Couldn't set eventlistener. EventListeners should implement either Doctrine_EventListener_Interface or Doctrine_Overloadable"); 318 } 319 $this->attributes[Doctrine_Core::ATTR_LISTENER] = $listener; 320 321 return $this; 322 } 323 324 /** 325 * returns the value of an attribute 326 * 327 * @param integer $attribute 328 * @return mixed 329 */ 330 public function getAttribute($attribute) 331 { 332 if (isset($this->attributes[$attribute])) { 333 return $this->attributes[$attribute]; 334 } 335 336 if (isset($this->parent)) { 337 return $this->parent->getAttribute($attribute); 338 } 339 return null; 340 } 341 342 /** 343 * Unset an attribute from this levels attributes 344 * 345 * @param integer $attribute 346 * @return void 347 */ 348 public function unsetAttribute($attribute) 349 { 350 if (isset($this->attributes[$attribute])) { 351 unset($this->attributes[$attribute]); 352 } 353 } 354 355 /** 356 * getAttributes 357 * returns all attributes as an array 358 * 359 * @return array 360 */ 361 public function getAttributes() 362 { 363 return $this->attributes; 364 } 365 366 /** 367 * Set the charset 368 * 369 * @param string $charset 370 */ 371 public function setCharset($charset) 372 { 373 $this->setAttribute(Doctrine_Core::ATTR_DEFAULT_TABLE_CHARSET, $charset); 374 } 375 376 /** 377 * Get the charset 378 * 379 * @return mixed 380 */ 381 public function getCharset() 382 { 383 return $this->getAttribute(Doctrine_Core::ATTR_DEFAULT_TABLE_CHARSET); 384 } 385 386 /** 387 * Set the collate 388 * 389 * @param string $collate 390 */ 391 public function setCollate($collate) 392 { 393 $this->setAttribute(Doctrine_Core::ATTR_DEFAULT_TABLE_COLLATE, $collate); 394 } 395 396 /** 397 * Get the collate 398 * 399 * @return mixed $collate 400 */ 401 public function getCollate() 402 { 403 return $this->getAttribute(Doctrine_Core::ATTR_DEFAULT_TABLE_COLLATE); 404 } 405 406 /** 407 * sets a parent for this configurable component 408 * the parent must be configurable component itself 409 * 410 * @param Doctrine_Configurable $component 411 * @return void 412 */ 413 public function setParent(Doctrine_Configurable $component) 414 { 415 $this->parent = $component; 416 } 417 418 /** 419 * getParent 420 * returns the parent of this component 421 * 422 * @return Doctrine_Configurable 423 */ 424 public function getParent() 425 { 426 return $this->parent; 427 } 428} 429