00001 <?php
00002
00047 class SnapVersion extends SnapObject {
00049 const STATUS_PRIVATE = 0;
00051 const STATUS_PENDING = 1;
00053 const STATUS_DEV = 2;
00055 const STATUS_LIVE = 3;
00057 const STATUS_DEFUNCT = 4;
00058
00062 public static $STAT_NAMES = array(
00063 self::STATUS_PRIVATE => 'In Progress',
00064 self::STATUS_PENDING => 'Pending',
00065 self::STATUS_DEV => 'Dev',
00066 self::STATUS_LIVE => 'Live',
00067 self::STATUS_DEFUNCT => 'Defunct'
00068 );
00069
00073 public static $STAT_VALUES = array(
00074 'In Progress' => self::STATUS_PRIVATE,
00075 'Pending' => self::STATUS_PENDING,
00076 'Dev' => self::STATUS_DEV,
00077 'Live' => self::STATUS_LIVE,
00078 'Defunct' => self::STATUS_DEFUNCT
00079 );
00080
00084 public static $ATTRIBUTES = array(
00085 'id', 'created', 'modified', 'author', 'status', 'ordinal', 'content', 'resourceId', 'prevVersionId'
00086 );
00087
00091 public function __construct($id = '') {
00092 $fields = array_merge(array_flip(self::$ATTRIBUTES), array('resource' => array($this, 'loadResource'),
00093 'contentModule' => array($this, 'loadContentModule'),
00094 'prevVersion' => array($this, 'loadPrevVersion')));
00095 parent::__construct('Version', $fields, self::$ATTRIBUTES);
00096 $this->setSave('contentModule', false);
00097 $this->setSave('prevVersion', false);
00098 $this->setSave('resource', false);
00099 if($id != '') {
00100 $this->set('id', $id);
00101 $this->populate();
00102 }
00103 }
00104
00106 public function toCacheDump() {
00107 $resourceId = $this->get('resourceId');
00108 $status = $this->get('status');
00109 return "Resource: $resourceId; status: " . self::$STAT_NAMES[$status];
00110 }
00111
00113 protected function populate() {
00114 if(!$this->checkValid()) return false;
00115
00116 $query = 'SELECT ' . implode(',', self::$ATTRIBUTES) . ' FROM Version '
00117 . 'WHERE id = ' . $this->getId();
00118 if(!SnapDBI::query($query)) {
00119 $this->setError('Could not populate due to database error');
00120 return false;
00121 }
00122
00123 if(SnapDBI::getNumRows() == 0) {
00124 SnapDBI::freeResult();
00125 $this->setValid(false);
00126 return false;
00127 }
00128
00129 if(SnapDBI::getNumRows() > 1)
00130 $this->setWarning('Multiple version objects with the same ID!');
00131
00132 $result = SnapDBI::firstRow();
00133 foreach(self::$ATTRIBUTES as $a)
00134 $this->set($a, $result[$a]);
00135
00136 SnapDBI::freeResult();
00137
00138 $this->setValid(true);
00139 SnapCache::updateById($this->getType(), $this->getId());
00140
00141 return true;
00142 }
00143
00148 protected function loadResource() {
00149 $res = SnapResource::retrieve($this->get('resourceId'));
00150 $this->set('resource', $res);
00151 SnapCache::updateById($this->getType(), $this->getId());
00152 return true;
00153 }
00154
00159 protected function loadContentModule() {
00160 $cm = SnapContent::getContentModule($this);
00161 $this->set('contentModule', $cm);
00162 SnapCache::updateById($this->getType(), $this->getId());
00163 return true;
00164 }
00165
00170 protected function loadPrevVersion() {
00171 $prevId = $this->get('prevVersionId');
00172 if($prevId > 0) {
00173 $v = SnapVersion::retrieve($prevId);
00174 $this->set('prevVersion', $v);
00175 SnapCache::updateById($this->getType(), $this->getId());
00176 }
00177 return true;
00178 }
00179
00184 public function systemDestroy() {
00185 $cm = $this->get('contentModule');
00186 $cm->delete();
00187 $this->set('contentModule', null);
00188 $this->setValid(false);
00189 return true;
00190 }
00191
00197 protected function logAction($action) {
00198 if(!SnapDBI::startTransaction())
00199 return false;
00200
00201 $query = 'INSERT INTO ActionLog (uid, action, versionId) VALUES '
00202 . '(\'' . Snap2::getCurrentUser() . '\',\'' . $action . '\',\'' . $this->getId()
00203 . '\')';
00204 if(!SnapDBI::query($query)) {
00205 $this->setError('Error during query');
00206 SnapDBI::cancelTransaction();
00207 return false;
00208 }
00209
00210 SnapDBI::commitTransaction();
00211
00212 return true;
00213 }
00214
00219 public function __call($name, $args) {
00220 if(substr($name, 0, 3) == 'can') {
00221 if(!method_exists($this, '_' . $name)) {
00222 $this->setError('Invalid dynamic function call: \'' . $name . '\'');
00223 return false;
00224 }
00225 if(!$this->checkValid()) return false;
00226 return call_user_func_array(array($this, '_' . $name), $args) ? true : false;
00227 }
00228 else
00229 return parent::__call($name, $args);
00230 }
00231
00232
00233
00234
00235
00244 public static function retrieve($id) {
00245 if(!Snap2::checkInit()) return null;
00246 if(!ctype_digit((string) $id) || $id <= 0) {
00247 self::setStaticError('ID must be numeric');
00248 return null;
00249 }
00250
00251 $v = SnapCache::getById('Version', $id);
00252 if($v != null)
00253 return $v;
00254 else {
00255 $v = new SnapVersion($id);
00256 $v->populate();
00257 if(!($v->getId() > 0))
00258 return null;
00259 }
00260
00261 SnapCache::putById('Version', $id, $v);
00262
00263 return $v;
00264 }
00265
00274 public static function lookup($path) {
00275 if(!Snap2::checkInit()) return null;
00276
00277 if(!preg_match('/^\s*((\/[a-zA-Z0-9\$\-_.]*)+\@([0-9]+|dev|live|active|latest|pending|private|defunct))\s*$/',
00278 $path, $matches))
00279 {
00280 self::setStaticError('Invalid path: \'' . $path . '\'');
00281 return null;
00282 }
00283
00284 $path = $matches[1];
00285
00286 $v = SnapCache::getByPath('Version', $path);
00287 if($v != null)
00288 return $v;
00289
00290 $vParts = explode('@', $path);
00291 $pathParts = explode('/', $vParts[0]);
00292 $ordinal = $vParts[1];
00293
00294 $attributes = '';
00295 foreach(self::$ATTRIBUTES as $a)
00296 $attributes .= 'Version.'. $a . ',';
00297 $attributes = rtrim($attributes, ',');
00298
00299 $query = 'SELECT ' . $attributes . ' FROM Version LEFT JOIN Resource '
00300 . 'ON Version.resourceId = Resource.id ';
00301 if(ctype_digit((string) $ordinal))
00302 $where = ' WHERE Version.ordinal = ' . $ordinal;
00303 else if($ordinal == 'dev')
00304 $where = ' WHERE Version.status = ' . self::STATUS_DEV;
00305 else if($ordinal == 'live')
00306 $where = ' WHERE Version.status = ' . self::STATUS_LIVE;
00307 else if($ordinal == 'private') {
00308 $where = ' WHERE Version.status = ' . self::STATUS_PRIVATE;
00309 $ignoreMulti = true;
00310 }
00311 else if($ordinal == 'pending') {
00312 $where = ' WHERE Version.status = ' . self::STATUS_PENDING;
00313 $ignoreMulti = true;
00314 }
00315 else if($ordinal == 'defunct') {
00316 $where = ' WHERE Version.status = ' . self::STATUS_DEFUNCT;
00317 $ignoreMulti = true;
00318 }
00319 else if($ordinal == 'latest') {
00320 $where = ' WHERE Version.ordinal = (SELECT MAX(ordinal) FROM Version WHERE resourceId = Resource.id)';
00321 $ignoreMulti = true;
00322 }
00323 else if($ordinal == 'active' && SConfig::getOption('common.SERVER_TYPE') == 'dev')
00324 $where = ' WHERE (Version.status = ' . self::STATUS_DEV . ' OR Version.status = ' . self::STATUS_LIVE . ')';
00325 else if($ordinal == 'active' && SConfig::getOption('common.SERVER_TYPE') == 'prod')
00326 $where = ' WHERE Version.status = ' . self::STATUS_LIVE;
00327 $where .= ' AND ';
00328 for($i = 1, $j = count($pathParts) - 1; $i < count($pathParts); $i++, $j--) {
00329 if($i == 1) $link1 = 'ResourceLink';
00330 else $link1 = 'DirectoryLink';
00331 if($i == 2) $link2 = 'ResourceLink';
00332 else $link2 = 'DirectoryLink';
00333 if($j == 1) $link3 = 'ResourceLink';
00334 else $link3 = 'DirectoryLink';
00335 $query .= ' LEFT JOIN ' . $link1 . ' AS ' . $link1 . $i . ' ON ' . $link1 . $i
00336 . '.childId = ' . ($i == 1 ? 'Resource.id' : ($link2 . ($i - 1) . '.parentId'));
00337 $where .= ' ' . $link3 . $j . '.shortName = BINARY \'' . $pathParts[$i] . '\' AND ';
00338 }
00339 $query .= rtrim($where, ' AND ') . ' ORDER BY status';
00340
00341 $result = SnapDBI::query($query, true);
00342 if($result === false)
00343 return null;
00344
00345 if(count($result) == 0)
00346 return null;
00347 else if(count($result) == 2 && $ordinal == 'active') {
00348 if($result[0]['status'] == $result[1]['status'])
00349 self::setStaticWarning('Multiple active results for path \'' . $path
00350 . '\'! Run snap consistency check please.');
00351 else {
00352 if($result[1]['status'] == SnapVersion::STATUS_DEV)
00353 $result[0] = $result[1];
00354 unset($result[1]);
00355 }
00356 }
00357 else if(count($result) != 1) {
00358 if(isset($ignoreMulti)) {
00359 $newResult = array($result[count($result)-1]);
00360 $result = $newResult;
00361 }
00362 else {
00363 self::setStaticWarning('Multiple results for path \'' . $path
00364 . '\'! Run Snap consistency check please.');
00365 }
00366 }
00367
00368 $v = SnapCache::getById('Version', $result[0]['id']);
00369 if($v != null) {
00370 SnapCache::putByPath('Version', $path, $v);
00371 return $v;
00372 }
00373
00374 $v = new SnapVersion();
00375 foreach(self::$ATTRIBUTES as $a)
00376 $v->set($a, $result[0][$a]);
00377
00378 SnapCache::putByPath('Version', $path, $v);
00379
00380 return $v;
00381 }
00382
00383 /*
00384 * Capability Checks
00385 */
00386
00388 protected function _canSteal() {
00389 if($this->get('status') != self::STATUS_PRIVATE) {
00390 $this->setReason('Cannot steal version that is not In Progress');
00391 return false;
00392 }
00393
00394 if($this->get('author') == Snap2::getCurrentUser()) {
00395 $this->setReason('Cannot steal version that is already your own');
00396 return false;
00397 }
00398
00399 if(!$this->get('resource')->getPermission()->maySteal()) {
00400 $this->setReason('Permission denied');
00401 return false;
00402 }
00403
00404 return true;
00405 }
00406
00408 protected function _canUpdate($newCM = null) {
00409 if($this->get('status') != self::STATUS_PRIVATE) {
00410 $this->setReason('Cannot update version that is not In Progress');
00411 return false;
00412 }
00413
00414 $cl = SnapContent::getContentModuleClass($this);
00415 if($newCM) {
00416 if(!is_object($newCM) || !$newCM instanceof $cl) {
00417 $this->setReason('Invalid content module passed to update():'.
00418 " It's possible there are two or more modules with the same shortName.");
00419 return false;
00420 }
00421
00422 if(!$newCM->isValid()) {
00423 $this->setReason('Invalid content');
00424 return false;
00425 }
00426 }
00427
00428 if(!$this->get('resource')->getPermission()->mayUpdate()) {
00429 $this->setReason('Permission denied');
00430 return false;
00431 }
00432
00433 return true;
00434 }
00435
00437 protected function _canSubmit() {
00438 if($this->get('status') != self::STATUS_PRIVATE) {
00439 $this->setReason('Cannot submit version that is not In Progress');
00440 return false;
00441 }
00442
00443 if(!$this->get('resource')->getPermission()->maySubmit()) {
00444 $this->setReason('Permission denied');
00445 return false;
00446 }
00447
00448 return true;
00449 }
00450
00452 protected function _canApproveForDev() {
00453 if($this->get('status') != self::STATUS_PENDING) {
00454 $this->setReason('Cannot submit version that is not Pending');
00455 return false;
00456 }
00457
00458 if(!$this->get('resource')->getPermission()->mayApproveForDev()) {
00459 $this->setReason('Permission denied');
00460 return false;
00461 }
00462
00463 return true;
00464 }
00465
00467 protected function _canApproveForLive() {
00468 if($this->get('status') != self::STATUS_PENDING
00469 && $this->get('status') != self::STATUS_DEV) {
00470 $this->setReason('Cannot submit version that is not Pending or Dev');
00471 return false;
00472 }
00473
00474 if(!$this->get('resource')->getPermission()->mayApproveForLive()) {
00475 $this->setReason('Permission denied');
00476 return false;
00477 }
00478
00479 return true;
00480 }
00481
00483 protected function _canDefunct() {
00484 if($this->get('status') == self::STATUS_DEFUNCT) {
00485 $this->setReason('Version is already defunct');
00486 return false;
00487 }
00488
00489 if(!$this->get('resource')->getPermission()->mayDefunct($this->get('status'))) {
00490 $this->setReason('Permission denied');
00491 return false;
00492 }
00493
00494 return true;
00495 }
00496
00498 protected function _canDestroy() {
00499 if($this->get('status') != self::STATUS_DEFUNCT) {
00500 $this->setReason('Cannot destroy version that is not Defunct');
00501 return false;
00502 }
00503
00504 if(!$this->get('resource')->getPermission()->mayDestroyVersion()) {
00505 $this->setReason('Permission denied');
00506 return false;
00507 }
00508
00509 return true;
00510 }
00511
00513 protected function _canDeny() {
00514 if($this->get('status') != self::STATUS_PENDING) {
00515 $this->setReason('Cannot deny version that is not Pending');
00516 return false;
00517 }
00518
00519 if(!$this->get('resource')->getPermission()->mayDeny()) {
00520 $this->setReason('Permission denied');
00521 return false;
00522 }
00523
00524 return true;
00525 }
00526
00527 /*
00528 * Public Interface Methods
00529 */
00530
00548 public function update($newCM) {
00549 if(!$this->checkValid()) return false;
00550
00551 if(!SnapDBI::startTransaction())
00552 return false;
00553
00554 if($newCM == null) {
00555 $this->setError('No content module passed to update!');
00556 SnapDBI::cancelTransaction();
00557 return false;
00558 }
00559
00560 if(!$this->_canUpdate($newCM)) {
00561 $this->setError('Failed to update: ' . $this->getReason());
00562 SnapDBI::cancelTransaction();
00563 return false;
00564 }
00565
00566 $oldCM = $this->getContentModule();
00567
00568 $content = mysql_escape_string($newCM->getRaw());
00569 $query = 'UPDATE Version SET content = \'' . $content . '\' WHERE id = ' . $this->getId();
00570 if(!SnapDBI::query($query)) {
00571 $this->setError('Error during query');
00572 SnapDBI::cancelTransaction();
00573 return false;
00574 }
00575 SnapDBI::commitTransaction();
00576
00577 $oldCM->delete();
00578
00579 $this->set('contentModule', $newCM);
00580 $this->set('content', $newCM->getRaw());
00581
00582 $this->logAction('Edit');
00583 SnapCache::updateById($this->getType(), $this->getId());
00584
00585 return true;
00586 }
00587
00595 public function submit() {
00596 if(!$this->checkValid()) return false;
00597
00598 if(!SnapDBI::startTransaction())
00599 return false;
00600
00601 if(!$this->_canSubmit()) {
00602 $this->setError('Failed to submit: ' . $this->getReason());
00603 SnapDBI::cancelTransaction();
00604 return false;
00605 }
00606
00607 $query = 'UPDATE Version SET status = ' . self::STATUS_PENDING . ' WHERE id = ' . $this->getId();
00608 if(!SnapDBI::query($query)) {
00609 $this->setError('Error during query');
00610 SnapDBI::cancelTransaction();
00611 return false;
00612 }
00613
00614 SnapDBI::commitTransaction();
00615
00616 $this->set('status', self::STATUS_PENDING);
00617
00618 $this->logAction('Submit');
00619 SnapCache::updateById($this->getType(), $this->getId());
00620
00621 return true;
00622 }
00623
00632 public function approveForDev() {
00633 if(!$this->checkValid()) return false;
00634
00635 if(!SnapDBI::startTransaction())
00636 return false;
00637
00638 if(!$this->_canApproveForDev()) {
00639 $this->setError('Failed to approve for dev: ' . $this->getReason());
00640 SnapDBI::cancelTransaction();
00641 return false;
00642 }
00643
00644 $res = $this->get('resource');
00645
00646 // 1) Set old dev version to defunct
00647 if($res->get('devVersionId') > 0) {
00648 $query = 'UPDATE Version SET status = ' . self::STATUS_DEFUNCT . ' WHERE id = ' . $res->get('devVersionId');
00649 if(!SnapDBI::query($query)) {
00650 $this->setError('Error updating old dev version');
00651 SnapDBI::cancelTransaction();
00652 return false;
00653 }
00654 }
00655
00656 // 2) Set this version to dev
00657 $query = 'UPDATE Version SET status = ' . self::STATUS_DEV . ' WHERE id = ' . $this->getId();
00658 if(!SnapDBI::query($query)) {
00659 $this->setError('Error during query');
00660 SnapDBI::cancelTransaction();
00661 return false;
00662 }
00663
00664 // 3) Set resource's devVersionId to this
00665 $query = 'UPDATE Resource SET devVersionId = ' . $this->getId() . ' WHERE id = ' . $this->get('resourceId');
00666 if(!SnapDBI::query($query)) {
00667 $this->setError('Error during query');
00668 SnapDBI::cancelTransaction();
00669 return false;
00670 }
00671
00672 SnapDBI::commitTransaction();
00673
00674 $this->set('status', self::STATUS_DEV);
00675
00676 $oldDev = SnapCache::getById('Version', $res->get('devVersionId'));
00677 if($oldDev) {
00678 $oldDev->set('status', self::STATUS_DEFUNCT);
00679 SnapCache::updateById($oldDev->getType(), $oldDev->getId());
00680 }
00681
00682 $res->set('devVersionId', $this->getId());
00683 if($res->isLoaded('devVersion')) {
00684 $res->set('devVersion', $this);
00685 SnapCache::updateById($res->getType(), $res->getId());
00686 }
00687
00688 $this->logAction('ApproveForDev');
00689 SnapCache::updateById($this->getType(), $this->getId());
00690
00691 return true;
00692 }
00693
00702 public function approveForLive() {
00703 if(!$this->checkValid()) return false;
00704
00705 if(!SnapDBI::startTransaction())
00706 return false;
00707
00708 if(!$this->_canApproveForLive()) {
00709 $this->setError('Failed to approve for live: ' . $this->getReason());
00710 SnapDBI::cancelTransaction();
00711 return false;
00712 }
00713
00714 /*
00715 Things to do:
00716 1) Set old live version to defunct (if there was an old live version)
00717 2) Set this version to live
00718 3) Set resource's devVersionId to null (if this was the dev version)
00719 4) Set resource's liveVersionId to this
00720 5) Update cache for old live version (if old live version)
00721 6) Update cache for resource
00722 */
00723
00724 $res = $this->get('resource');
00725
00726 // 1) Set old live version to defunct
00727 if($res->get('liveVersionId') > 0) {
00728 $query = 'UPDATE Version SET status = ' . self::STATUS_DEFUNCT . ' WHERE id = ' . $res->get('liveVersionId');
00729 if(!SnapDBI::query($query)) {
00730 $this->setError('Error updating old live version');
00731 SnapDBI::cancelTransaction();
00732 return false;
00733 }
00734 }
00735
00736 // 2) Set this version to live
00737 $query = 'UPDATE Version SET status = ' . self::STATUS_LIVE . ' WHERE id = ' . $this->getId();
00738 if(!SnapDBI::query($query)) {
00739 $this->setError('Error during query');
00740 SnapDBI::cancelTransaction();
00741 return false;
00742 }
00743
00744 // 3) Set resource's devVersionId to null
00745 if(($oldStatus = $this->get('status')) == self::STATUS_DEV) {
00746 $query = 'UPDATE Resource SET devVersionId = NULL WHERE id = ' . $this->get('resourceId');
00747 if(!SnapDBI::query($query)) {
00748 $this->setError('Error updating resource');
00749 SnapDBI::cancelTransaction();
00750 return false;
00751 }
00752 }
00753
00754 // 4) Set resource's liveVersionId to this
00755 $query = 'UPDATE Resource SET liveVersionId = ' . $this->getId() . ' WHERE id = ' . $this->get('resourceId');
00756 if(!SnapDBI::query($query)) {
00757 $this->setError('Error during query');
00758 SnapDBI::cancelTransaction();
00759 return false;
00760 }
00761
00762 $query = 'UPDATE Resource SET approvalDate = CURRENT_TIMESTAMP WHERE id = ' . $this->get('resourceId');
00763 if(!SnapDBI::query($query)) {
00764 $this->setError('Error during query');
00765 SnapDBI::cancelTransaction();
00766 return false;
00767 }
00768
00769 SnapDBI::commitTransaction();
00770
00771 $this->set('status', self::STATUS_LIVE);
00772
00773 $oldLive = SnapCache::getById('Version', $res->get('liveVersionId'));
00774 if($oldLive) {
00775 $oldLive->set('status', self::STATUS_DEFUNCT);
00776 SnapCache::updateById($oldLive->getType(), $oldLive->getId());
00777 }
00778
00779 $res->set('liveVersionId', $this->getId());
00780 if($res->isLoaded('liveVersion'))
00781 $res->set('liveVersion', $this);
00782
00783 if($oldStatus == self::STATUS_DEV) {
00784 $res->set('devVersionId', '');
00785 if($res->isLoaded('devVersion'))
00786 $res->set('devVersion', null);
00787 }
00788 SnapCache::updateById($res->getType(), $res->getId());
00789
00790 $this->logAction('ApproveForLive');
00791 SnapCache::updateById($this->getType(), $this->getId());
00792
00793 return true;
00794 }
00795
00806 public function defunct() {
00807 if(!$this->checkValid()) return false;
00808
00809 if(!SnapDBI::startTransaction())
00810 return false;
00811
00812 if(!$this->_canDefunct()) {
00813 $this->setError('Failed to defunct: ' . $this->getReason());
00814 SnapDBI::cancelTransaction();
00815 return false;
00816 }
00817
00818 if($this->get('status') == self::STATUS_DEV) {
00819 $query = 'UPDATE Resource SET devVersionId = NULL WHERE id = ' . $this->get('resourceId');
00820 if(!SnapDBI::query($query)) {
00821 $this->setError('Error updating parent resource');
00822 SnapDBI::cancelTransaction();
00823 return false;
00824 }
00825 }
00826 else if($this->get('status') == self::STATUS_LIVE) {
00827 $query = 'UPDATE Resource SET liveVersionId = NULL WHERE id = ' . $this->get('resourceId');
00828 if(!SnapDBI::query($query)) {
00829 $this->setError('Error updating parent resource');
00830 SnapDBI::cancelTransaction();
00831 return false;
00832 }
00833 }
00834
00835 $query = 'UPDATE Version SET status = ' . self::STATUS_DEFUNCT . ' WHERE id = ' . $this->getId();
00836 if(!SnapDBI::query($query)) {
00837 $this->setError('Error updating version');
00838 SnapDBI::cancelTransaction();
00839 return false;
00840 }
00841
00842 SnapDBI::commitTransaction();
00843
00844 $oldStatus = $this->get('status');
00845 $this->set('status', self::STATUS_DEFUNCT);
00846 if($res = SnapCache::getById('Resource', $this->get('resourceId'))) {
00847 if($oldStatus == self::STATUS_DEV) {
00848 $res->set('devVersionId', '');
00849 if($res->isLoaded('devVersion'))
00850 $res->set('devVersion', null);
00851 }
00852 else if($oldStatus == self::STATUS_LIVE) {
00853 $res->set('liveVersionId', '');
00854 if($res->isLoaded('liveVersion'))
00855 $res->set('liveVersion', null);
00856 }
00857 SnapCache::updateById($res->getType(), $res->getId());
00858 }
00859
00860 $this->logAction('ApproveForLive');
00861 SnapCache::updateById($this->getType(), $this->getId());
00862
00863 return true;
00864 }
00865
00874 public function destroy() {
00875 if(!$this->checkValid()) return false;
00876
00877 if(!SnapDBI::startTransaction())
00878 return false;
00879
00880 if(!$this->_canDestroy()) {
00881 $this->setError('Failed to destroy: ' . $this->getReason());
00882 SnapDBI::cancelTransaction();
00883 return false;
00884 }
00885
00886 $query = 'DELETE FROM Version WHERE id = ' . $this->getId();
00887 if(!SnapDBI::query($query)) {
00888 $this->setError('Error during query');
00889 SnapDBI::cancelTransaction();
00890 return false;
00891 }
00892
00893 $cm = $this->getContentModule();
00894 $cm->delete();
00895
00896 SnapDBI::commitTransaction();
00897
00898 $res = SnapResource::retrieve($this->get('resourceId'));
00899 $res->unsetField('maxOrdinal');
00900
00901 SnapCache::deleteById('Version', $this->getId());
00902
00903 SnapDBI::query('DELETE FROM PathCache WHERE versionId = ' . $this->getId());
00904
00905 $this->setValid(false);
00906
00907 return true;
00908 }
00909
00918 public function deny() {
00919 if(!$this->checkValid()) return false;
00920
00921 if(!SnapDBI::startTransaction())
00922 return false;
00923
00924 if(!$this->_canDeny()) {
00925 $this->setError('Failed to deny: ' . $this->getReason());
00926 SnapDBI::cancelTransaction();
00927 return false;
00928 }
00929
00930 $query = "UPDATE Version SET status = '" . self::STATUS_PRIVATE . "' WHERE id = "
00931 . $this->getId();
00932 if(!SnapDBI::query($query)) {
00933 $this->setError('Error during query');
00934 SnapDBI::cancelTransaction();
00935 return false;
00936 }
00937
00938 SnapDBI::commitTransaction();
00939
00940 $this->set('status', self::STATUS_PRIVATE);
00941
00942 $this->logAction('Deny');
00943 SnapCache::updateById($this->getType(), $this->getId());
00944
00945 return true;
00946 }
00947
00956 public function steal() {
00957 if(!$this->checkValid()) return false;
00958
00959 if(!SnapDBI::startTransaction())
00960 return false;
00961
00962 if(!$this->_canSteal()) {
00963 $this->setError('Failed to steal: ' . $this->getReason());
00964 SnapDBI::cancelTransaction();
00965 return false;
00966 }
00967
00968 $query = 'UPDATE Version SET author = \'' . Snap2::getCurrentUser() . '\' WHERE id = '
00969 . $this->getId();
00970 if(!SnapDBI::query($query)) {
00971 $this->setError('Error during query');
00972 SnapDBI::cancelTransaction();
00973 return false;
00974 }
00975
00976 SnapDBI::commitTransaction();
00977
00978 $this->set('author', Snap2::getCurrentUser());
00979
00980 $this->logAction('Steal');
00981 SnapCache::updateById($this->getType(), $this->getId());
00982
00983 return true;
00984 }
00985
00986 /*
00987 * Query/list functions
00988 */
00989
01014 public function listActions($constraint = array(), $limit = array(), $order = array()) {
01015 if(!$this->checkValid()) return null;
01016
01017 $query = 'SELECT uid,action,actionTime FROM ActionLog WHERE versionId = ' . $this->getId();
01018
01019 $attrs = array('uid', 'action', 'actionTime');
01020
01021 $constraint = SnapDBI::criteriaToString($constraint, $attrs);
01022 if($constraint === false) return null;
01023 else if($constraint != '') $query .= ' AND ' . $constraint;
01024
01025 $order = SnapDBI::orderToString($order, $attrs);
01026 if($order === false) return null;
01027 else if($order != '') $query .= ' ' . $order;
01028
01029 $limit = SnapDBI::limitToString($limit);
01030 if($limit === false) return null;
01031 else if($limit != '') $query .= ' ' . $limit;
01032
01033 if(($result = SnapDBI::query($query, true)) === false) {
01034 $this->setError('Error during query');
01035 return null;
01036 }
01037
01038 return $result;
01039 }
01040
01048 public function getCanonicalPath() {
01049 $res = $this->get('resource');
01050 return $res->getCanonicalPath() . '@' . $this->get('ordinal');
01051 }
01052
01060 public function getAllPaths() {
01061 $paths = $this->get('resource')->getAllPaths();
01062 $finalPaths = array();
01063 foreach($paths as $path) {
01064 $finalPaths[] = $path . '@' . $this->get('ordinal');
01065 }
01066 return $finalPaths;
01067 }
01068 }
01069
01070 ?>