├── .DS_Store ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── resources ├── .DS_Store └── img │ └── plugin-logo.png └── src ├── .DS_Store ├── Conditions.php ├── assets └── ConditionsAssets.php ├── elements └── Conditions.php ├── migrations └── Install.php ├── models └── ConditionalsModel.php ├── records └── ConditionalsRecord.php ├── resources ├── .DS_Store ├── javascripts │ ├── .DS_Store │ ├── conditions-atest3dc3r.js │ ├── modules │ │ ├── builder.js │ │ ├── fld.js │ │ └── render.js │ └── reasons.js └── stylesheets │ ├── .DS_Store │ └── conditions-btest9098.css ├── services └── ConditionsService.php └── translations └── en └── conditions.php /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkshakeStudio/craft-conditions/1c334a49e908d562ea1459c5b4726d2cb90f5ec0/.DS_Store -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Conditions Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | ## 1.0.0 - 2019-03-01 8 | ### Added 9 | - Initial release 10 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Milkshake Studio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | # Conditions plugin for Craft CMS 3.x 7 | Conditions is taken from [Reasons for Craft 2.0](https://github.com/mmikkel/Reasons-Craft). Since it was not being rebuilt we decided to try and update it for 3.0. 8 | 9 | 10 | 11 | ## Conditions Roadmap 12 | 13 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "craftconditions/conditions", 3 | "description": "conditions on fields", 4 | "type": "craft-plugin", 5 | "version": "1.0.3", 6 | "keywords": [ 7 | "craft", 8 | "cms", 9 | "craftcms", 10 | "craft-plugin", 11 | "conditions" 12 | ], 13 | "support": { 14 | "docs": "https://github.com/MilkshakeStudio/craft-conditions/", 15 | "issues": "https://github.com/MilkshakeStudio/craft-conditions/issues" 16 | }, 17 | "license": "MIT", 18 | "authors": [ 19 | { 20 | "name": "Milkshake Studio", 21 | "homepage": "http://milkshake.studio/" 22 | } 23 | ], 24 | "require": { 25 | "craftcms/cms": "^3.0.0-RC1" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "craftconditions\\conditions\\": "src/" 30 | } 31 | }, 32 | "extra": { 33 | "name": "Conditions", 34 | "handle": "conditions", 35 | "hasCpSettings": false, 36 | "hasCpSection": false, 37 | "changelogUrl": "???", 38 | "components": { 39 | "conditionsService": "craftconditions\\conditions\\services\\ConditionsService" 40 | }, 41 | "class": "craftconditions\\conditions\\Conditions" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /resources/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkshakeStudio/craft-conditions/1c334a49e908d562ea1459c5b4726d2cb90f5ec0/resources/.DS_Store -------------------------------------------------------------------------------- /resources/img/plugin-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkshakeStudio/craft-conditions/1c334a49e908d562ea1459c5b4726d2cb90f5ec0/resources/img/plugin-logo.png -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkshakeStudio/craft-conditions/1c334a49e908d562ea1459c5b4726d2cb90f5ec0/src/.DS_Store -------------------------------------------------------------------------------- /src/Conditions.php: -------------------------------------------------------------------------------- 1 | types[] = ConditionsElement::class; 108 | } 109 | ); 110 | 111 | // Do something after we're installed 112 | Event::on( 113 | Plugins::class, 114 | Plugins::EVENT_AFTER_INSTALL_PLUGIN, 115 | function (PluginEvent $event) { 116 | if ($event->plugin === $this) { 117 | // We were just installed 118 | } 119 | } 120 | ); 121 | 122 | /** 123 | * Logging in Craft involves using one of the following methods: 124 | * 125 | * Craft::trace(): record a message to trace how a piece of code runs. This is mainly for development use. 126 | * Craft::info(): record a message that conveys some useful information. 127 | * Craft::warning(): record a warning message that indicates something unexpected has happened. 128 | * Craft::error(): record a fatal error that should be investigated as soon as possible. 129 | * 130 | * Unless `devMode` is on, only Craft::warning() & Craft::error() will log to `craft/storage/logs/web.log` 131 | * 132 | * It's recommended that you pass in the magic constant `__METHOD__` as the second parameter, which sets 133 | * the category to the method (prefixed with the fully qualified class name) where the constant appears. 134 | * 135 | * To enable the Yii debug toolbar, go to your user account in the AdminCP and check the 136 | * [] Show the debug toolbar on the front end & [] Show the debug toolbar on the Control Panel 137 | * 138 | * http://www.yiiframework.com/doc-2.0/guide-runtime-logging.html 139 | */ 140 | Craft::info( 141 | Craft::t( 142 | 'conditions', 143 | '{name} plugin loaded', 144 | ['name' => $this->name] 145 | ), 146 | __METHOD__ 147 | ); 148 | if(Craft::$app->getRequest()->getIsCpRequest()) { 149 | if (Craft::$app->getRequest()->getIsAjax()) { 150 | $this->ProcessAfterLoad(); 151 | } else { 152 | 153 | $this->includeAssets(); 154 | Craft::$app->view->registerJs('if (window.Craft && window.Craft.ConditionsPlugin) { 155 | Craft.ConditionsPlugin.init('.$this->jsonToJs().'); 156 | }'); 157 | Event::on(Fields::class, Fields::EVENT_BEFORE_SAVE_FIELD_LAYOUT, function(Event $event) { 158 | $this->onSaveConditionalLayout($event); 159 | }); 160 | } 161 | } 162 | } 163 | /** 164 | * include Javascript and css Assets 165 | */ 166 | protected function includeAssets() 167 | { 168 | $this->view->registerAssetBundle(ConditionsAssets::class); 169 | } 170 | 171 | 172 | /** 173 | * @return string 174 | */ 175 | protected function jsonToJs() 176 | { 177 | $data = array( 178 | 'expressions' => $this->getConditionalObj(), 179 | 'fldIds' => $this->getFieldIds(), 180 | 'conditionalFieldTypes' => $this->getAllConditionalFieldTypes(), 181 | 'conditionalFields' => $this->getAllConditionalFields(), 182 | ); 183 | return json_encode($data); 184 | } 185 | 186 | /** 187 | * @return array 188 | */ 189 | protected function getConditionalObj() 190 | { 191 | $resources = array(); 192 | $sources = array(); 193 | 194 | // Get Asset volumes 195 | $allAssetSources = Craft::$app->getVolumes()->getAllVolumes(); 196 | 197 | if(!empty($allAssetSources)) 198 | { 199 | foreach ($allAssetSources as $assetSource) { 200 | $sources['assetSource:' . $assetSource->id] = $assetSource->fieldLayoutId; 201 | } 202 | } 203 | 204 | // Get Tag groups 205 | $allTagGroups = Craft::$app->tags->getAllTagGroups(); 206 | foreach ($allTagGroups as $tagGroup) { 207 | $sources['tagGroup:' . $tagGroup->id] = $tagGroup->fieldLayoutId; 208 | } 209 | 210 | // Get all Entry types records 211 | 212 | $entryTypeRecords = EntryTypeRecord::find()->all(); 213 | 214 | if ($entryTypeRecords) { 215 | foreach ($entryTypeRecords as $entryType) { 216 | $sources['entryType:' . $entryType->id] = $entryType->fieldLayoutId; 217 | $sources['section:' . $entryType->sectionId] = $entryType->fieldLayoutId; 218 | } 219 | } 220 | 221 | 222 | // Get Global sets 223 | $allGlobalSets = Craft::$app->globals->getAllSets(); 224 | foreach ($allGlobalSets as $globalSet) { 225 | $sources['globalSet:' . $globalSet->id] = $globalSet->fieldLayoutId; 226 | } 227 | 228 | // Get Category groups 229 | $allCategoryGroups = Craft::$app->categories->getAllGroups(); 230 | foreach ($allCategoryGroups as $categoryGroup) { 231 | $sources['categoryGroup:' . $categoryGroup->id] = $categoryGroup->fieldLayoutId; 232 | } 233 | 234 | 235 | // Retrive Users Field Layout 236 | $usersFieldLayout = Craft::$app->fields->getLayoutByType('craft\elements\User'); 237 | 238 | 239 | 240 | if ($usersFieldLayout) { 241 | $sources['users'] = $usersFieldLayout->id; 242 | } 243 | 244 | 245 | // Get conditionals Array 246 | $conArr = array(); 247 | $tableSchema = Craft::$app->db->schema->getTableSchema('{{%conditions_conditionalsrecord}}'); 248 | if ($tableSchema != null) 249 | { 250 | $conditionalsRecords = ConditionalsRecord::find()->all(); 251 | if ($conditionalsRecords) { 252 | foreach ($conditionalsRecords as $conditionalsRecord) { 253 | $conditionalsModel = $conditionalsRecord; 254 | if ($conditionalsModel->expressions && $conditionalsModel->expressions != '') { 255 | $conArr['fieldLayout:' . $conditionalsModel->fieldLayoutId] = $conditionalsModel->expressions; 256 | } 257 | } 258 | } 259 | } 260 | // Conditionals to origin mapping 261 | foreach ($sources as $sourceId => $fieldLayoutId) { 262 | if (isset($conArr['fieldLayout:' . $fieldLayoutId])) { 263 | $resources[$sourceId] = $conArr['fieldLayout:' . $fieldLayoutId]; 264 | } 265 | } 266 | return $resources; 267 | 268 | } 269 | /** 270 | * @param Event $event 271 | */ 272 | public function onSaveConditionalLayout(Event $event) 273 | { 274 | 275 | $fldLayout = $event->layout; 276 | $cndlModel = new ConditionalsModel(); 277 | $cndlModel->fieldLayoutId = $fldLayout->id; 278 | 279 | $cndlModel->expressions = Craft::$app->getRequest()->getBodyParam('_conditions'); 280 | $conditionsService = new ConditionsService(); 281 | $conditionsService->save($cndlModel); 282 | } 283 | /** 284 | * @return bool Ajax 285 | */ 286 | protected function ProcessAfterLoad() 287 | { 288 | 289 | if (!Craft::$app->getRequest()->getIsPost()) { 290 | return false; 291 | } 292 | 293 | $segments = Craft::$app->request->segments; 294 | $actionSegment = $segments[count($segments) - 1]; 295 | 296 | switch ($actionSegment) { 297 | 298 | case 'switch-entry-type' : 299 | Craft::$app->view->registerJs('Craft.ConditionsPlugin.FormLoad();'); 300 | break; 301 | 302 | case 'get-editor-html' : 303 | 304 | $elementId = (int)Craft::$app->getRequest()->getBodyParam('elementId'); 305 | 306 | $element = $elementId ? Craft::$app->getElements()->getElementById($elementId) : null; 307 | $elementType = $element ?Craft::$app->getElements()->getElementTypeById($elementId) : Craft::$app->getRequest()->getBodyParam('elementType'); 308 | $attributes = Craft::$app->getRequest()->getBodyParam('attributes'); 309 | 310 | $entityType = null; 311 | 312 | switch ($elementType) { 313 | 314 | case 'craft\elements\Entry' : 315 | if ($element) { 316 | $entityType = 'entryType:' . $element->type->id; 317 | } else if (isset($attributes['typeId'])) { 318 | $entityType = 'entryType:' . $attributes['typeId']; 319 | } else if (isset($attributes['sectionId'])) { 320 | $entryTypes = Craft::$app->sections->getEntryTypesBySectionId((int)$attributes['sectionId']); 321 | $entryType = $entryTypes ? array_shift($entryTypes) : false; 322 | $entityType = $entryType ? 'entryType:' . $entryType->id : null; 323 | } 324 | break; 325 | 326 | case 'craft\elements\GlobalSet' : 327 | $entityType = $element ? 'globalSet:' . $element->id : null; 328 | break; 329 | 330 | case 'craft\elements\Asset' : 331 | 332 | $entityType = $element ? 'assetSource:' . $element->volumeId : null; 333 | break; 334 | 335 | case 'craft\elements\Category' : 336 | $entityType = $element ? 'categoryGroup:' . $element->group->id : null; 337 | break; 338 | 339 | case 'craft\elements\Tag' : 340 | $entityType = $element ? 'tagGroup:' . $element->group->id : null; 341 | break; 342 | 343 | case 'craft\elements\User' : 344 | $entityType = 'users'; 345 | break; 346 | } 347 | 348 | if ($entityType) { 349 | Craft::$app->view->registerJs('Craft.ConditionsPlugin.ElementEditorLoad("' . $entityType . '");'); 350 | } 351 | break; 352 | } 353 | } 354 | 355 | /* 356 | * Returns all toggleable fields 357 | * 358 | */ 359 | /** 360 | * @return array 361 | */ 362 | protected function getAllConditionalFields() 363 | { 364 | $tgFields = array(); 365 | $flds = Craft::$app->fields->getAllFields(); 366 | 367 | $toggleFieldTypes = $this->getAllConditionalFieldTypes(); 368 | foreach ($flds as $field) { 369 | 370 | $fieldType = join('', array_slice(explode('\\', get_class($field)), -1)); 371 | $classHandle = $fieldType; 372 | if (!$classHandle) { 373 | continue; 374 | } 375 | if (in_array($classHandle, $toggleFieldTypes)) { 376 | $tgFields[] = array( 377 | 'id' => $field->id, 378 | 'handle' => $field->handle, 379 | 'name' => $field->name, 380 | 'type' => $classHandle, 381 | 'settings' => $field->settings, 382 | ); 383 | } 384 | } 385 | return $tgFields; 386 | } 387 | 388 | /** 389 | * @return array 390 | */ 391 | protected function getFieldIds() 392 | { 393 | $data = array(); 394 | $flds = Craft::$app->fields->getAllFields(); 395 | foreach ($flds as $field) { 396 | $data[$field->handle] = $field->id; 397 | } 398 | return $data; 399 | } 400 | 401 | /** 402 | * @return array 403 | */ 404 | protected function getAllConditionalFieldTypes() 405 | { 406 | return array( 407 | 'PlainText', 408 | 'Number', 409 | 'Entries', 410 | 'SuperTableField', 411 | 'MultiSelect', 412 | 'Lightswitch', 413 | 'ButtonBox_Buttons', 414 | 'Tags', 415 | 'Dropdown', 416 | 'Assets', 417 | 'ButtonBox_Width', 418 | 'Checkboxes', 419 | 'ButtonBox_TextSize', 420 | 'Users', 421 | 'ButtonBox_Stars', 422 | 'RadioButtons', 423 | 'Calendar_Event', 424 | 'PositionSelect', 425 | 'Categories', 426 | 'ButtonBox_Colours', 427 | ); 428 | } 429 | 430 | } 431 | -------------------------------------------------------------------------------- /src/assets/ConditionsAssets.php: -------------------------------------------------------------------------------- 1 | sourcePath = '@craftconditions/conditions/resources'; 78 | 79 | // define the dependencies 80 | $this->depends = [ 81 | GarnishAsset::class, 82 | CpAsset::class, 83 | ]; 84 | $cssFile = 'stylesheets/conditions-btest9098.css'; 85 | $jsFile = 'javascripts/conditions-atest3dc3r.js'; 86 | $this->js = [ 87 | $jsFile 88 | ]; 89 | 90 | $this->css = [ 91 | $cssFile 92 | ]; 93 | 94 | parent::init(); 95 | } 96 | 97 | // Protected Methods 98 | // ========================================================================= 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/elements/Conditions.php: -------------------------------------------------------------------------------- 1 | id(5)->one(); 136 | * 137 | * // Find all assets and order them by their filename: 138 | * $assets = Asset::find() 139 | * ->orderBy('filename') 140 | * ->all(); 141 | * ``` 142 | * 143 | * If you want to define custom criteria parameters for your elements, you can do so by overriding 144 | * this method and returning a custom query class. For example, 145 | * 146 | * ```php 147 | * class Product extends Element 148 | * { 149 | * public static function find() 150 | * { 151 | * // use ProductQuery instead of the default ElementQuery 152 | * return new ProductQuery(get_called_class()); 153 | * } 154 | * } 155 | * ``` 156 | * 157 | * You can also set default criteria parameters on the ElementQuery if you don’t have a need for 158 | * a custom query class. For example, 159 | * 160 | * ```php 161 | * class Customer extends ActiveRecord 162 | * { 163 | * public static function find() 164 | * { 165 | * return parent::find()->limit(50); 166 | * } 167 | * } 168 | * ``` 169 | * 170 | * @return ElementQueryInterface The newly created [[ElementQueryInterface]] instance. 171 | */ 172 | public static function find(): ElementQueryInterface 173 | { 174 | return new ElementQuery(get_called_class()); 175 | } 176 | 177 | /** 178 | * Defines the sources that elements of this type may belong to. 179 | * 180 | * @param string|null $context The context ('index' or 'modal'). 181 | * 182 | * @return array The sources. 183 | * @see sources() 184 | */ 185 | protected static function defineSources(string $context = null): array 186 | { 187 | $sources = []; 188 | 189 | return $sources; 190 | } 191 | 192 | // Public Methods 193 | // ========================================================================= 194 | 195 | /** 196 | * Returns the validation rules for attributes. 197 | * 198 | * Validation rules are used by [[validate()]] to check if attribute values are valid. 199 | * Child classes may override this method to declare different validation rules. 200 | * 201 | * More info: http://www.yiiframework.com/doc-2.0/guide-input-validation.html 202 | * 203 | * @return array 204 | */ 205 | public function rules() 206 | { 207 | return [ 208 | ['someAttribute', 'string'], 209 | ['someAttribute', 'default', 'value' => 'Some Default'], 210 | ]; 211 | } 212 | 213 | /** 214 | * Returns whether the current user can edit the element. 215 | * 216 | * @return bool 217 | */ 218 | public function getIsEditable(): bool 219 | { 220 | return true; 221 | } 222 | 223 | /** 224 | * Returns the field layout used by this element. 225 | * 226 | * @return FieldLayout|null 227 | */ 228 | public function getFieldLayout() 229 | { 230 | $tagGroup = $this->getGroup(); 231 | 232 | if ($tagGroup) { 233 | return $tagGroup->getFieldLayout(); 234 | } 235 | 236 | return null; 237 | } 238 | 239 | public function getGroup() 240 | { 241 | if ($this->groupId === null) { 242 | throw new InvalidConfigException('Tag is missing its group ID'); 243 | } 244 | 245 | if (($group = Craft::$app->getTags()->getTagGroupById($this->groupId)) === null) { 246 | throw new InvalidConfigException('Invalid tag group ID: '.$this->groupId); 247 | } 248 | 249 | return $group; 250 | } 251 | 252 | // Indexes, etc. 253 | // ------------------------------------------------------------------------- 254 | 255 | /** 256 | * Returns the HTML for the element’s editor HUD. 257 | * 258 | * @return string The HTML for the editor HUD 259 | */ 260 | public function getEditorHtml(): string 261 | { 262 | $html = Craft::$app->getView()->renderTemplateMacro('_includes/forms', 'textField', [ 263 | [ 264 | 'label' => Craft::t('app', 'Title'), 265 | 'siteId' => $this->siteId, 266 | 'id' => 'title', 267 | 'name' => 'title', 268 | 'value' => $this->title, 269 | 'errors' => $this->getErrors('title'), 270 | 'first' => true, 271 | 'autofocus' => true, 272 | 'required' => true 273 | ] 274 | ]); 275 | 276 | $html .= parent::getEditorHtml(); 277 | 278 | return $html; 279 | } 280 | 281 | // Events 282 | // ------------------------------------------------------------------------- 283 | 284 | /** 285 | * Performs actions before an element is saved. 286 | * 287 | * @param bool $isNew Whether the element is brand new 288 | * 289 | * @return bool Whether the element should be saved 290 | */ 291 | public function beforeSave(bool $isNew): bool 292 | { 293 | return true; 294 | } 295 | 296 | /** 297 | * Performs actions after an element is saved. 298 | * 299 | * @param bool $isNew Whether the element is brand new 300 | * 301 | * @return void 302 | */ 303 | public function afterSave(bool $isNew) 304 | { 305 | } 306 | 307 | /** 308 | * Performs actions before an element is deleted. 309 | * 310 | * @return bool Whether the element should be deleted 311 | */ 312 | public function beforeDelete(): bool 313 | { 314 | return true; 315 | } 316 | 317 | /** 318 | * Performs actions after an element is deleted. 319 | * 320 | * @return void 321 | */ 322 | public function afterDelete() 323 | { 324 | } 325 | 326 | /** 327 | * Performs actions before an element is moved within a structure. 328 | * 329 | * @param int $structureId The structure ID 330 | * 331 | * @return bool Whether the element should be moved within the structure 332 | */ 333 | public function beforeMoveInStructure(int $structureId): bool 334 | { 335 | return true; 336 | } 337 | 338 | /** 339 | * Performs actions after an element is moved within a structure. 340 | * 341 | * @param int $structureId The structure ID 342 | * 343 | * @return void 344 | */ 345 | public function afterMoveInStructure(int $structureId) 346 | { 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /src/migrations/Install.php: -------------------------------------------------------------------------------- 1 | driver = Craft::$app->getConfig()->getDb()->driver; 60 | if ($this->createTables()) { 61 | 62 | $this->createIndexes(); 63 | // $this->addForeignKeys(); 64 | // Refresh the db schema caches 65 | Craft::$app->db->schema->refresh(); 66 | $this->insertDefaultData(); 67 | } 68 | 69 | return true; 70 | } 71 | 72 | /** 73 | * This method contains the logic to be executed when removing this migration. 74 | * This method differs from [[down()]] in that the DB logic implemented here will 75 | * be enclosed within a DB transaction. 76 | * Child classes may implement this method instead of [[down()]] if the DB logic 77 | * needs to be within a transaction. 78 | * 79 | * @return boolean return a false value to indicate the migration fails 80 | * and should not proceed further. All other return values mean the migration succeeds. 81 | */ 82 | public function safeDown() 83 | { 84 | $this->driver = Craft::$app->getConfig()->getDb()->driver; 85 | $this->removeTables(); 86 | 87 | return true; 88 | } 89 | 90 | // Protected Methods 91 | // ========================================================================= 92 | 93 | /** 94 | * Creates the tables needed for the Records used by the plugin 95 | * 96 | * @return bool 97 | */ 98 | protected function createTables() 99 | { 100 | $tablesCreated = false; 101 | 102 | // conditions_conditionalsrecord table 103 | $tableSchema = Craft::$app->db->schema->getTableSchema('{{%conditions_conditionalsrecord}}'); 104 | if ($tableSchema === null) { 105 | $tablesCreated = true; 106 | $this->createTable( 107 | '{{%conditions_conditionalsrecord}}', 108 | [ 109 | 'id' => $this->primaryKey(), 110 | 'fieldLayoutId' => $this->integer()->notNull(), 111 | 'expressions' => $this->text()->notNull(), 112 | 'dateCreated' => $this->dateTime()->notNull(), 113 | 'dateUpdated' => $this->dateTime()->notNull(), 114 | 'uid' => $this->uid(), 115 | 'siteId' => $this->integer()->notNull()->defaultValue(1), 116 | 'some_field' => $this->string(255)->notNull()->defaultValue('') 117 | ] 118 | ); 119 | } 120 | 121 | return $tablesCreated; 122 | } 123 | 124 | /** 125 | * Creates the indexes needed for the Records used by the plugin 126 | * 127 | * @return void 128 | */ 129 | protected function createIndexes() 130 | { 131 | // conditions_conditionalsrecord table 132 | /* $this->createIndex( 133 | $this->db->getIndexName( 134 | '{{%conditions_conditionalsrecord}}', 135 | 'some_field', 136 | true 137 | ), 138 | 139 | '{{%conditions_conditionalsrecord}}', 140 | 'some_field', 141 | true 142 | ); 143 | */ 144 | // Additional commands depending on the db driver 145 | switch ($this->driver) { 146 | case DbConfig::DRIVER_MYSQL: 147 | break; 148 | case DbConfig::DRIVER_PGSQL: 149 | break; 150 | } 151 | } 152 | 153 | /** 154 | * Creates the foreign keys needed for the Records used by the plugin 155 | * 156 | * @return void 157 | */ 158 | protected function addForeignKeys() 159 | { 160 | // conditions_conditionalsrecord table 161 | $this->addForeignKey( 162 | $this->db->getForeignKeyName('{{%conditions_conditionalsrecord}}', 'siteId'), 163 | '{{%conditions_conditionalsrecord}}', 164 | 'siteId', 165 | '{{%sites}}', 166 | 'id', 167 | 'CASCADE', 168 | 'CASCADE' 169 | ); 170 | } 171 | 172 | /** 173 | * Populates the DB with the default data. 174 | * 175 | * @return void 176 | */ 177 | protected function insertDefaultData() 178 | { 179 | } 180 | 181 | /** 182 | * Removes the tables needed for the Records used by the plugin 183 | * 184 | * @return void 185 | */ 186 | protected function removeTables() 187 | { 188 | // conditions_conditionalsrecord table 189 | $this->dropTableIfExists('{{%conditions_conditionalsrecord}}'); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/models/ConditionalsModel.php: -------------------------------------------------------------------------------- 1 | 'Some Default'], 62 | ]; 63 | } 64 | protected function defineAttributes() 65 | { 66 | return array( 67 | 'id' => AttributeType::Number, 68 | 'fieldLayoutId' => AttributeType::Number, 69 | 'expressions' => AttributeType::Mixed, 70 | ); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/records/ConditionalsRecord.php: -------------------------------------------------------------------------------- 1 | array(AttributeType::Number), 64 | 'expressions' => array(AttributeType::Mixed), 65 | ); 66 | 67 | } 68 | /** 69 | * @access public 70 | * @return array 71 | */ 72 | 73 | public function defineRelations() 74 | { 75 | return array( 76 | 'fieldLayout' => array( 77 | static::BELONGS_TO, 78 | 'FieldLayoutRecord', 79 | 'fieldLayoutId', 80 | 'onDelete' => static::CASCADE, 81 | ), 82 | ); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/resources/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkshakeStudio/craft-conditions/1c334a49e908d562ea1459c5b4726d2cb90f5ec0/src/resources/.DS_Store -------------------------------------------------------------------------------- /src/resources/javascripts/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkshakeStudio/craft-conditions/1c334a49e908d562ea1459c5b4726d2cb90f5ec0/src/resources/javascripts/.DS_Store -------------------------------------------------------------------------------- /src/resources/javascripts/conditions-atest3dc3r.js: -------------------------------------------------------------------------------- 1 | ! function (e) { 2 | 3 | function t(s) { 4 | if (i[s]) return i[s].exports; 5 | var n = i[s] = { 6 | exports: {}, 7 | id: s, 8 | loaded: !1 9 | }; 10 | return e[s].call(n.exports, n, n.exports, t), n.loaded = !0, n.exports 11 | } 12 | var i = {}; 13 | return t.m = e, t.c = i, t.p = "javascripts/", t(0) 14 | }([function (e, t, i) { 15 | 16 | e.exports = i(1) 17 | }, function (e, t, i) { 18 | "use strict"; 19 | ! function (e) { 20 | /*** action */ 21 | return !!e.Craft && void(Craft.ConditionsPlugin = { 22 | FieldLayoutDesigner: i(2), 23 | ConditionalsRenderer: i(4), 24 | ASSET_SOURCE_HANDLE: "assetSource", 25 | CATEGORY_GROUP_HANDLE: "categoryGroup", 26 | TAG_GROUP_HANDLE: "tagGroup", 27 | GLOBAL_SET_HANDLE: "globalSet", 28 | ENTRY_TYPE_HANDLE: "entryType", 29 | SECTION_HANDLE: "section", 30 | USERS_HANDLE: "users", 31 | FIELDS_HANDLE: "field", 32 | SOLSPACE_CALENDAR_HANDLE: "solspace-calendar", 33 | ASSET_SOURCE_ACTION: "volumes/save-volume", 34 | CATEGORY_ACTION: "categories/save-category", 35 | CATEGORY_GROUP_ACTION: "categories/save-group", 36 | TAG_ACTION: "tag-manager/save-tag", 37 | TAG_GROUP_ACTION: "tags/save-tag-group", 38 | GLOBAL_SET_CONTENT_ACTION: "globals/save-content", 39 | GLOBAL_SET_ACTION: "globals/save-set", 40 | ENTRY_ACTION: "entries/save-entry", 41 | ENTRY_REVISION_ACTION: "entry-revisions/save-draft", 42 | ENTRY_TYPE_ACTION: "sections/save-entry-type", 43 | USERS_ACTION: "users/save-user", 44 | USERS_FIELDS_ACTION: "users/save-field-layout", 45 | FIELDS_ACTION: "fields/save-field", 46 | SOLSPACE_CALENDAR_EVENTS_ACTION: "calendar/events/save-event", 47 | SOLSPACE_CALENDAR_SETTINGS_ACTION: "calendar/calendars/save-calendar", 48 | SOLSPACE_CALENDAR_LEGACY_SETTINGS_ACTION: "calendar/settings/save-settings", 49 | RENDER_CONTEXT: "render", 50 | LAYOUT_DESIGNER_CONTEXT: "fld", 51 | FIELD_DESIGNER_CONTEXT: "field", 52 | init: function (e) { 53 | this.data = e, this.initPrimaryForm(); 54 | 55 | }, 56 | initPrimaryForm: function () { 57 | this.destroyPrimaryForm(), Garnish.requestAnimationFrame(function () { 58 | 59 | var e = Craft.cp.$primaryForm && Craft.cp.$primaryForm.length ? Craft.cp.$primaryForm : $("#content form:first"); 60 | 61 | e && e.length && (this.primaryForm = this.initForm(e)); 62 | 63 | }.bind(this)); 64 | 65 | }, 66 | destroyPrimaryForm: function () { 67 | this.primaryForm && (this.primaryForm.destroy(), delete this.primaryForm) 68 | }, 69 | initElementEditor: function (e) { 70 | //alert('qqqqq'); 71 | //console.log(e); 72 | var t = this.getConditionals(e); 73 | 74 | if (!t) return !1; 75 | var i = (new Date).getTime(), 76 | s = function () { 77 | var e = (new Date).getTime(), 78 | n = $(".elementeditor:last"), 79 | a = n.length > 0 && n.closest(".hud"), 80 | r = !!(a && a.length > 0) && a.data("elementEditor"), 81 | o = !!r && r.$form; 82 | o ? (r._conditionsForm = new this.ConditionalsRenderer(o, t), r.hud.on("hide", $.proxy(this.destroyElementEditorForm, this, r))) : e - i < 2e3 && Garnish.requestAnimationFrame(s) 83 | }.bind(this); 84 | s() 85 | }, 86 | destroyElementEditorForm: function (e) { 87 | var t = e._conditionsForm || null; 88 | t && (t.destroy(), delete e._conditionsForm) 89 | }, 90 | initForm: function (e) { 91 | 92 | var t = this.getElementSourceFromForm(e); 93 | 94 | i = !!t && this.getFormContext(e); 95 | /* 96 | alert('ddd'); 97 | console.log(e); 98 | console.log(t); 99 | */ 100 | 101 | if (!t || !i) return !1; 102 | var s = t.type + (t.id ? ":" + t.id : ""), 103 | n = this.getConditionals(s); 104 | 105 | switch (i) { 106 | case this.LAYOUT_DESIGNER_CONTEXT: 107 | 108 | return new this.FieldLayoutDesigner(e, n); 109 | case this.FIELD_DESIGNER_CONTEXT: 110 | return null; 111 | case this.RENDER_CONTEXT: 112 | return n ? new this.ConditionalsRenderer(e, n) : null 113 | } 114 | return null 115 | }, 116 | getConditionals: function (e) { 117 | //alert('qqqqqxx'); 118 | console.log(e); 119 | // alert('getConditionals'); 120 | // console.log('xxxx'); 121 | // console.log(e); 122 | // console.log(JSON.parse(this.data.conditionals[e])); 123 | return e ? this.data.conditionals && this.data.conditionals.hasOwnProperty(e) ? JSON.parse(this.data.conditionals[e]): null : this.data.conditionals || {} 124 | }, 125 | getToggleFields: function () { 126 | return this.data.toggleFields ? this.data.toggleFields : [] 127 | }, 128 | getToggleFieldById: function (e) { 129 | e = parseInt(e); 130 | for (var t = this.getToggleFields(), i = t.length, s = 0; s < i; ++s) 131 | if (parseInt(t[s].id) === e) return t[s]; 132 | return !1 133 | }, 134 | getFieldIds: function () { 135 | return this.data.fieldIds ? this.data.fieldIds : {} 136 | }, 137 | getFieldIdByHandle: function (e) { 138 | var t = this.getFieldIds(); 139 | return !(!t || !t.hasOwnProperty(e)) && t[e] 140 | }, 141 | getToggleFieldTypes: function () { 142 | return this.data.toggleFieldTypes ? this.data.toggleFieldTypes : [] 143 | }, 144 | getElementSourceFromForm: function (e) { 145 | 146 | if (e.data("elementEditor")) return !1; 147 | 148 | var t = e.find('input[type="hidden"][name="namespace"]').val(); 149 | t && (t += "-"); 150 | var i, s, n = e.find('input[type="hidden"][name="action"]').val(); 151 | 152 | switch (n) { 153 | case this.ASSET_SOURCE_ACTION: 154 | i = this.ASSET_SOURCE_HANDLE, s = 'input[type="hidden"][name="volumeId"]'; 155 | break; 156 | case this.CATEGORY_ACTION: 157 | case this.CATEGORY_GROUP_ACTION: 158 | i = this.CATEGORY_GROUP_HANDLE, s = 'input[type="hidden"][name="groupId"]'; 159 | break; 160 | case this.GLOBAL_SET_CONTENT_ACTION: 161 | case this.GLOBAL_SET_ACTION: 162 | i = this.GLOBAL_SET_HANDLE, s = 'input[type="hidden"][name="setId"]'; 163 | break; 164 | case this.ENTRY_ACTION: 165 | case this.ENTRY_REVISION_ACTION: 166 | var a = e.find('select#entryType, input[type="hidden"][name="entryTypeId"], input[type="hidden"][name="typeId"], #' + t + "entryType"); 167 | i = a.length ? this.ENTRY_TYPE_HANDLE : this.SECTION_HANDLE, s = a.length ? 'select#entryType, input[type="hidden"][name="entryTypeId"], input[type="hidden"][name="typeId"], #' + t + "entryType" : 'input[type="hidden"][name="sectionId"], #' + t + "section"; 168 | break; 169 | case this.ENTRY_TYPE_ACTION: 170 | i = this.ENTRY_TYPE_HANDLE, s = 'input[type="hidden"][name="entryTypeId"]'; 171 | 172 | break; 173 | case this.TAG_ACTION: 174 | case this.TAG_GROUP_ACTION: 175 | i = this.TAG_GROUP_HANDLE, s = 'input[type="hidden"][name="tagGroupId"], input[type="hidden"][name="groupId"]'; 176 | break; 177 | case this.USERS_ACTION: 178 | case this.USERS_FIELDS_ACTION: 179 | i = this.USERS_HANDLE; 180 | break; 181 | case this.FIELDS_ACTION: 182 | i = this.FIELDS_HANDLE, s = 'input[type="hidden"][name="fieldId"]'; 183 | break; 184 | case this.SOLSPACE_CALENDAR_LEGACY_SETTINGS_ACTION: 185 | i = this.SOLSPACE_CALENDAR_HANDLE; 186 | break; 187 | case this.SOLSPACE_CALENDAR_EVENTS_ACTION: 188 | i = this.SOLSPACE_CALENDAR_HANDLE, s = 'input[type="hidden"][name="calendarEvent[calendarId]"]'; 189 | break; 190 | case this.SOLSPACE_CALENDAR_SETTINGS_ACTION: 191 | i = this.SOLSPACE_CALENDAR_HANDLE, s = 'input[type="hidden"][name="calendarId"]'; 192 | break; 193 | case this.COMMERCE_PRODUCT_TYPE_ACTION: 194 | case this.COMMERCE_PRODUCT_ACTION: 195 | i = this.COMMERCE_PRODUCT_TYPE_HANDLE, s = 'input[type="hidden"][name="typeId"]' 196 | } 197 | /* code added by firoz */ 198 | 199 | 200 | 201 | /* code added by firoz end */ 202 | return !!i && { 203 | type: i, 204 | id: !!s && 0 | e.find(s).val() 205 | } 206 | }, 207 | getFormContext: function (e) { 208 | 209 | if (e.data("elementEditor")) return !1; 210 | var t = e.find('input[type="hidden"][name="action"]').val(); 211 | /**** hidden action field value **/ 212 | switch (t) { 213 | case this.GLOBAL_SET_CONTENT_ACTION: 214 | case this.ENTRY_ACTION: 215 | case this.ENTRY_REVISION_ACTION: 216 | case this.TAG_ACTION: 217 | case this.CATEGORY_ACTION: 218 | case this.USERS_ACTION: 219 | case this.SOLSPACE_CALENDAR_EVENTS_ACTION: 220 | case this.COMMERCE_PRODUCT_ACTION: 221 | return this.RENDER_CONTEXT; 222 | case this.ASSET_SOURCE_ACTION: 223 | case this.CATEGORY_GROUP_ACTION: 224 | case this.GLOBAL_SET_ACTION: 225 | case this.ENTRY_TYPE_ACTION: 226 | case this.TAG_GROUP_ACTION: 227 | case this.USERS_FIELDS_ACTION: 228 | case this.SOLSPACE_CALENDAR_LEGACY_SETTINGS_ACTION: 229 | case this.SOLSPACE_CALENDAR_SETTINGS_ACTION: 230 | case this.COMMERCE_PRODUCT_TYPE_ACTION: 231 | return this.LAYOUT_DESIGNER_CONTEXT; 232 | case this.FIELDS_ACTION: 233 | return this.FIELD_DESIGNER_CONTEXT 234 | } 235 | return !1 236 | } 237 | }) 238 | }(window), window.jQuery && 239 | /*! 240 | * jQuery.fn.hasAttr() 241 | * 242 | * Copyright 2011, Rick Waldron 243 | * Licensed under MIT license. 244 | * 245 | */ 246 | ! function (e) { 247 | e.fn.hasAttr = function (e) { 248 | for (var t = 0, i = this.length; t < i; t++) 249 | if (void 0 !== this.attr(e)) return !0; 250 | return !1 251 | } 252 | }(jQuery) 253 | }, 254 | 255 | function (e, t, i) { 256 | "use strict"; 257 | 258 | function s(e, t) { 259 | if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function") 260 | } 261 | var n = function () { 262 | function e(e, t) { 263 | for (var i = 0; i < t.length; i++) { 264 | var s = t[i]; 265 | s.enumerable = s.enumerable || !1, s.configurable = !0, "value" in s && (s.writable = !0), Object.defineProperty(e, s.key, s) 266 | } 267 | } 268 | return function (t, i, s) { 269 | return i && e(t.prototype, i), s && e(t, s), t 270 | } 271 | }(), 272 | a = i(3); 273 | 274 | e.exports = function () { 275 | 276 | function e(t, i) { 277 | 278 | s(this, e), t && t.length && (this.$el = t, this.conditionals = i, this.settings = { 279 | formSelector: "form:first", 280 | fieldSettingsSelector: "a.settings", 281 | fieldSelector: ".fld-field", 282 | tabSelector: ".fld-tabs .fld-tab" 283 | }, this.templates = { 284 | input: function (e) { 285 | return '' 286 | }, 287 | modal: function () { 288 | return '