示例#1
0
 /**
  * @param ActiveRecord $target
  * @param int $key
  * @param int $levelUp
  * @throws Exception
  * @return boolean
  */
 private function moveNode($target, $key, $levelUp)
 {
     if ($this->owner->getIsNewRecord()) {
         throw new Exception('The node should not be new record.');
     }
     if ($this->getIsDeletedRecord()) {
         throw new Exception('The node should not be deleted.');
     }
     if ($target->getIsDeletedRecord()) {
         throw new Exception('The target node should not be deleted.');
     }
     if ($this->owner->equals($target)) {
         throw new Exception('The target node should not be self.');
     }
     if ($target->isDescendantOf($this->owner)) {
         throw new Exception('The target node should not be descendant.');
     }
     if (!$levelUp && $target->isRoot()) {
         throw new Exception('The target node should not be root.');
     }
     if (!$this->beforeMoveNode($this->_previousPath)) {
         return false;
     }
     $db = $this->owner->getDb();
     if ($db->getTransaction() === null) {
         $transaction = $db->beginTransaction();
     }
     try {
         $left = $this->owner->getAttribute($this->leftAttribute);
         $right = $this->owner->getAttribute($this->rightAttribute);
         $levelDelta = $target->getAttribute($this->levelAttribute) - $this->owner->getAttribute($this->levelAttribute) + $levelUp;
         if ($this->hasManyRoots && $this->owner->getAttribute($this->rootAttribute) !== $target->getAttribute($this->rootAttribute)) {
             foreach ([$this->leftAttribute, $this->rightAttribute] as $attribute) {
                 $this->owner->updateAll([$attribute => new Expression($db->quoteColumnName($attribute) . sprintf('%+d', $right - $left + 1))], $db->quoteColumnName($attribute) . '>=' . $key . ' AND ' . $db->quoteColumnName($this->rootAttribute) . '=:' . $this->rootAttribute, [':' . $this->rootAttribute => $target->getAttribute($this->rootAttribute)]);
             }
             $delta = $key - $left;
             $this->owner->updateAll([$this->leftAttribute => new Expression($db->quoteColumnName($this->leftAttribute) . sprintf('%+d', $delta)), $this->rightAttribute => new Expression($db->quoteColumnName($this->rightAttribute) . sprintf('%+d', $delta)), $this->levelAttribute => new Expression($db->quoteColumnName($this->levelAttribute) . sprintf('%+d', $levelDelta)), $this->rootAttribute => $target->getAttribute($this->rootAttribute)], $db->quoteColumnName($this->leftAttribute) . '>=' . $left . ' AND ' . $db->quoteColumnName($this->rightAttribute) . '<=' . $right . ' AND ' . $db->quoteColumnName($this->rootAttribute) . '=:' . $this->rootAttribute, [':' . $this->rootAttribute => $this->owner->getAttribute($this->rootAttribute)]);
             $this->shiftLeftRight($right + 1, $left - $right - 1);
             if (isset($transaction)) {
                 $transaction->commit();
             }
             $this->correctCachedOnMoveBetweenTrees($key, $levelDelta, $target->getAttribute($this->rootAttribute));
         } else {
             $delta = $right - $left + 1;
             $this->shiftLeftRight($key, $delta);
             if ($left >= $key) {
                 $left += $delta;
                 $right += $delta;
             }
             $condition = $db->quoteColumnName($this->leftAttribute) . '>=' . $left . ' AND ' . $db->quoteColumnName($this->rightAttribute) . '<=' . $right;
             $params = [];
             if ($this->hasManyRoots) {
                 $condition .= ' AND ' . $db->quoteColumnName($this->rootAttribute) . '=:' . $this->rootAttribute;
                 $params[':' . $this->rootAttribute] = $this->owner->getAttribute($this->rootAttribute);
             }
             $updateColumns = [];
             $updateColumns[$this->levelAttribute] = new Expression($db->quoteColumnName($this->levelAttribute) . sprintf('%+d', $levelDelta));
             if ($this->hasPaths && $this->owner->hasAttribute($this->pathAttribute)) {
                 $pathLength = Tools::strlen($this->_previousPath) + 1;
                 // SQL Server: SUBSTRING() rather than SUBSTR
                 // SQL Server: + instead of CONCAT
                 if ($db->getDriverName() == 'mssql') {
                     $updateColumns[$this->pathAttribute] = new Expression($db->quoteValue($this->owner->getAttribute($this->pathAttribute)) . ' + SUBSTRING(' . $db->quoteColumnName($this->pathAttribute) . ', ' . $pathLength . '))');
                 } else {
                     $updateColumns[$this->pathAttribute] = new Expression('CONCAT(' . $db->quoteValue($this->owner->getAttribute($this->pathAttribute)) . ', SUBSTR(' . $db->quoteColumnName($this->pathAttribute) . ', ' . $pathLength . '))');
                 }
             }
             $this->owner->updateAll($updateColumns, $condition, $params);
             foreach ([$this->leftAttribute, $this->rightAttribute] as $attribute) {
                 $condition = $db->quoteColumnName($attribute) . '>=' . $left . ' AND ' . $db->quoteColumnName($attribute) . '<=' . $right;
                 $params = [];
                 if ($this->hasManyRoots) {
                     $condition .= ' AND ' . $db->quoteColumnName($this->rootAttribute) . '=:' . $this->rootAttribute;
                     $params[':' . $this->rootAttribute] = $this->owner->getAttribute($this->rootAttribute);
                 }
                 $this->owner->updateAll([$attribute => new Expression($db->quoteColumnName($attribute) . sprintf('%+d', $key - $left))], $condition, $params);
             }
             $this->shiftLeftRight($right + 1, -$delta);
             $result = $this->afterMoveNode($this->_previousPath);
             if (isset($transaction)) {
                 if ($result) {
                     $transaction->commit();
                 } else {
                     $transaction->rollback();
                     $this->_previousPath = '';
                     return false;
                 }
             }
             $this->correctCachedOnMoveNode($key, $levelDelta);
         }
     } catch (\Exception $e) {
         if (isset($transaction)) {
             $transaction->rollback();
         }
         throw $e;
     }
     $this->_previousPath = '';
     return true;
 }
示例#2
0
 /**
  * Check changed attributes and compare the table schema, truncating any fields as required
  *
  * @param array $attributes Array of attributes to limit checking to those only
  */
 public function checkAndFixLongStrings($attributes = false)
 {
     $hasChanges = $this->getDirtyAttributes();
     if ($hasChanges) {
         $columns = self::getTableSchema()->columns;
         foreach ($hasChanges as $name => $value) {
             if (array_key_exists($name, $columns)) {
                 if (!$attributes || in_array($name, $attributes) !== false) {
                     if ($columns[$name]->type == 'string' && $columns[$name]->size) {
                         if (Tools::strlen($value) > $columns[$name]->size) {
                             $this->setAttribute($name, Tools::substr($value, 0, $columns[$name]->size));
                         }
                     }
                 }
             }
         }
     }
 }