00001 <?php
00002
00051 class TSDRelation extends TSDObject {
00052 public static $ATTRIBUTES = array(
00053 'id' => false,
00054 'sourceId' => 'edit',
00055 'destId' => 'edit',
00056 'description' => 'edit',
00057 'version' => false,
00058 'status' => false
00059 );
00060
00080 public function __construct($sourceId = '', $destId = '', $version = TSD::VERSION_LIVE) {
00081 parent::__construct('TSDRelation', self::$ATTRIBUTES, 'id', '');
00082
00083 if($version != TSD::VERSION_DEV && $version != TSD::VERSION_LIVE)
00084 $version = TSD::VERSION_LIVE;
00085
00086
00087
00088 $this->setAttr('status', TSD::STATUS_NEW);
00089 $this->setAttr('version', TSD::VERSION_DEV);
00090
00091 if($sourceId != '' && $destId != '' && ctype_digit((string) $sourceId) && ctype_digit((string) $destId)) {
00092 $this->setAttr('sourceId', $sourceId);
00093 $this->setAttr('destId', $destId);
00094 $this->populate($version);
00095 }
00096 }
00097
00109 public function set($field, $value) {
00110 if($this->version == TSD::VERSION_LIVE) {
00111 $this->setError('Live versions are immutable');
00112 return false;
00113 }
00114 if(($field == 'sourceId' || $field == 'destId') && $this->inDB) {
00115 $this->setError('You cannot change the source and dest IDs when the relationship is already in the database');
00116 return false;
00117 }
00118 return parent::set($field, $value);
00119 }
00120
00132 protected function populate($version) {
00133 if(!$this->checkInit('Cannot populate')) return false;
00134
00135 $sourceId = mysql_escape_string($this->sourceId);
00136 $destId = mysql_escape_string($this->destId);
00137
00138 $query = 'SELECT id, sourceId, destId, description, version, status FROM TSDRelation '
00139 . "WHERE sourceId = '$sourceId' AND destId = '$destId' AND version = '$version'";
00140 $result = $this->DBI->query($query);
00141 if(count($this->DBI->getError()) > 0) {
00142 $this->setError('Failed to populate: ' . implode('; ', $this->DBI->getError()));
00143 return false;
00144 }
00145
00146 if($version == TSD::VERSION_DEV && count($result) == 0) {
00147 $query = 'SELECT id, sourceId, destId, description FROM TSDRelation WHERE sourceId = '
00148 . $sourceId . ' AND destId = ' . $destId . ' AND version = \'LIVE\'';
00149 $result = $this->DBI->query($query);
00150 if(count($this->DBI->getError()) > 0) {
00151 $this->setError('Failed to populate: ' . implode('; ', $this->DBI->getError()));
00152 return false;
00153 }
00154 if(count($result) > 0) {
00155 $this->setAttr('sourceId', $result[0]['sourceId']);
00156 $this->setAttr('destId', $result[0]['destId']);
00157 $this->setAttr('description', $result[0]['description']);
00158 $this->setAttr('version', TSD::VERSION_DEV);
00159 $this->setAttr('status', TSD::STATUS_APPROVED);
00160 $this->setAttr('id', '');
00161 $this->inDB = false;
00162 }
00163 }
00164 else if(count($result) > 0) {
00165 $this->setAttr('id', $result[0]['id']);
00166 $this->setAttr('sourceId', $result[0]['sourceId']);
00167 $this->setAttr('destId', $result[0]['destId']);
00168 $this->setAttr('description', $result[0]['description']);
00169 $this->setAttr('version', $result[0]['version']);
00170 $this->setAttr('status', $result[0]['status']);
00171 $this->inDB = true;
00172 }
00173 else {
00174 $this->setAttr('version', TSD::VERSION_DEV);
00175 $this->setAttr('status', TSD::STATUS_NEW);
00176 $this->inDB = false;
00177 }
00178 }
00179
00192 public function commit() {
00193 if(!$this->checkInit('Cannot commit')) return false;
00194 if(!TSD::can('align')) {
00195 $this->setError('Permission denied');
00196 return false;
00197 }
00198 if(!$this->isValid()) {
00199 $this->setError('Cannot commit invalid object');
00200 return false;
00201 }
00202 if($this->version != TSD::VERSION_DEV) {
00203 $this->setError('Cannot commit live versions');
00204 return false;
00205 }
00206
00207 if($this->status == TSD::STATUS_APPROVED)
00208 $this->setAttr('status', TSD::STATUS_CHANGED);
00209
00210 if($this->inDB) {
00211 $query = 'UPDATE TSDRelation SET ';
00212 foreach($this->attributes as $a => $v) {
00213 $v = mysql_escape_string($v);
00214 $query .= " $a = '$v',";
00215 }
00216 $query = rtrim($query, ',');
00217 $query .= ' WHERE id = \'' . $this->id . '\'';
00218 }
00219 else {
00220 $query = 'INSERT INTO TSDRelation SET ';
00221 foreach($this->attributes as $a => $v) {
00222 if($a == 'id' && $v == '')
00223 continue;
00224 $v = mysql_escape_string($v);
00225 $query .= " $a = '$v',";
00226 }
00227 $query = rtrim($query, ',');
00228 }
00229
00230 $this->DBI->query($query);
00231 if(count($this->DBI->getError()) > 0) {
00232 $this->setError('Failed to commit because of database error(s): ' . implode('; ', $this->DBI->getError()));
00233 return false;
00234 }
00235
00236 if($this->id == '') {
00237 $this->setAttr('id', $this->DBI->mysql_insert_id());
00238 }
00239
00240 $this->inDB = true;
00241
00242 return true;
00243 }
00244
00255 public function approve() {
00256 if(!$this->checkInit('Cannot approve')) return false;
00257 if(!TSD::can('approve')) {
00258 $this->setError('Permission denied');
00259 return false;
00260 }
00261 if(!$this->isValid()) {
00262 $this->setError('Cannot approve invalid object!');
00263 return false;
00264 }
00265
00266
00267 if($this->version == TSD::VERSION_LIVE || $this->status == TSD::STATUS_APPROVED)
00268 return true;
00269
00270 switch($this->status) {
00271 case TSD::STATUS_DELETED:
00272 $query = 'DELETE FROM TSDRelation WHERE sourceId = ' . $this->sourceId . ' AND destId = ' . $this->destId;
00273 break;
00274 case TSD::STATUS_CHANGED:
00275 $query = 'UPDATE TSDRelation SET description = \'' . mysql_escape_string($this->description)
00276 . '\' WHERE sourceId = ' . $this->sourceId . ' AND destId = ' . $this->destId;
00277 break;
00278 case TSD::STATUS_NEW:
00279 $query = 'INSERT INTO TSDRelation (sourceId, destId, description, version, status) VALUES ('
00280 . $this->sourceId . ', ' . $this->destId . ', \'' . mysql_escape_string($this->description)
00281 . '\', \'LIVE\', \'APPROVED\')';
00282 break;
00283 }
00284
00285 $this->DBI->query($query);
00286 if(count($this->DBI->getError()) > 0) {
00287 $this->setError('Failed to approve because of database error(s): ' . implode('; ', $this->DBI->getError()));
00288 return false;
00289 }
00290
00291 if($this->status != TSD::STATUS_DELETED) {
00292 $query = 'UPDATE TSDRelation SET status = \'APPROVED\' WHERE sourceId = ' . $this->sourceId
00293 . ' AND destId = ' . $this->destId;
00294 $this->DBI->query($query);
00295 if(count($this->DBI->getError()) > 0) {
00296 $this->setError('Failed to approve because of database error(s): ' . implode('; ', $this->DBI->getError()));
00297 return false;
00298 }
00299 $this->setAttr('status', TSD::STATUS_APPROVED);
00300 }
00301 else {
00302 $this->inDB = false;
00303 $this->setAttr('id', null);
00304 $this->setAttr('sourceId', null);
00305 $this->setAttr('destId', null);
00306 $this->setAttr('description', null);
00307 $this->setAttr('version', null);
00308 $this->setAttr('status', null);
00309 }
00310
00311 return true;
00312 }
00313
00325 public function cancel() {
00326 if(!$this->checkInit('Cannot cancel')) return false;
00327 if(!TSD::can('approve')) {
00328 $this->setError('Permission denied');
00329 return false;
00330 }
00331 if(!$this->isValid()) {
00332 $this->setError('Cannot cancel invalid object!');
00333 return false;
00334 }
00335
00336
00337 $query = 'SELECT sourceId, destId, description, version, status FROM TSDRelation WHERE sourceId = '
00338 . $this->sourceId . ' AND destId = ' . $this->destId . ' AND version = \'LIVE\'';
00339 $results = $this->DBI->query($query);
00340 if(count($this->DBI->getError()) > 0) {
00341 $this->setError('Failed to cancel because of database error(s): ' . implode('; ', $this->DBI->getError()));
00342 return false;
00343 }
00344
00345 if(count($results) == 0) {
00346
00347 $query = 'DELETE FROM TSDRelation WHERE sourceId = ' . $this->sourceId . ' AND destId = ' . $this->destId;
00348 $this->DBI->query($query);
00349 if(count($this->DBI->getError()) > 0) {
00350 $this->setError('Failed to cancel because of database error(s): ' . implode('; ', $this->DBI->getError()));
00351 return false;
00352 }
00353 $this->setAttr('id', null);
00354 $this->setAttr('sourceId', null);
00355 $this->setAttr('destId', null);
00356 $this->setAttr('description', null);
00357 $this->setAttr('version', null);
00358 $this->setAttr('status', null);
00359 $this->inDB = false;
00360 }
00361 else {
00362
00363 $query = 'UPDATE TSDRelation SET description = \'' . mysql_escape_string($results[0]['description'])
00364 . '\', status = \'APPROVED\' WHERE sourceId = ' . $this->sourceId . ' AND destId = ' . $this->destId
00365 . ' AND version = \'DEV\'';
00366 $this->DBI->query($query);
00367 if(count($this->DBI->getError()) > 0) {
00368 $this->setError('Failed to cancel because of database error(s): ' . implode('; ', $this->DBI->getError()));
00369 return false;
00370 }
00371 $this->setAttr('description', $results[0]['description']);
00372 $this->setAttr('status', TSD::STATUS_APPROVED);
00373 }
00374
00375 return true;
00376 }
00377
00386 public function delete() {
00387 if(!$this->checkInit('Cannot delete')) return false;
00388 if(!TSD::can('align')) {
00389 $this->setError('Permission denied');
00390 return false;
00391 }
00392 if(!$this->isValid()) {
00393 $this->setError('Cannot delete invalid object!');
00394 return false;
00395 }
00396
00397 if($this->status == 'NEW')
00398 $query = 'DELETE FROM TSDRelation WHERE sourceId = ' . $this->sourceId . ' AND destId = '
00399 . $this->destId . ' AND version = \'DEV\'';
00400 else
00401 $query = 'UPDATE TSDRelation SET status = \'DELETED\' WHERE sourceId = ' . $this->sourceId . ' AND destId = '
00402 . $this->destId . ' AND version = \'DEV\'';
00403
00404 $this->DBI->query($query);
00405 if(count($this->DBI->getError()) > 0) {
00406 $this->setError('Failed to delete because of database error(s): ' . implode('; ', $this->DBI->getError()));
00407 return false;
00408 }
00409
00410 if($this->status == 'NEW') {
00411 $this->setAttr('id', null);
00412 $this->setAttr('sourceId', null);
00413 $this->setAttr('destId', null);
00414 $this->setAttr('description', null);
00415 $this->setAttr('version', null);
00416 $this->setAttr('status', null);
00417 $this->inDB = false;
00418 }
00419 else
00420 $this->setAttr('status', TSD::STATUS_DELETED);
00421
00422 return true;
00423 }
00424
00440 public function isValid() {
00441 $okay = true;
00442 if($this->id != '' && $this->id <= 0) {
00443 $this->setError("'id' is invalid (must be numeric and greater than zero, or null)");
00444 $okay = false;
00445 }
00446 if(!ctype_digit((string) $this->sourceId) || $this->sourceId <= 0) {
00447 $this->setError("'sourceId' is invalid (must be numeric and greater than zero)");
00448 $okay = false;
00449 }
00450 if(!ctype_digit((string) $this->destId) || $this->destId <= 0) {
00451 $this->setError("'destId' is invalid (must be numeric and greater than zero)");
00452 $okay = false;
00453 }
00454 if($this->sourceId >= $this->destId) {
00455 $this->setError("'sourceId' must be strictly less than 'destId'");
00456 $okay = false;
00457 }
00458 if($this->version != TSD::VERSION_DEV && $this->version != TSD::VERSION_LIVE) {
00459 $this->setError("'version' must either be TSD::VERSION_DEV or TSD::VERSION_LIVE");
00460 $okay = false;
00461 }
00462 if($this->status != TSD::STATUS_APPROVED && $this->status != TSD::STATUS_DELETED
00463 && $this->status != TSD::STATUS_NEW && $this->status != TSD::STATUS_CHANGED)
00464 {
00465 $this->setError("'status' must be one of the TSD::STATUS_* values");
00466 $okay = false;
00467 }
00468 if($this->status != TSD::STATUS_APPROVED && $this->version == TSD::VERSION_LIVE) {
00469 $this->setError("Live versions cannot have a status other than TSD::STATUS_APPROVED");
00470 $okay = false;
00471 }
00472 return $okay;
00473 }
00474
00489 public static function getList($constraints = array(), $limit = array(), $order = array(), $cnt = false) {
00490 return self::getListImpl('TSDRelation', 'TSDRelation', array_keys(self::$ATTRIBUTES), $constraints,
00491 array(), $limit, $order, $cnt);
00492 }
00493
00508 public static function getRelated($itemUrlOrId, $mode = TSD::MODE_LIVE, $cnt = false, $limit = array(),
00509 $order = array())
00510 {
00511 $limitStr = TSDObject::limitToString($limit);
00512 if($limitStr === false)
00513 return null;
00514 $orderStr = TSDObject::orderToString($order);
00515 if($orderStr === false)
00516 return null;
00517
00518 $itemId = self::getCWISID($itemUrlOrId);
00519 if($cnt)
00520 $query = "SELECT COUNT(*) FROM TSDRelation WHERE sourceId = '$itemId' OR destId = '$itemId' ";
00521 else
00522 $query = "SELECT TSDRelation.sourceId, TSDRelation.destId, TSDRelation.version, TSDRelation.status, "
00523 . "TSDRelation.description FROM TSDRelation " . $limitStr
00524 . " WHERE (sourceId = '$itemId' OR destId = '$itemId') ";
00525
00526 switch($mode) {
00527 case TSD::MODE_LIVE:
00528 $query .= ' AND version = \'LIVE\'';
00529 break;
00530 case TSD::MODE_DEV:
00531 $query .= ' AND version = \'DEV\'';
00532 break;
00533 case TSD::MODE_DEV_ACTIVE:
00534 $query .= ' AND version = \'DEV\' AND status <> \'DELETED\'';
00535 break;
00536 case TSD::MODE_DEV_UNAPPROVED:
00537 $query .= ' AND version = \'DEV\' AND status <> \'APPROVED\'';
00538 break;
00539 case TSD::MODE_NEW:
00540 $query .= ' AND version = \'DEV\' AND status = \'NEW\'';
00541 break;
00542 case TSD::MODE_CHANGED:
00543 $query .= ' AND version = \'DEV\' AND status = \'CHANGED\'';
00544 break;
00545 case TSD::MODE_DELETED:
00546 $query .= ' AND version = \'DEV\' AND status = \'DELETED\'';
00547 break;
00548 case TSD::MODE_APPROVED:
00549 $query .= ' AND version = \'DEV\' AND status = \'APPROVED\'';
00550 break;
00551 case TSD::MODE_ALL:
00552 $query .= '';
00553 break;
00554 }
00555 if($orderStr == '')
00556 $query .= ' ORDER BY version ASC, status ASC, sourceId ASC, destId ASC';
00557 else
00558 $query .= $orderStr;
00559
00560 $result = TSD::getDBI()->query($query);
00561 if(count(TSD::getDBI()->getError()) > 0) {
00562 self::setStaticError('DB error(s): ' . implode('; ', TSD::getDBI()->getError()));
00563 return null;
00564 }
00565
00566 $out = array();
00567 foreach($result as $r) {
00568 $rel = new TSDRelation;
00569 $rel->setAttr('sourceId', $r['sourceId']);
00570 $rel->setAttr('destId', $r['destId']);
00571 $rel->setAttr('description', $r['description']);
00572 $rel->setAttr('version', $r['version']);
00573 $rel->setAttr('status', $r['status']);
00574
00575 $out[] = $rel;
00576 }
00577
00578 return $out;
00579 }
00580
00586 public function getParent() {
00587 return null;
00588 }
00589
00599 public function getIdentifier() {
00600 return "($this->sourceId, $this->destId)";
00601 }
00602
00612 public function listChildren($constraints = array(), $limit = array(), $order = array(), $cnt = false) {
00613 return null;
00614 }
00615
00625 public function listValidChildren($constraints = array(), $limit = array(), $order = array(), $cnt = false) {
00626 return null;
00627 }
00628 }
00629
00630 ?>