fillFromConfig([ 'conditionsRuleType', ]); if ($widget = $this->makeConditionFormWidget()) { $widget->bindToController(); } $this->initRootCondition(); } /** * {@inheritDoc} */ protected function loadAssets() { $this->addJs('js/conditions.js', 'RainLab.Notify'); $this->addJs('js/conditions.multivalue.js', 'RainLab.Notify'); $this->addCss('css/conditions.css', 'RainLab.Notify'); } /** * {@inheritDoc} */ public function render() { $this->prepareVars(); return $this->makePartial('conditions_container'); } /** * Prepares the list data */ public function prepareVars() { $this->vars['rootCondition'] = $this->getConditionsRoot(); $this->vars['conditionFormWidget'] = $this->conditionFormWidget; } public function initRootCondition() { if ($this->getConditionsRoot()) { return; } $relationObject = $this->getRelationObject(); $rootRule = $this->getRelationModel(); $rootRule->rule_host_type = $this->conditionsRuleType; $rootRule->class_name = $rootRule->getRootConditionClass(); $rootRule->save(); $relationObject->add($rootRule, $this->sessionKey); $this->conditionsRoot = $rootRule; } public function isRootCondition($condition) { if ($root = $this->getConditionsRoot()) { return $condition->id === $root->id; } return false; } public function getConditionsRoot() { if ($this->conditionsRoot !== false) { return $this->conditionsRoot; } $relationObject = $this->getRelationObject(); $rootCondition = $relationObject->withDeferred($this->sessionKey)->first(); return $this->conditionsRoot = $rootCondition ?: null; } /** * @inheritDoc */ public function getSaveValue($value) { $this->model->bindEvent('model.afterSave', function() { $this->processSave(); }); return FormField::NO_SAVE_DATA; } protected function processSave() { $cache = $this->getCacheConditionDataPayload(); foreach ($cache as $id => $data) { $condition = $this->findConditionObj($id); $attributes = $this->getCacheConditionAttributes($condition); $condition->fill($attributes); $condition->save(null, $this->sessionKey.'_'.$condition->id); } } // // AJAX // public function onLoadConditionSetup() { try { $condition = $this->findConditionObj(); $this->prepareVars(); $this->vars['condition'] = $condition; } catch (Exception $ex) { $this->handleError($ex); } return $this->makePartial('condition_settings_form'); } public function onLoadCreateChildCondition() { try { $condition = $this->findConditionObj(); /* * Look up parents */ $parents = [$condition->id]; $parentsArray = post('condition_parent_id', []); $currentId = $condition->id; while (array_key_exists($currentId, $parentsArray) && $parentsArray[$currentId]) { $parents[] = $currentId = $parentsArray[$currentId]; } /* * Custom rules provided by model */ $extraRules = []; if ($this->model->methodExists('getExtraConditionRules')) { $extraRules = $this->model->getExtraConditionRules(); } /* * Look up conditions */ $options = $condition->getChildOptions([ 'ruleType' => $this->conditionsRuleType, 'parentIds' => $parents, 'extraRules' => $extraRules ]); $this->prepareVars(); $this->vars['condition'] = $condition; $this->vars['options'] = $options; } catch (Exception $ex) { $this->handleError($ex); } return $this->makePartial('create_child_form'); } public function onSaveCondition() { $this->restoreCacheConditionDataPayload(); $condition = $this->findConditionObj(); $data = post('Condition', []); $condition->fill($data); $condition->validate(); $condition->condition_text = $condition->getConditionObject()->getText(); $condition->applyCustomData(); $this->setCacheConditionData($condition); return $this->renderConditions($condition); } public function onCreateCondition() { if (!$className = post('condition_class')) { throw new ValidationException(['condition_class' => 'Please specify a condition']); } $this->restoreCacheConditionDataPayload(); $subcondition = null; $parts = explode(':', $className); if (count($parts) > 1) { $subcondition = $parts[1]; $className = $parts[0]; } $parentCondition = $this->findConditionObj(); $newCondition = $this->getRelationModel(); $newCondition->class_name = $className; $newCondition->rule_host_type = $parentCondition->rule_host_type; if ($subcondition) { $newCondition->subcondition = $subcondition; } $newCondition->save(); $parentCondition->children()->add($newCondition, post('_session_key').'_'.$parentCondition->id); $this->vars['newConditionId'] = $newCondition->id; return $this->renderConditions($parentCondition); } public function onDeleteCondition() { $parentCondition = null; $condition = $this->findConditionObj(); if ($parentId = $this->getParentIdFromCondition($condition)) { $parentCondition = $this->findConditionObj($parentId); if ($parentCondition) { $parentCondition->children()->remove($condition, post('_session_key').'_'.$parentCondition->id); } } return $this->renderConditions($parentCondition); } public function onCancelConditionSettings() { $condition = $this->findConditionObj(post('new_condition_id')); $condition->delete(); return $this->renderConditions(); } // // Postback deferring // public function getCacheConditionAttributes($condition) { return array_get($this->getCacheConditionData($condition), 'attributes'); } public function getCacheConditionText($condition) { return array_get($this->getCacheConditionData($condition), 'text'); } public function getCacheConditionJoinText($condition) { return array_get($this->getCacheConditionData($condition), 'joinText'); } public function getCacheConditionData($condition, $default = null) { $cache = post('condition_data', []); if (is_array($cache) && array_key_exists($condition->id, $cache)) { return json_decode($cache[$condition->id], true); } if ($default === false) { return null; } return $this->makeCacheConditionData($condition); } public function makeCacheConditionData($condition) { $data = [ 'attributes' => $condition->config_data, 'text' => $condition->getText() ]; if ($condition->isCompound()) { $data['joinText'] = $condition->getJoinText(); } return $data; } public function setCacheConditionData($condition) { $cache = post('condition_data', []); $cache[$condition->id] = json_encode($this->makeCacheConditionData($condition)); Request::merge([ 'condition_data' => $cache ]); } public function restoreCacheConditionDataPayload() { Request::merge([ 'condition_data' => json_decode(post('current_condition_data', []), true) ]); } public function getCacheConditionDataPayload() { return post('condition_data'); } // // Helpers // public function getParentIdFromCondition($condition) { if ($parentId = post('current_parent_id')) { return $parentId; } $parentIds = post('condition_parent_id', []); if (isset($parentIds[$condition->id])) { return $parentIds[$condition->id]; } } /** * Updates the primary rule conditions container * @return array */ protected function renderConditions($currentCondition = null) { if ($currentCondition && $this->isRootCondition($currentCondition)) { $condition = $currentCondition; } else { $condition = $this->getConditionsRoot(); } return [ '#'.$this->getId() => $this->makePartial('conditions', ['condition' => $condition]) ]; } protected function makeConditionFormWidget() { if ($this->conditionFormWidget !== null) { return $this->conditionFormWidget; } if (!$model = $this->findConditionObj(null, false)) { return null; } $config = $model->getFieldConfig(); $config->model = $model; $config->alias = $this->alias . 'Form'; $config->arrayName = 'Condition'; $widget = $this->makeWidget('Backend\Widgets\Form', $config); /* * Set form values based on postback or cached attributes */ if (!$data = post('Condition')) { $data = $this->getCacheConditionAttributes($model); } $widget->setFormValues($data); /* * Allow conditions to register their own widgets */ $model->onPreRender($this->controller, $this); return $this->conditionFormWidget = $widget; } protected function findConditionObj($conditionId = null, $throw = true) { $conditionId = $conditionId ? $conditionId : post('current_condition_id'); $condition = null; if (strlen($conditionId)) { $condition = $this->getRelationModel()->find($conditionId); } if ($throw && !$condition) { throw new ApplicationException('Condition not found'); } return $condition; } }