00001 <?php
00002
00012 abstract class SnapObject extends SObject {
00013
00014 private $values = array();
00015
00016 private $valuesLoaded = array();
00017
00018 private $loaders = array();
00019
00020 private $save = array();
00021
00022 private $attributes;
00023
00024 private $type;
00025
00026
00027 private $reason = '';
00028
00029
00030 private $valid = true;
00031
00035 public $__FOR_CACHE = null;
00036
00051 public function __construct($type, $fields, $attributes) {
00052 parent::__construct();
00053
00054 foreach($fields as $f => $callback) {
00055 $this->values[$f] = "";
00056 $this->valuesLoaded[$f] = false;
00057 if(is_callable($callback, true))
00058 $this->loaders[$f] = $callback;
00059 else
00060 $this->loaders[$f] = array($this, 'populate');
00061 $this->save[$f] = true;
00062 }
00063 $this->type = $type;
00064 $this->attributes = $attributes;
00065 }
00066
00076 protected function get($field) {
00077
00078 if(!$this->valuesLoaded[$field]) {
00079 if(!call_user_func($this->loaders[$field]))
00080 return null;
00081 }
00082 return $this->values[$field];
00083 }
00084
00096 protected function set($field, $value) {
00097
00098
00099
00100
00101
00102
00103
00104 $this->values[$field] = $value;
00105 $this->valuesLoaded[$field] = true;
00106 return true;
00107 }
00108
00121 protected function setSave($field, $save) {
00122 if(!$this->checkValid()) return false;
00123 if(!array_key_exists($field, $this->values)) {
00124 $this->setError("No such field '$field'");
00125 return false;
00126 }
00127 $this->save[$field] = $save;
00128 }
00129
00141 protected function unsetField($field) {
00142 if(!$this->checkValid()) return false;
00143 if(!array_key_exists($field, $this->values)) {
00144 $this->setError("No such field '$field'");
00145 return false;
00146 }
00147 $this->values[$field] = null;
00148 $this->valuesLoaded[$field] = false;
00149 return true;
00150 }
00151
00165 protected function setValid($valid) {
00166 $this->valid = $valid;
00167 if($valid == false) {
00168 $this->values = array();
00169 $this->valuesLoaded = array();
00170 $this->type = '';
00171 $this->attributes = array();
00172 }
00173 }
00174
00182 public function isValid() {
00183 return $this->valid;
00184 }
00185
00195 protected function checkValid($operation = "") {
00196 if(!$this->valid) {
00197 $this->setError('Cannot perform operation on invalid object' .
00198 ($operation != '' ? ': ' . $operation : ''));
00199 return false;
00200 }
00201 return true;
00202 }
00203
00213 public function __call($name, $args) {
00214 if(substr($name, 0, 3) == 'get') {
00215 if(!$this->checkValid()) return false;
00216 $field = strtolower(substr($name, 3, 1)) . substr($name, 4);
00217 if(!array_key_exists($field, $this->values)) {
00218 $this->setError("No such field '$field'");
00219 return null;
00220 }
00221
00222
00223 if(!$this->valuesLoaded[$field]) {
00224 if(!call_user_func($this->loaders[$field]))
00225 return null;
00226 }
00227
00228 return $this->values[$field];
00229 }
00230
00231 $this->setError("Invalid dynamic function call '$name()'");
00232 return false;
00233 }
00234
00241 public function isLoaded($field) {
00242 if(!$this->checkValid()) return false;
00243 if(!isset($this->valuesLoaded[$field])) {
00244 $this->setError("No such field '$field'");
00245 return false;
00246 }
00247 return $this->valuesLoaded[$field];
00248 }
00249
00254 public function getType() {
00255 if(!$this->checkValid()) return false;
00256 return $this->type;
00257 }
00258
00269 public function getId() {
00270
00271 if(!$this->checkValid()) return false;
00272 return $this->values['id'];
00273 }
00274
00283 public function getValues() {
00284 if(!$this->checkValid()) return false;
00285 return $this->values;
00286 }
00287
00293 public function getFields() {
00294 if(!$this->checkValid()) return false;
00295 return array_keys($this->values);
00296 }
00297
00306 public function getAttributes() {
00307 if(!$this->checkValid()) return false;
00308 return $this->attributes;
00309 }
00310
00321 protected abstract function populate();
00322
00334 protected function setReason($msg) {
00335 $this->reason = $msg;
00336 }
00337
00346 public function getReason() {
00347 return $this->reason;
00348 }
00349
00365 protected static function convertReference($ref, $type) {
00366 if($type != 'Directory' && $type != 'Resource' && $type != 'Version'
00367 && $type != 'File') {
00368 self::setStaticError('Invalid type: \'' . $type . '\'');
00369 return null;
00370 }
00371
00372 if(ctype_digit((string) $ref)) {
00373 if($ref <= 0) {
00374 self::setStaticError('Snap object ID must be a positive integer');
00375 return null;
00376 }
00377 switch($type) {
00378 case 'Directory':
00379 $obj = SnapDirectory::retrieve($ref);
00380 break;
00381 case 'Resource':
00382 $obj = SnapResource::retrieve($ref);
00383 break;
00384 case 'Version':
00385 $obj = SnapVersion::retrieve($ref);
00386 break;
00387 case 'File':
00388 self::setStaticError('Ambiguous ID: must use path or object');
00389 return null;
00390 }
00391 if($obj == null) {
00392 self::setStaticError('No such file or version: \'' . $ref . '\'');
00393 return null;
00394 }
00395 return $obj;
00396 }
00397 else if(is_string($ref)) {
00398 switch($type) {
00399 case 'Directory':
00400 $obj = SnapDirectory::lookup($ref);
00401 break;
00402 case 'Resource':
00403 $obj = SnapResource::lookup($ref);
00404 break;
00405 case 'Version':
00406 $obj = SnapVersion::lookup($ref);
00407 break;
00408 case 'File':
00409 if(substr($ref, -1) == '/')
00410 $obj = SnapDirectory::lookup($ref);
00411 else
00412 $obj = SnapResource::lookup($ref);
00413 break;
00414 }
00415 if($obj == null) {
00416 self::setStaticError('No such file or version: \'' . $ref . '\'');
00417 return null;
00418 }
00419 return $obj;
00420 }
00421 else if(is_object($ref)) {
00422 if($type == 'Directory' && $ref instanceof SnapDirectory)
00423 return $ref;
00424 else if($type == 'Resource' && $ref instanceof SnapResource)
00425 return $ref;
00426 else if($type == 'Version' && $ref instanceof SnapVersion)
00427 return $ref;
00428 else if($type == 'File' && $ref instanceof SnapFile)
00429 return $ref;
00430 else {
00431 self::setStaticError('Reference object is not of correct type');
00432 return null;
00433 }
00434 }
00435
00436 self::setStaticError('Invalid Snap reference');
00437 return null;
00438 }
00439
00446 protected function saveForCache() {
00447 $values = $this->values;
00448 $valuesLoaded = $this->valuesLoaded;
00449 foreach($this->save as $field => $sv)
00450 if(!$sv) {
00451 $values[$field] = null;
00452 $valuesLoaded[$field] = false;
00453 }
00454 return array('values' => $values, 'valuesLoaded' => $valuesLoaded, 'loaders' => $this->loaders,
00455 'attributes' => $this->attributes, 'type' => $this->type, 'valid' => $this->valid,
00456 'save' => $this->save);
00457 }
00458
00463 public function __sleep() {
00464 if($this->__FOR_CACHE == null)
00465 $this->__FOR_CACHE = $this->saveForCache();
00466 return array('__FOR_CACHE');
00467 }
00468
00473 public function __wakeup() {
00474 foreach($this->__FOR_CACHE as $var => $value)
00475 $this->$var = $value;
00476 $this->__FOR_CACHE = null;
00477 }
00478
00483 public function toCacheDump() {
00484 return '';
00485 }
00486
00491 public static function dumpResults($result) {
00492 $html = '<table border="1"><tr>';
00493 foreach($result[0] as $a => $v)
00494 $html .= '<th>' . $a . '</th>';
00495 $html .= '</tr>';
00496 foreach($result as $row) {
00497 $html .= '<tr>';
00498 foreach($row as $a => $v)
00499 $html .= '<td>' . $v . '</td>';
00500 $html .= '</tr>';
00501 }
00502 $html .= '</table>';
00503 return $html;
00504 }
00505 }
00506
00507 ?>