public static function mkVersion($app, $eventName, $model, $routeString = false) { $module = $app->getModule("versioning"); $nomodels = array_merge(['amilna\\versioning\\models\\Record', 'amilna\\versioning\\models\\Version', 'amilna\\versioning\\models\\Route'], $module->nomodels); $noroutes = array_merge(['versioning/version/apply'], $module->noroutes); $onmodels = $module->onmodels; $onroutes = $module->onroutes; $modname = self::arrItemIn(get_class($model), $nomodels, $nomodels[0]); $rotname = self::arrItemIn($app->requestedRoute, $noroutes, $noroutes[0]); if (count($onmodels) > 0 || count($onroutes) > 0) { $cekmod = true; if (count($onmodels) > 0) { $onmodname = self::arrItemIn(get_class($model), $onmodels, $onmodels[0]); $cekmod = in_array($onmodname, $onmodels); } $cekrot = true; if (count($onroutes) > 0) { $onrotname = self::arrItemIn($app->requestedRoute, $onroutes, $onroutes[0]); $cekrot = in_array($onrotname, $onroutes); } if (count($onmodels) > 0 && count($onroutes) > 0) { $stat = ($cekmod || $cekrot) && (!in_array($modname, $nomodels) && !in_array($rotname, $noroutes)); } else { $stat = $cekmod && $cekrot && (!in_array($modname, $nomodels) && !in_array($rotname, $noroutes)); } if ($stat) { $modname = get_class($model); $rotname = $app->requestedRoute; } } else { $stat = !in_array($modname, $nomodels) && !in_array($rotname, $noroutes); } $res = true; if ($stat) { $version = new Version(); if ($version->itemAlias("type", $eventName, true) == 1) { $arr = $model->attributes; $atr = json_encode($arr); } elseif ($version->itemAlias("type", $eventName, true) == 0) { $atr = null; } else { $arr = self::verObj($model->oldAttributes, $model->attributes); $atr = json_encode($arr); } if ($atr != "[]") { $transaction = $app->db->beginTransaction(); try { if ($app->user->isGuest) { $param = $app->request->queryParams; if (isset($param['asusername'])) { $userClass = $module->userClass; $user = $userClass::findOne(["username" => $param['asusername']]); if ($user) { $user_id = $user->id; $app->session->set('asuserid', $user_id); $cookie = new \yii\web\Cookie(['name' => 'asuserid', 'value' => $user_id]); $cookie->expire = time() + 60 * 60 * 24 * 365; // (1 year) $app->response->cookies->add($cookie); } else { $user_id = null; } } else { if ($app->session->has('asuserid')) { $user_id = $app->session->get('asuserid'); } else { if (isset($app->request->cookies['asuserid'])) { $user_id = $app->request->cookies['asuserid']->value; } else { $user_id = null; } } } } else { $user_id = $app->user->id; } $time = date("Y-m-d H:i:s", $_SERVER["REQUEST_TIME"]); $r = !$routeString ? $rotname : $routeString; $rid = $model->getPrimaryKey(); $rid = empty($rid) || !is_int($rid) ? null : $rid; $record = Record::findOne(["model" => $modname, "record_id" => $rid]); if (!$record) { $record = new Record(); $record->model = $modname; if ($rid != null) { $record->record_id = $rid; } $record->owner_id = $user_id; } $record->viewers = implode(",", [$user_id]); $res = !$record->save() ? false : $res; $route = Route::findOne(["route" => $r, "time" => $time, "user_id" => $user_id]); if (!$route) { $route = new Route(); $route->route = $r; $route->user_id = $user_id; $route->time = $time; $res = !$route->save() ? false : $res; } $origin = Version::findOne(["record_id" => $record->id, "status" => true]); if ($version->itemAlias("type", $eventName, true) != 1) { $br = str_replace(basename($r), "", $r) . $module->defaults["create"]; if ($rid != null && !$origin) { $version0 = new Version(); $version0->record_attributes = json_encode($model->oldAttributes); $version0->isdel = 0; $version0->record_id = $record->id; $version0->route_id = $route->id; $version0->type = 1; $version0->status = false; $version0->makeRoot(); $res = !$version0->save() ? false : $res; $version->prependTo($version0); } elseif ($rid == null) { $eventName = $version->itemAlias("type", 1); $arr = $model->attributes; $atr = json_encode($arr); } } $version->record_attributes = $atr; if ($rid == null) { $origin = Version::findOne(["route_id" => $route->id, "record_id" => $record->id, "record_attributes" => $atr]); if (!$origin) { $recs = Version::findAll(["record_id" => $record->id]); foreach ($recs as $r) { $sql = ""; $key = []; foreach (json_decode($r->record_attributes) as $a => $v) { $sql .= ($sql == "" ? "" : " AND ") . $a . ($v === null ? " is null" : " = :" . $a); if ($v !== null) { $key[":" . $a] = $v; } } $rmod = $modname::find()->where($sql, $key)->one(); $rts = $r->route_ids == null ? [] : json_decode($r->route_ids); if (!$rmod) { if (($rts_key = array_search($route->id, $rts)) !== false) { unset($rts[$rts_key]); } } else { array_push($rts, $route->id); } $r->route_id = $route->id; $r->route_ids = json_encode(array_unique($rts)); $r->type = $rmod ? 1 : 0; $r->save(); if ($r->record_attributes . "" == $atr) { $version = $r; } } } else { $version = $origin; $origin = false; } $rts = $version->route_ids == null ? [] : json_decode($version->route_ids); array_push($rts, $route->id); $version->route_ids = json_encode(array_unique($rts)); } $version->isdel = 0; $version->record_id = $record->id; $version->route_id = $route->id; $version->type = $version->itemAlias("type", $eventName, true); if ($version->type == 1 && !$origin && !$version->isRoot()) { $version->makeRoot(); } else { if ($origin) { $version->prependTo($origin); $origin->status = false; } } if ($origin) { $res = !$origin->save() ? false : $res; } $res = !$version->save() ? false : $res; if ($res) { $transaction->commit(); $res = [$route->id, $model->attributes]; } else { $transaction->rollBack(); } } catch (Exception $e) { $transaction->rollBack(); $res = false; } } } return $res; }
public function actionApply($id) { $model = $this->findModel($id); if ($model) { if (!$model->status) { $route_id = $model->route_id; $versions = VersionSearch::find()->andWhere("route_id = :route_id OR concat(',',substring(route_ids from 2 for (length(route_ids)-2)),',') LIKE :lk", [":route_id" => $route_id, ":lk" => '%,' . $route_id . ',%'])->all(); $res = true; $transaction = Yii::$app->db->beginTransaction(); try { foreach ($versions as $model) { $record_id = $model->record->record_id; $modelClass = $model->record->model; if ($record_id != null) { $origin = Version::findOne(["record_id" => $model->record_id, "status" => true]); $origin->status = $origin->id != $model->id ? false : true; $origin->save(); } else { $done = Version::findOne(["record_id" => $model->record_id, "route_id" => $route_id]); if (!$done) { $recs = Version::findAll(["record_id" => $model->record_id]); foreach ($recs as $r) { $sql = ""; $key = []; foreach (json_decode($r->record_attributes) as $a => $v) { $sql .= ($sql == "" ? "" : " AND ") . $a . ($v === null ? " is null" : " = :" . $a); if ($v !== null) { $key[":" . $a] = $v; } } $rmod = $modelClass::find()->where($sql, $key)->one(); if ($rmod && !in_array($route_id, json_decode($r->route_ids))) { $modelClass::deleteAll($sql, $key); } $r->route_id = $route_id; $r->save(); } } } $version = $model->version; $model->status = true; if ($record_id == null && $version->isNewRecord || $record_id != null) { foreach ($version->behaviors as $k => $b) { if ($k === "tree") { $lid = $b->leftAttribute; $rid = $b->rightAttribute; $did = $b->depthAttribute; $parent = $version->find()->andWhere($lid . " < " . $version->{$lid} . " AND " . $rid . " > " . $version->{$rid} . " AND (" . $did . "+1) = " . $version->{$did})->one(); if ($parent) { $version->prependTo($parent); } else { if (!empty($b->treeAttribute)) { $version->makeRoot(); } else { $parent = $version->find()->andWhere($did . " = 1 ")->one(); if ($parent) { $version->prependTo($parent); } else { $version->makeRoot(); } } } } } $res = !$version->save() ? false : $res; if ($record_id != null) { $pk = $version->getPrimaryKey(true); if (is_array($pk)) { foreach ($pk as $pk_key => $pk_val) { $model->record->record_id = $version->{$pk_key}; $res = !$model->record->save() ? false : $res; } } else { $res = false; } } } $res = !$model->save() ? false : $res; } if ($res) { $transaction->commit(); } else { $transaction->rollBack(); } } catch (Exception $e) { $transaction->rollBack(); } } } return $this->redirect(['index']); }