├── help ├── Migrations_table.png ├── Comparison_source.jpg ├── Log_changes_source.png ├── Setup_page_source.jpg ├── Setup_page_target.jpg ├── Installable_migration.png ├── Migration_page_source.jpg ├── Migration_page_target.jpg ├── Preview_install_data.png ├── Setup_page _target_v3.jpg ├── Setup_page_source_v3.jpg ├── Setup_page_target_v3.jpg ├── Migration_source_example.png ├── Migrations_table_target.png ├── Migration_page_source_full_v3.jpg ├── Migration_page_source_full_v4.jpg └── Preview_differences_selector.jpg ├── RuntimeFields ├── dbMigrateRuntimeReady.js ├── dbMigrateRuntimeControl.js ├── dbMigrateRuntimeAction.js ├── dbMigrateRuntimeReady.php ├── dbMigrateRuntimeControl.php └── dbMigrateRuntimeAction.php ├── .gitattributes ├── .gitignore ├── ProcessDbMigrate.info.php ├── HannaMigrate ├── README.md └── HannaMigrate.module.php ├── ProcessDbMigrate.js ├── readme.md ├── ProcessDbMigrate.css ├── old ├── data.json └── migration.json ├── bootstrap ├── old │ ├── data.json │ └── migration.json └── new │ ├── migration.json │ └── data.json ├── DbMigrateHelp.php ├── DbComparisonPage.class.php ├── FieldtypeDbMigrateRuntime.module └── new ├── migration.json └── data.json /help/Migrations_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Migrations_table.png -------------------------------------------------------------------------------- /help/Comparison_source.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Comparison_source.jpg -------------------------------------------------------------------------------- /help/Log_changes_source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Log_changes_source.png -------------------------------------------------------------------------------- /help/Setup_page_source.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Setup_page_source.jpg -------------------------------------------------------------------------------- /help/Setup_page_target.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Setup_page_target.jpg -------------------------------------------------------------------------------- /help/Installable_migration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Installable_migration.png -------------------------------------------------------------------------------- /help/Migration_page_source.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Migration_page_source.jpg -------------------------------------------------------------------------------- /help/Migration_page_target.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Migration_page_target.jpg -------------------------------------------------------------------------------- /help/Preview_install_data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Preview_install_data.png -------------------------------------------------------------------------------- /help/Setup_page _target_v3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Setup_page _target_v3.jpg -------------------------------------------------------------------------------- /help/Setup_page_source_v3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Setup_page_source_v3.jpg -------------------------------------------------------------------------------- /help/Setup_page_target_v3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Setup_page_target_v3.jpg -------------------------------------------------------------------------------- /help/Migration_source_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Migration_source_example.png -------------------------------------------------------------------------------- /help/Migrations_table_target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Migrations_table_target.png -------------------------------------------------------------------------------- /help/Migration_page_source_full_v3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Migration_page_source_full_v3.jpg -------------------------------------------------------------------------------- /help/Migration_page_source_full_v4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Migration_page_source_full_v4.jpg -------------------------------------------------------------------------------- /help/Preview_differences_selector.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaTunes/ProcessDbMigrate/HEAD/help/Preview_differences_selector.jpg -------------------------------------------------------------------------------- /RuntimeFields/dbMigrateRuntimeReady.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $(".Inputfield_dbMigrateRuntimeReady .description").html(ProcessWire.config.dbMigrateRuntimeReady.description); 3 | }); -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows thumbnail cache files 2 | Thumbs.db 3 | ehthumbs.db 4 | ehthumbs_vista.db 5 | 6 | # Folder config file 7 | Desktop.ini 8 | 9 | # Recycle Bin used on file shares 10 | $RECYCLE.BIN/ 11 | 12 | # Windows Installer files 13 | *.cab 14 | *.msi 15 | *.msm 16 | *.msp 17 | 18 | # Windows shortcuts 19 | *.lnk 20 | 21 | # ========================= 22 | # Operating System Files 23 | # ========================= 24 | 25 | # Code Editors 26 | *.code-workspace 27 | -------------------------------------------------------------------------------- /RuntimeFields/dbMigrateRuntimeControl.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | 3 | $('#lock-page').click(function (event) { 4 | if (!confirm(ProcessWire.config.dbMigrateRuntimeControl.lock)) { 5 | event.preventDefault(); 6 | } 7 | }); 8 | 9 | $('#unlock-page').click(function (event) { 10 | if (!confirm(ProcessWire.config.dbMigrateRuntimeControl.unlock)) { 11 | event.preventDefault(); 12 | } 13 | }); 14 | 15 | }); -------------------------------------------------------------------------------- /RuntimeFields/dbMigrateRuntimeAction.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | 3 | $('#remove_files').click(function (event) { 4 | if (!confirm(ProcessWire.config.dbMigrateRuntimeAction.confirmRemoveFiles)) { 5 | event.preventDefault(); 6 | } 7 | }); 8 | 9 | $('#install_migration, #uninstall_migration').click(function (event) { 10 | if (!confirm(ProcessWire.config.dbMigrateRuntimeAction.confirmInstall)) { 11 | event.preventDefault(); 12 | } 13 | }); 14 | 15 | $('#remove_old').click(function (event) { 16 | if (!confirm(ProcessWire.config.dbMigrateRuntimeAction.confirmRemoveOld)) { 17 | event.preventDefault(); 18 | } 19 | }); 20 | 21 | }); -------------------------------------------------------------------------------- /ProcessDbMigrate.info.php: -------------------------------------------------------------------------------- 1 | false, // true if module is permanent and thus not uninstallable (3rd party modules should specify 'false') 6 | 'title' => 'ProcessDbMigrate', 7 | 'summary' => 'Manage migrations via the PW GUI', 8 | 'comments' => 'Document (manually or by automated change tracking) and manage migrations. Allow roll-back and database comparisons.', 9 | 'author' => 'Mark Evens with contributions from Jonathan Lahijani', 10 | 'version' => "2.0.26", 11 | // Versions >= 0.1.0 use FieldtypeDbMigrateRuntime not RuntimeOnly. Versions >= 1.0.0 have change tracking (scope at individual migration level for v2.0.0+). 12 | 'autoload' => true, 13 | 'singular' => true, 14 | 'page' => array( //install/uninstall a page for this process automatically 15 | 'name' => 'dbmigrations', //name of page to create 16 | 'parent' => 'setup', // parent name (under admin) 17 | 'title' => 'Database Migrations', // title of page 18 | ), 19 | 'icon' => 'upload', 20 | 'requires' => 'PHP>=8.0', 'ProcessWire>=3.0.172', 21 | 'installs' => 'FieldtypeDbMigrateRuntime', // Runtime field type for use with this module 22 | 'permission' => 'admin-dbMigrate', // ToDo refine permissions? 23 | ); -------------------------------------------------------------------------------- /RuntimeFields/dbMigrateRuntimeReady.php: -------------------------------------------------------------------------------- 1 | ready(); // NB Removed - should have already been called by ProcessDbMigrate before this file is included 9 | $config->js('dbMigrateRuntimeReady', [ 10 | 'description' => sprintf(__('Contents of %1$s%2$s/ready.php'), $page->migrationsPath, $page->name), 11 | ]); 12 | $readyFile = "{$page->migrationsPath}/{$page->name}/ready.php"; 13 | if(file_exists($readyFile)) { 14 | echo '
' . htmlspecialchars(file_get_contents($readyFile)) . '
'; 15 | } else { 16 | $out = __("NO FILE") . '
'; 17 | $out .= sprintf(__('Create the file - %1$s%2$s/ready.php - if you wish to add hooks.'), $page->migrationsPath, $page->name) . '
'; 18 | $out .= sprintf(__("Remember to use %s as the first line."), htmlspecialchars(''; 19 | $out .= __("Hooks will be specific to this migration page - use \$this to reference it.") . '
'; 20 | $out .= __("See the help file for more details."); 21 | echo $out; 22 | } -------------------------------------------------------------------------------- /HannaMigrate/README.md: -------------------------------------------------------------------------------- 1 | # HannaMigrate 2 | ## Migrate PW hanna codes 3 | 4 | Provides 2 methods exportAll() and importAll() 5 | 6 | ### Simple usage: 7 | 8 | 1. Install the module. 9 | 10 | 2. Use TracyDebugger console in the source database to: 11 | ```` 12 | $hannaMig = $modules->get('HannaMigrate'); 13 | $hannaMig->exportAll(string $optional_migration_name = null); 14 | ```` 15 | where optional_migration_name is a name of a related migration, 16 | if you are using ProcessDbMigrate. 17 | Otherwise leave blank and the data file will be in assets/migrations/hanna-codes/data.json. 18 | 19 | If you are using ProcessDbMigrate, the data file will be in the directory holding the migration (or its parent, if no migration name is specified). 20 | 21 | 3. Copy the data file to the target environment. 22 | 4. Then use TracyDebugger console in the target database to: 23 | ```` 24 | $hannaMig = $modules->get('HannaMigrate'); 25 | $hannaMig->importAll(string $optional_migration_name = null, bool $overwrite = false, bool $delete = false); 26 | ```` 27 | where optional_migration_name is the name of the related migration, 28 | if you are using ProcessDbMigrate. 29 | Otherwise leave blank and the data file will be in assets/migrations/hanna-codes/data.json. 30 | The overwrite parameter is optional and defaults to false. If true, it will overwrite existing hanna codes. 31 | The delete parameter is optional and defaults to false. If true, it will delete existing hanna codes if they do not exist in the import. 32 | 33 | (Do this while on the Hanna Codes page, then refresh the page to see the results and any error messages). 34 | 35 | You could also use the methods in your own code. I may look to integrating it in ProcessDbMigrate. 36 | -------------------------------------------------------------------------------- /ProcessDbMigrate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Abbreviate notes and provide popup 3 | * 4 | * @param event 5 | */ 6 | function shortNotes(event) { 7 | // console.log($(this).html()); 8 | if ($(this).html().length > 200) { 9 | var note = $(this).html(); 10 | var shortNote = $(this).html().substring(0, 150) + '... (click for more)'; 11 | $(this).html(shortNote); 12 | $(this).after('
' + note + '
'); 13 | event.stopImmediatePropagation(); 14 | } 15 | } 16 | 17 | /** 18 | * Pop-out for help 19 | * 20 | * @param event 21 | * @returns {boolean} 22 | */ 23 | function popOut(event) { 24 | var link = $(this).attr('href'); 25 | window.open(link, 'popup', 'resizable= 1, height = 800, width=1200, scrollbars=1'); 26 | return false; 27 | } 28 | 29 | $(document).ready(function () { 30 | 31 | $('.AdminDataTable .abbreviate').each(shortNotes); 32 | 33 | if($('#ProcessDbMigrate').length) { 34 | $('#ProcessDbMigrate').WireTabs({ 35 | items: $('.WireTab') 36 | }); 37 | } 38 | 39 | var arr = window.location.href.split('/'); 40 | var seg = arr[arr.length-1]; 41 | if (seg.startsWith("#")) $(seg).click(); 42 | 43 | $('.ProcessPageEdit-template-DbMigration #delete_page').click(function (event) { 44 | if ($(this).prop('checked')) { 45 | if (!confirm(ProcessWire.config.ProcessDbMigrate.confirmDelete)) { 46 | event.preventDefault(); 47 | } 48 | } 49 | }); 50 | $('.ProcessPageEdit-template-DbComparison #delete_page').click(function (event) { 51 | if ($(this).prop('checked')) { 52 | if (!confirm(ProcessWire.config.ProcessDbMigrate.confirmDelete)) { 53 | event.preventDefault(); 54 | } 55 | } 56 | }); 57 | 58 | $(document).on('click', 'a.popout-help', popOut); 59 | 60 | }); -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ProcessDbMigrate 2 | ## Introduction 3 | This module is designed to ease the problem of migrating database changes from one PW environment to another. 4 | I wanted something to achieve the following: 5 | 6 | - To allow development to take place (in a separate environment on a copy of the live database, or on a test database with the same structure) using the Admin UI. When finished, to permit a declarative approach to defining the migration and implementing it (again in the UI). 7 | - To allow testing of the migration in a test environment on a copy of the live database. 8 | - To allow roll-back of a migration if installation causes problems (ideally while testing rather than after implementation!). 9 | - To provide a record of changes applied. 10 | - Although not originally intended, the module I developed also allows the selective reversion of parts of the database by exporting migration data from a backup copy. Also, if changes are made directly on the live system (presumably simple, low-risk mods – although not best practice), it allows reverse migration to the development system in a similar fashion. 11 | 12 | While numerous improvements have been made since the early versions, I should emphasise that what I have built is still 'alpha'. Please test it thoroughly before using it on a live system and take frequent backups. 13 | I have used it on a number of sites, but I have not tested it on all possible configurations. 14 | 15 | This version incorporates automated tracking of changes - your migration specification is built for you as you make changes in the development system! It also alerts you 16 | to circular dependencies and allows you to resolve them. If you ignore them then the installation will probably still work the system will make up to 3 tries before giving up. 17 | 18 | ## Installation 19 | Place the ProcessDbMigrate folder in your site/modules directory or install from the PW modules library. PW version 3.0.210 or later is recommended. Please let me know if it works with earlier versions. 20 | 21 | Having satisfied the dependencies, install the module. 22 | 23 | Note that if your admin path is something other than /processwire/, the module will change it's bootstrap json file to reflect this. 24 | If you attempt to migrate to a site with a different admin path then it may appear that the migration does not fully install, although it might work. 25 | 26 | ## Updating 27 | Use the PW modules library to update the module (check for updates in the module information). 28 | Note that if you have hacked the bootstrap json, then updating will overwrite your hack. 29 | 30 | ## Usage 31 | I think the usage is quite logical, but it is fairly complex, so please read the [help file](https://metatunes.github.io/DbMigrate/help.html) first. -------------------------------------------------------------------------------- /ProcessDbMigrate.css: -------------------------------------------------------------------------------- 1 | 2 | /* modify page edit in target environments */ 3 | #Inputfield_dbMigrateLogChanges .noDisplay { display: none; } 4 | #Inputfield_dbMigrateRuntimeAction .full-width { width: 100%; } 5 | 6 | /* Special repeater rows */ 7 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem:not(.InputfieldRepeaterDeletePending):not(.InputfieldRepeaterItemRequested) > label { background-color: transparent; outline: 1px solid transparent !important; } 8 | 9 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.fields-new:not(.InputfieldRepeaterDeletePending):not(.InputfieldRepeaterItemRequested) > label { background-image: linear-gradient(to right, #615a5a, #295f1b 50%); } 10 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.fields-changed:not(.InputfieldRepeaterDeletePending):not(.InputfieldRepeaterItemRequested) > label { background-image: linear-gradient(to right, #62be48, #295f1b 25%); } 11 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.fields-removed:not(.InputfieldRepeaterDeletePending):not(.InputfieldRepeaterItemRequested) > label { background-image: linear-gradient(to right, #295f1b, #433e3e 50%); } 12 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.templates-new:not(.InputfieldRepeaterDeletePending):not(.InputfieldRepeaterItemRequested) > label { background-image: linear-gradient(to right, #615a5a, #845333 50%); } 13 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.templates-changed:not(.InputfieldRepeaterDeletePending):not(.InputfieldRepeaterItemRequested) > label { background-image: linear-gradient(to right, #dc8f62, #845333 25%); } 14 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.templates-removed:not(.InputfieldRepeaterDeletePending):not(.InputfieldRepeaterItemRequested) > label { background-image: linear-gradient(to right, #845333, #433e3e 50%); } 15 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.pages-new:not(.InputfieldRepeaterDeletePending):not(.InputfieldRepeaterItemRequested) > label { background-image: linear-gradient(to right, #615a5a, #0e54d7 50%); } 16 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.pages-changed:not(.InputfieldRepeaterDeletePending):not(.InputfieldRepeaterItemRequested) > label { background-image: linear-gradient(to right, #9ab0dc, #0e54d7 25%); } 17 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.pages-removed:not(.InputfieldRepeaterDeletePending):not(.InputfieldRepeaterItemRequested) > label { background-image: linear-gradient(to right, #0e54d7, #433e3e 50%); } 18 | 19 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.has-wand > label .InputfieldRepeaterItemLabel:before { font-family:'FontAwesome'; color: #e0cfe8; content:"\f0d0"; display:inline-block; margin-right:6px; } 20 | #wrap_Inputfield_dbMigrateItem .InputfieldRepeaterItem.has-arrows > label .InputfieldRepeaterItemLabel:before { font-family:'FontAwesome'; color: #e0cfe8; content:"\f0d0\f160"; display:inline-block; margin-right:6px; } 21 | 22 | /* Increase or decrease row height on mouse click */ 23 | .migration-table-text { 24 | max-width: 20vw; 25 | white-space: nowrap; 26 | overflow: hidden; 27 | text-overflow: ellipsis; 28 | } 29 | 30 | .migration-table-text:hover { 31 | max-width: 20vw; 32 | white-space: normal; 33 | overflow: visible; 34 | text-overflow: clip; 35 | } 36 | 37 | tr:has(.migration-table-text):hover { 38 | background-color: #dbde9e; 39 | } -------------------------------------------------------------------------------- /old/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "pages": { 4 | "removed": { 5 | "template=DbMigrations, include=all": [] 6 | } 7 | } 8 | }, 9 | { 10 | "templates": { 11 | "removed": { 12 | "DbMigrations": [] 13 | } 14 | } 15 | }, 16 | { 17 | "templates": { 18 | "removed": { 19 | "DbMigration": [] 20 | } 21 | } 22 | }, 23 | { 24 | "templates": { 25 | "removed": { 26 | "DbComparison": [] 27 | } 28 | } 29 | }, 30 | { 31 | "fields": { 32 | "removed": { 33 | "dbMigrateRuntimeReady": [] 34 | } 35 | } 36 | }, 37 | { 38 | "fields": { 39 | "removed": { 40 | "dbMigrateRuntimeAction": [] 41 | } 42 | } 43 | }, 44 | { 45 | "fields": { 46 | "removed": { 47 | "dbMigrateRuntimeControl": [] 48 | } 49 | } 50 | }, 51 | { 52 | "fields": { 53 | "removed": { 54 | "dbMigrateSnippets": [] 55 | } 56 | } 57 | }, 58 | { 59 | "templates": { 60 | "removed": { 61 | "repeater_dbMigrateSnippets": [] 62 | } 63 | } 64 | }, 65 | { 66 | "fields": { 67 | "removed": { 68 | "dbMigrateRestrictFields": [] 69 | } 70 | } 71 | }, 72 | { 73 | "fields": { 74 | "removed": { 75 | "dbMigrateAdditionalDetails": [] 76 | } 77 | } 78 | }, 79 | { 80 | "fields": { 81 | "removed": { 82 | "dbMigrateSummary": [] 83 | } 84 | } 85 | }, 86 | { 87 | "fields": { 88 | "removed": { 89 | "dbMigrateLogChanges": [] 90 | } 91 | } 92 | }, 93 | { 94 | "fields": { 95 | "removed": { 96 | "dbMigrateTrackingScope": [] 97 | } 98 | } 99 | }, 100 | { 101 | "fields": { 102 | "removed": { 103 | "dbMigrateFieldTracking": [] 104 | } 105 | } 106 | }, 107 | { 108 | "fields": { 109 | "removed": { 110 | "dbMigrateTemplateTracking": [] 111 | } 112 | } 113 | }, 114 | { 115 | "fields": { 116 | "removed": { 117 | "dbMigratePageTracking": [] 118 | } 119 | } 120 | }, 121 | { 122 | "fields": { 123 | "removed": { 124 | "dbMigrateTrackingScope_END": [] 125 | } 126 | } 127 | }, 128 | { 129 | "fields": { 130 | "removed": { 131 | "dbMigrateItem": [] 132 | } 133 | } 134 | }, 135 | { 136 | "fields": { 137 | "removed": { 138 | "dbMigrateComparisonItem": [] 139 | } 140 | } 141 | }, 142 | { 143 | "templates": { 144 | "removed": { 145 | "repeater_dbMigrateItem": [] 146 | } 147 | } 148 | }, 149 | { 150 | "templates": { 151 | "removed": { 152 | "repeater_dbMigrateComparisonItem": [] 153 | } 154 | } 155 | }, 156 | { 157 | "fields": { 158 | "removed": { 159 | "dbMigrateOldName": [] 160 | } 161 | } 162 | }, 163 | { 164 | "fields": { 165 | "removed": { 166 | "dbMigrateName": [] 167 | } 168 | } 169 | }, 170 | { 171 | "fields": { 172 | "removed": { 173 | "dbMigrateAction": [] 174 | } 175 | } 176 | }, 177 | { 178 | "fields": { 179 | "removed": { 180 | "dbMigrateType": [] 181 | } 182 | } 183 | } 184 | ] -------------------------------------------------------------------------------- /bootstrap/old/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "pages": { 4 | "removed": { 5 | "template=DbMigrations, include=all": [] 6 | } 7 | } 8 | }, 9 | { 10 | "templates": { 11 | "removed": { 12 | "DbMigrations": [] 13 | } 14 | } 15 | }, 16 | { 17 | "templates": { 18 | "removed": { 19 | "DbMigration": [] 20 | } 21 | } 22 | }, 23 | { 24 | "templates": { 25 | "removed": { 26 | "DbComparison": [] 27 | } 28 | } 29 | }, 30 | { 31 | "fields": { 32 | "removed": { 33 | "dbMigrateRuntimeReady": [] 34 | } 35 | } 36 | }, 37 | { 38 | "fields": { 39 | "removed": { 40 | "dbMigrateRuntimeAction": [] 41 | } 42 | } 43 | }, 44 | { 45 | "fields": { 46 | "removed": { 47 | "dbMigrateRuntimeControl": [] 48 | } 49 | } 50 | }, 51 | { 52 | "fields": { 53 | "removed": { 54 | "dbMigrateSnippets": [] 55 | } 56 | } 57 | }, 58 | { 59 | "templates": { 60 | "removed": { 61 | "repeater_dbMigrateSnippets": [] 62 | } 63 | } 64 | }, 65 | { 66 | "fields": { 67 | "removed": { 68 | "dbMigrateRestrictFields": [] 69 | } 70 | } 71 | }, 72 | { 73 | "fields": { 74 | "removed": { 75 | "dbMigrateAdditionalDetails": [] 76 | } 77 | } 78 | }, 79 | { 80 | "fields": { 81 | "removed": { 82 | "dbMigrateSummary": [] 83 | } 84 | } 85 | }, 86 | { 87 | "fields": { 88 | "removed": { 89 | "dbMigrateLogChanges": [] 90 | } 91 | } 92 | }, 93 | { 94 | "fields": { 95 | "removed": { 96 | "dbMigrateTrackingScope": [] 97 | } 98 | } 99 | }, 100 | { 101 | "fields": { 102 | "removed": { 103 | "dbMigrateFieldTracking": [] 104 | } 105 | } 106 | }, 107 | { 108 | "fields": { 109 | "removed": { 110 | "dbMigrateTemplateTracking": [] 111 | } 112 | } 113 | }, 114 | { 115 | "fields": { 116 | "removed": { 117 | "dbMigratePageTracking": [] 118 | } 119 | } 120 | }, 121 | { 122 | "fields": { 123 | "removed": { 124 | "dbMigrateTrackingScope_END": [] 125 | } 126 | } 127 | }, 128 | { 129 | "fields": { 130 | "removed": { 131 | "dbMigrateItem": [] 132 | } 133 | } 134 | }, 135 | { 136 | "fields": { 137 | "removed": { 138 | "dbMigrateComparisonItem": [] 139 | } 140 | } 141 | }, 142 | { 143 | "templates": { 144 | "removed": { 145 | "repeater_dbMigrateItem": [] 146 | } 147 | } 148 | }, 149 | { 150 | "templates": { 151 | "removed": { 152 | "repeater_dbMigrateComparisonItem": [] 153 | } 154 | } 155 | }, 156 | { 157 | "fields": { 158 | "removed": { 159 | "dbMigrateOldName": [] 160 | } 161 | } 162 | }, 163 | { 164 | "fields": { 165 | "removed": { 166 | "dbMigrateName": [] 167 | } 168 | } 169 | }, 170 | { 171 | "fields": { 172 | "removed": { 173 | "dbMigrateAction": [] 174 | } 175 | } 176 | }, 177 | { 178 | "fields": { 179 | "removed": { 180 | "dbMigrateType": [] 181 | } 182 | } 183 | } 184 | ] -------------------------------------------------------------------------------- /RuntimeFields/dbMigrateRuntimeControl.php: -------------------------------------------------------------------------------- 1 | template == ProcessDbMigrate::MIGRATION_TEMPLATE) { 9 | /* @var $page \ProcessWire\DbMigrationPage */ 10 | $lockText = ($page->meta('installable')) ? __('Lock the page? Locking marks the migration as complete and reduces the risk of subsequent conflicts.') : 11 | __('Lock the page? Locking marks the migration as complete and reduces the risk of subsequent conflicts. You will need lock the target(s) separately or sync the lockfile to implement the lock in target environments.'); 12 | $unlockText = ($page->meta('installable')) ? __('Unlock the page? Unlocking allows changes and may conflict with other migrations.') : 13 | __('Unlock the page? Unlocking allows changes and may conflict with other migrations. You will need to unlock the target(s) separately or remove the lockfile from target environments if you wish the unlock to be implemented there.'); 14 | $config->js('dbMigrateRuntimeControl', [ 15 | 'lock' => $lockText, 16 | 'unlock' => $unlockText 17 | ]); 18 | 19 | $locked = ($page->meta('locked')); 20 | $display = wire('modules')->get("InputfieldMarkup"); 21 | $installedStatus = $page->meta('installedStatus') ? : ['status' => 'None']; 22 | //bd($installedStatus, '$installedStatus in migration control'); 23 | if($locked) { 24 | $text = __('This page is locked and cannot be changed or actioned unless you unlock it.'); 25 | if($page->meta('installable')) { 26 | $text2 = __('The status of installation is') . ' "'; 27 | $text2 .= $installedStatus['status'] . '".'; 28 | } else { 29 | $text2 = __('The status of the export is') . ' "'; 30 | $text2 .= $installedStatus['status'] . '".'; 31 | } 32 | } else { 33 | if($page->meta('installable')) { 34 | $text = __('This page is installable here. It cannot be amended.'); 35 | $text2 = __('The status of installation is') . ' "'; 36 | $text2 .= $installedStatus['status'] . '".'; 37 | } else { 38 | $text = __('This page is exportable - i.e. you can generate migration data from it.'); 39 | $text2 = __('The status of the export is') . ' "'; 40 | $text2 .= $installedStatus['status'] . '".'; 41 | } 42 | } 43 | if($page->meta('installable')) { 44 | $text3 = __(' Source database for this migration is '); 45 | $text3 .= ($page->meta('sourceDb')) ?: __('not named'); 46 | } else { 47 | $text3 = ''; 48 | } 49 | $display->value = $text . '
' . $text2 . '
' . $text3 . '.'; 50 | echo $display->render(); 51 | $form = wire(new InputfieldWrapper()); 52 | $control = wire(new InputfieldWrapper()); 53 | $control->wrapAttr('style', "display:none"); 54 | // if($page->meta('installable')) { 55 | // //locked status 56 | // if($page->meta('locked')) { 57 | // $btn = wire('modules')->get("InputfieldButton"); 58 | // $btn->attr('id', "unlock-page"); 59 | // $btn->attr('value', __(" You can only unlock this in the source system")); 60 | // $btn->class('fa fa-lock'); 61 | // $btn->showInHeader(); 62 | // $control->append($btn); 63 | // } else { 64 | // //Lock button 65 | // $btn = wire('modules')->get("InputfieldButton"); 66 | // $btn->attr('id', "lock-page"); 67 | // $btn->attr('value', __(' You can only lock this in the source system')); 68 | // $btn->class('fa fa-unlock'); 69 | // $btn->showInHeader(); 70 | // $control->append($btn); 71 | // } 72 | // 73 | // } else { 74 | //Unlock button 75 | if($page->meta('locked')) { 76 | $btn = wire('modules')->get("InputfieldButton"); 77 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/lock/?id=" . $page->id . '&action=unlock'); 78 | $btn->attr('id', "unlock-page"); 79 | $btn->attr('value', " Unlock"); 80 | $btn->class('fa fa-lock'); 81 | $btn->showInHeader(); 82 | $control->append($btn); 83 | } else { 84 | //unlock status 85 | $btn = wire('modules')->get("InputfieldButton"); 86 | $btn->attr('id', "lock-page"); 87 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/lock/?id=" . $page->id . '&action=lock'); 88 | $btn->attr('value', ' Lock'); 89 | $btn->class('fa fa-unlock'); 90 | $btn->showInHeader(); 91 | $control->append($btn); 92 | } 93 | // } 94 | 95 | $form->append($control); 96 | 97 | echo $form->render(); 98 | } -------------------------------------------------------------------------------- /DbMigrateHelp.php: -------------------------------------------------------------------------------- 1 | styles->add($config->urls->templates . "styles/admin.css"); 3 | //bd($page, 'RENDERING'); 4 | ?> 5 | 6 | 7 | 8 | 9 | 60 | 61 | 62 |
63 | $v) $forArray[$k] = trim($v); 70 | 71 | $for = implode('|', $forArray); 72 | $anchors = array(); 73 | // Use saved help text if it exists - in case it was updated externally - but only if we ARE NOT TRYING TO EXPORT THE FILE!! 74 | if(!$page->export && file_exists(wire('config')->paths->siteModules . basename(__DIR__) . '/helpText.html')) { 75 | $value = file_get_contents($this->modulePath . 'helpText.html'); 76 | } else { 77 | $value = $page->dbMigrateAdditionalDetails; 78 | } 79 | 80 | /* 81 | * This first regex needs to match anything with the form

heading text

but not anything like

heading text

82 | * Group 1 matches the tag without the brackets 83 | * Group 2 matches the heading text 84 | * Group 3 matches the closing tag (with the brackets) 85 | * The heading is then amended to include the - the regex is designed to prevent this occurring iteratively 86 | */ 87 | if(preg_match_all('{<(' . $for . ')[^>]*>(?!<)(.+?)()}i', $value, $matches)) { 88 | foreach($matches[1] as $key => $tag) { 89 | $text = $matches[2][$key]; 90 | $close = $matches[3][$key]; 91 | $anchor = $sanitizer->pageName($text, true); 92 | $full = $matches[0][$key]; 93 | $value = str_replace($full, "<$tag>$text$close", $value); 94 | } 95 | $page->dbMigrateAdditionalDetails = $value; 96 | } 97 | 98 | /* 99 | * This second regex matches anything like

heading text

and does not care about any included tags 100 | * The groups are as in the first regex 101 | * Included tags are stripped from the heading text before being used 102 | * The $anchor array is then created to be used in the sidenav index 103 | */ 104 | if(preg_match_all('{<(' . $for . ')[^>]*>(.+?)}i', $value, $matches)) { 105 | foreach($matches[1] as $key => $tag) { 106 | $text = strip_tags($matches[2][$key]); 107 | $anchor = $sanitizer->pageName($text, true); 108 | $level = array_search($tag, $forArray); 109 | $anchors[$anchor]['text'] = $text; 110 | $anchors[$anchor]['level'] = $level; 111 | } 112 | 113 | } 114 | 115 | if(count($anchors)) { 116 | $out = ""; 128 | } else { 129 | $out = ''; 130 | } 131 | echo $out; 132 | ?> 133 |
134 |
135 |
136 | dbMigrateAdditionalDetails; 138 | if(!$page->export) { // see note above re $page->export 139 | $html = str_replace('src="help/', 'src="' . $this->wire('config')->urls->siteModules . basename(__DIR__) . '/help/', $html); 140 | } 141 | echo $html; // Will have anchors inserted by sidebar code 142 | ?> 143 |
144 |
145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /HannaMigrate/HannaMigrate.module.php: -------------------------------------------------------------------------------- 1 | 'Hanna Migrate', 6 | 'summary' => 'Migrate Hanna codes between sites', 7 | 'version' => '0.0.3', 8 | 'author' => 'Mark Evens', 9 | 'icon' => 'medium', 10 | 'requires' => ['ProcessWire>=3.0.200'], 11 | 'singular' => true, 12 | ); 13 | } 14 | 15 | public function init() { 16 | 17 | } 18 | 19 | public function exportAll($migrationName = null) { 20 | $modules = $this->wire('modules'); 21 | $hm = $modules->get('ProcessHannaCode'); 22 | $ha = $hm->hannaCodes()->getAll(); 23 | $exportAll = []; 24 | foreach($ha as $h) { 25 | $exportData = array( 26 | 'name' => $h->name, 27 | 'type' => $h->type, 28 | 'code' => $hm->hannaCodes()->packCode($h->code, $h->attrs), 29 | ); 30 | $exportAll[$h->name] = "!HannaCode:$h->name:" . base64_encode(json_encode($exportData)) . "/!HannaCode"; 31 | } 32 | $directory = $this->migrationDirectory($migrationName); 33 | if(!is_dir($directory)) if(!\ProcessWire\wireMkdir($directory, true, "0777")) { // wireMkDir recursive 34 | throw new WireException("Unable to create migration directory: $directory"); 35 | } 36 | $exportJson = json_encode($exportAll); 37 | file_put_contents($directory . 'data.json', $exportJson); 38 | } 39 | 40 | public function importAll($migrationName = null, $overwrite = false, $delete = false) { 41 | $modules = $this->wire('modules'); 42 | $session = $this->wire('session'); 43 | $hm = $modules->get('ProcessHannaCode'); 44 | 45 | // Get the migration .json file for this migration 46 | $directory = $this->migrationDirectory($migrationName); 47 | $dataFile = (file_exists($directory . 'data.json')) 48 | ? file_get_contents($directory . 'data.json') : null; 49 | 50 | $dataArray = json_decode($dataFile, true); 51 | if(!$dataArray) { 52 | throw new WireException("Failed to json decode import file"); 53 | } 54 | 55 | // Delete existing hanna codes which are not in the import, if delete is set to true 56 | if($delete) { 57 | $ha = $hm->hannaCodes()->getAll(); 58 | foreach($ha as $h) { 59 | if(!array_key_exists($h->name, $dataArray)) { 60 | $hm->hannaCodes()->delete($h); 61 | $session->message($this->_("Deleted Hanna Code:") . " $h->name"); 62 | } 63 | } 64 | } 65 | 66 | foreach($dataArray as $nameKey => $data) { 67 | //bd([$nameKey, $data], 'nameKey, data'); 68 | if(!preg_match('{!HannaCode:([^:]+):(.*?)/!HannaCode}s', $data, $matches)) { 69 | $session->error("Unrecognized Hanna Code format for $nameKey"); 70 | } 71 | $name = $matches[1]; 72 | $data = $matches[2]; 73 | $data = base64_decode($data); 74 | if($data === false) { 75 | $session->error("Failed to base64 decode import data item $nameKey"); 76 | } 77 | 78 | $data = json_decode($data, true); 79 | if($data === false) { 80 | $session->error("Failed to json decode import data item $nameKey"); 81 | } 82 | 83 | if(empty($data['name']) || empty($data['code'])) { 84 | $session->error("Import data for $nameKey does not contain all required fields"); 85 | } 86 | 87 | $h = $hm->hannaCodes()->get($name); 88 | if($h->id) { 89 | if($overwrite) { 90 | $hm->hannaCodes()->delete($h); 91 | $session->message($this->_("Replaced Hanna Code with name $nameKey")); 92 | } else { 93 | $session->error($this->_("Hanna Code with name $nameKey already exists")); 94 | } 95 | } 96 | 97 | $data['type'] = (int)$data['type']; 98 | if($data['type'] & \ProcessWire\HannaCode::typePHP && !$hm->hasPermission('hanna-code-php')) { 99 | throw new WireException("You don't have permission to add/edit PHP Hanna Codes"); 100 | } 101 | 102 | $h = new \ProcessWire\HannaCode(); 103 | $hm->wire($h); 104 | $h->name = $name; 105 | $h->type = $data['type']; 106 | $h->code = $data['code']; 107 | $h->modified = time(); 108 | 109 | if($hm->hannaCodes()->save($h)) { 110 | $this->message($this->_('Imported Hanna Code:') . " $name"); 111 | } else { 112 | $session->error("Error importing Hanna code for $nameKey"); 113 | } 114 | } 115 | return ''; 116 | 117 | } 118 | 119 | public function migrationDirectory($migrationName) { 120 | $modules = $this->wire('modules'); 121 | $dbm = $modules->get('ProcessDbMigrate'); 122 | if($dbm) { 123 | $migrationPage = ($migrationName) ? $dbm->migrations->get("template=$dbm->migrationTemplate, name=$migrationName") : new \ProcessWire\nullPage(); 124 | /* @var $migrationPage \ProcessWire\DbMigrationPage */ 125 | if($migrationPage->id > 0) { 126 | $directory = $dbm->migrationsPath; 127 | $migrationPath = $directory . $migrationPage->name . '/hanna-codes/'; 128 | } else { 129 | $migrationPath = $dbm->migrationsPath . '/hanna-codes/'; 130 | } 131 | } else { 132 | $migrationPath = $this->wire()->config->paths->assets . 'migrations/hanna-codes/'; 133 | } 134 | return $migrationPath; 135 | } 136 | 137 | } -------------------------------------------------------------------------------- /DbComparisonPage.class.php: -------------------------------------------------------------------------------- 1 | templates->get('DbComparison'); 40 | parent::__construct($tpl); 41 | 42 | } 43 | 44 | 45 | public function init() { 46 | //bd('INIT COMPARISON'); 47 | } 48 | 49 | /** 50 | * Better to put hooks here rather than in ready.php 51 | * This is called from ready() in ProcessDbMigrate.module as that is autoloaded 52 | * 53 | * @throws WireException 54 | * 55 | */ 56 | public function ready() { 57 | $this->set('adminPath', wire('pages')->get(2)->path); 58 | $this->set('comparisons', wire('pages')->get($this->adminPath . ProcessDbMigrate::COMPARISON_PARENT)); 59 | $this->set('comparisonTemplate', wire('templates')->get(ProcessDbMigrate::COMPARISON_TEMPLATE)); 60 | $this->set('comparisonsPath', wire('config')->paths->templates . ProcessDbMigrate::COMPARISON_PATH); 61 | $this->set('configData', wire('modules')->getConfig('ProcessDbMigrate')); 62 | $dbMigrate = wire('modules')->get('ProcessDbMigrate'); 63 | $this->set('dbMigrate', $dbMigrate); 64 | $this->set('dbName', $dbMigrate->dbName()); 65 | if(isset($this->configData['suppress_hooks']) && $this->configData['suppress_hooks']) $this->wire()->error("Hook suppression is on - migrations will not work correctly - unset in the module settings."); 66 | 67 | // Fix for PW versions < 3.0.152, but left in place regardless of version, in case custom page classes are not enabled 68 | if($this->comparisonTemplate->pageClass != __CLASS__) { 69 | $this->comparisonTemplate->pageClass = __CLASS__; 70 | $this->comparisonTemplate->save(); 71 | } 72 | 73 | $this->addHookAfter("Pages::saved(template=$this->comparisonTemplate)", $this, 'afterSaved'); 74 | $this->addHookBefore("Pages::save(template=$this->comparisonTemplate)", $this, 'beforeSaveThis'); 75 | 76 | $this->set('ready', true); 77 | } 78 | 79 | /* 80 | * METHODS WHICH MODIFY THE PARENT CLASS 81 | */ 82 | 83 | /** 84 | * 85 | * Refresh page from json 86 | * 87 | * @param null $found 88 | * @return bool 89 | * @throws WireException 90 | * @throws WirePermissionException 91 | * 92 | */ 93 | public function refresh($found = null) { 94 | $this->migrationsPath = $this->comparisonsPath; 95 | $this->migrations = $this->comparisons; 96 | return parent::refresh($found); 97 | } 98 | 99 | /** 100 | * 101 | * Parse items, expanding selectors as necessary 102 | * Return list of all items in format [[type, action, name, oldName], [...], ...] 103 | * 104 | * @return array[] 105 | * @throws WireException 106 | * 107 | */ 108 | public function listItems($type = null) { 109 | $this->dbMigrateItem = $this->dbMigrateComparisonItem; 110 | return parent::listItems($type); 111 | } 112 | 113 | /** 114 | * @param $newOld 115 | * @param false $noSave 116 | * @return array|void|null 117 | * @throws WireException 118 | * @throws WirePermissionException 119 | */ 120 | public function exportData($newOld, $noSave = false) { 121 | $this->ready(); 122 | $this->dbMigrateItem = $this->dbMigrateComparisonItem; 123 | $this->migrationsPath = $this->comparisonsPath; 124 | return parent::exportData($newOld, $noSave); 125 | } 126 | 127 | /** 128 | * Replace image paths in RTE (Textarea) fields with the path to the file in the migration folder - for preview purposes 129 | * 130 | * @param string $html // Text in the RTE field 131 | * @param string $newOld // Context - to get the file from the 'new' or 'old' directory as appropriate 132 | * @param bool $json 133 | * @param string $path 134 | * @return string|string[]|null 135 | * @throws WireException 136 | * 137 | */ 138 | public function replaceImgSrcPath(string $html, string $newOld, $json = false, $path = ProcessDbMigrate::COMPARISON_PATH) { 139 | return parent::replaceImgSrcPath($html, $newOld, $json, $path); 140 | } 141 | 142 | /* 143 | * Override irrelevant functions with nulls 144 | */ 145 | 146 | public function afterSaved(HookEvent $event) { 147 | } 148 | 149 | protected function checkOverlaps($itemList) { 150 | } 151 | 152 | protected function beforeSaveThis(HookEvent $event) { 153 | } 154 | 155 | /* 156 | * These are not overridden 157 | */ 158 | 159 | // protected function beforeTrashThis(HookEvent $event) {} 160 | 161 | // protected function afterTrashedThis(HookEvent $event) {} 162 | } -------------------------------------------------------------------------------- /FieldtypeDbMigrateRuntime.module: -------------------------------------------------------------------------------- 1 | hasField; 21 | $config = $this->wire('config'); 22 | $js_path = "{$this->getPath($field)}.js"; 23 | if(file_exists($js_path)) { 24 | $modified = filemtime($js_path); 25 | $config->scripts->add("{$this->getUrl($field)}.js?v=$modified"); 26 | } 27 | $css_path = "{$this->getPath($field)}.css"; 28 | if(file_exists($css_path)) { 29 | $modified = filemtime($css_path); 30 | $config->styles->add("{$this->getUrl($field)}.css?v=$modified"); 31 | } 32 | return parent::renderReady($parent, $renderValueMode); 33 | } 34 | 35 | /** 36 | * @param Field $field 37 | * @return string 38 | * @throws WireException 39 | */ 40 | public function getPath(Field $field) { 41 | return $this->wire('config')->paths->siteModules . basename(__DIR__) . '/RuntimeFields/' . $field->name; 42 | } 43 | 44 | /** 45 | * @param Field $field 46 | * @return string 47 | * @throws WireException 48 | */ 49 | public function getUrl(Field $field) { 50 | return $this->wire('config')->urls->siteModules . basename(__DIR__) . '/RuntimeFields/' . $field->name; 51 | } 52 | 53 | /** 54 | * @return mixed|string 55 | */ 56 | public function ___render() { 57 | return $this->value; 58 | } 59 | 60 | /** 61 | * @param WireInputData $input 62 | * @return $this|InputfieldDbMigrateRuntime 63 | */ 64 | public function ___processInput(WireInputData $input) { 65 | return $this; 66 | } 67 | 68 | } 69 | 70 | 71 | class FieldtypeDbMigrateRuntime extends Fieldtype { 72 | 73 | /** 74 | * @return string[] 75 | */ 76 | public static function getModuleInfo() { 77 | return array( 78 | 'title' => 'DbMigrateRuntime', 79 | 'version' => '0.0.1', 80 | 'summary' => 'An inputfield, for use with ProcessDbMigrate, that renders at runtime, with no data saved to the database.', 81 | 'author' => 'Mark Evens, based on RuntimeOnly by Robin Sallis', 82 | 'icon' => 'code', 83 | 'requires' => 'ProcessWire>=3.0.0, PHP>=5.4.0, ProcessDbMigrate', 84 | ); 85 | } 86 | 87 | /** 88 | * @param Page $page 89 | * @param Field $field 90 | * @param $value 91 | * @param $property 92 | * @return bool|mixed|MarkupFieldtype|string 93 | */ 94 | public function ___markupValue(Page $page, Field $field, $value = null, $property = '') { 95 | if($field->no_lister_render) { 96 | return ''; 97 | } else { 98 | return $this->renderMarkup($page, $field); 99 | } 100 | } 101 | 102 | /** 103 | * @param Page $page 104 | * @param Field $field 105 | * @return bool|mixed|string 106 | * @throws WireException 107 | */ 108 | protected function renderMarkup(Page $page, Field $field) { 109 | $php_file = wire('config')->paths->siteModules . basename(__DIR__) . '/RuntimeFields/' . $field->name . ".php"; 110 | // $php_file = "{$this->wire('config')->paths->templates}RuntimeOnly/{$field->name}.php"; 111 | if(file_exists($php_file)) { 112 | return $this->wire('files')->render($php_file, ['page' => $page, 'field' => $field, 'inputfield' => $this]); 113 | } else { 114 | return sprintf($this->_('No file found at %s'), wire('config')->urls->siteModules . basename(__DIR__) . '/RuntimeFields/' . $field->name . ".php"); 115 | } 116 | } 117 | 118 | /** 119 | * @param Page $page 120 | * @param Field $field 121 | * @param $value 122 | * @return bool|mixed|string 123 | * @throws WireException 124 | */ 125 | public function ___wakeupValue(Page $page, Field $field, $value) { 126 | return $this->renderMarkup($page, $field); 127 | } 128 | 129 | /** 130 | * @param Page $page 131 | * @param Field $field 132 | * @return bool|mixed|object|Config|Fields|Fieldtypes|Inputfield|Modules|Notices|Page|Pages|Permissions|ProcessWire|Roles|Sanitizer|Session|Templates|User|Users|Wire|WireDatabasePDO|WireDateTime|WireFileTools|WireHooks|WireInput|WireMailTools|string|null 133 | * @throws WireException 134 | */ 135 | public function getInputfield(Page $page, Field $field) { 136 | $inputfield = $this->wire(new InputfieldDbMigrateRuntime()); 137 | $inputfield->class = $this->className(); 138 | return $inputfield; 139 | } 140 | 141 | /** 142 | * @param Field $field 143 | * @return InputfieldWrapper 144 | * @throws WireException 145 | */ 146 | public function ___getConfigInputfields(Field $field) { 147 | $inputfields = parent::___getConfigInputfields($field); 148 | $config = $this->wire('config'); 149 | 150 | // Rendering info 151 | /* @var InputfieldMarkup $f */ 152 | $f = $this->wire('modules')->InputfieldMarkup; 153 | $f->name = 'rendering'; 154 | $f->label = $this->_('Inputfield rendering'); 155 | $value = '

' . $this->_('This inputfield is solely for use as part of the ProcessDbMigrate module. Use for other purposes is not recommended. This fieldtype will be uninstalled if ProcessBbMigrate is uninstalled.') . '

'; 156 | $value .= '

' . sprintf($this->_('Inputfield markup will be rendered from a file at %s. In addition to the standard ProcessWire variables this file receives:'), 157 | wire('config')->urls->siteModules . basename(__DIR__) . '/RuntimeFields/' . $field->name . ".php") . '
'; 158 | $value .= '$page - ' . $this->_('The page being edited.') . '
'; 159 | $value .= '$field - ' . $this->_('the Field object.') . '
'; 160 | $value .= '$inputfield - ' . $this->_('the Inputfield object.') . '

'; 161 | $value .= '

' . sprintf($this->_('JS file %s will be added to admin if that file exists.'), wire('config')->urls->siteModules . basename(__DIR__) . '/RuntimeFields/' . $field->name . ".js") . '
'; 162 | $value .= sprintf($this->_('CSS file %s will be added to admin if that file exists.'), wire('config')->urls->siteModules . basename(__DIR__) . '/RuntimeFields/' . $field->name . ".js") . '
'; 163 | $value .= '

'; 164 | $f->value = $value; 165 | $inputfields->add($f); 166 | 167 | // // NOT USED // 168 | // // Prevent field rendering in Lister 169 | // /* @var InputfieldCheckbox $f */ 170 | // $f = $this->wire('modules')->InputfieldCheckbox; 171 | // $f_name = 'no_lister_render'; 172 | // $f->name = $f_name; 173 | // $f->label = $this->_('Lister rendering'); 174 | // $f->label2 = $this->_('Do not allow field to render inside a Lister column'); 175 | // $f->checked = $field->$f_name === 1 ? 'checked' : ''; 176 | // $inputfields->add($f); 177 | 178 | return $inputfields; 179 | } 180 | 181 | /** 182 | * @param Field $field 183 | * @return InputfieldWrapper 184 | * @throws WireException 185 | */ 186 | public function ___getConfigAdvancedInputfields(Field $field) { 187 | $inputfields = parent::___getConfigAdvancedInputfields($field); 188 | // Remove config fields that are not applicable 189 | $inputfields->remove($inputfields->get('autojoin')); 190 | $inputfields->remove($inputfields->get('global')); 191 | return $inputfields; 192 | } 193 | 194 | /** 195 | * @param Field $field 196 | * @return bool|mixed|object|Config|Fields|Fieldtypes|Modules|Notices|Page|Pages|Permissions|ProcessWire|Roles|Sanitizer|Session|Templates|User|Users|Wire|WireDatabasePDO|WireDateTime|WireFileTools|WireHooks|WireInput|WireMailTools|string|null 197 | * @throws WireException 198 | */ 199 | public function ___getCompatibleFieldtypes(Field $field) { 200 | $fieldtypes = $this->wire(new Fieldtypes()); 201 | foreach($this->wire('fieldtypes') as $fieldtype) { 202 | if($fieldtype instanceof FieldtypeDbMigrateRuntime) $fieldtypes->add($fieldtype); 203 | } 204 | return $fieldtypes; 205 | } 206 | 207 | /** 208 | * @param $query 209 | * @param $table 210 | * @param $subfield 211 | * @param $operator 212 | * @param $value 213 | * @return mixed 214 | * @throws WireException 215 | */ 216 | public function getMatchQuery($query, $table, $subfield, $operator, $value) { 217 | // This field may not be queried 218 | throw new WireException(sprintf($this->_("Field '%s' is runtime and not queryable"), $query->field->name)); 219 | } 220 | 221 | /** 222 | * @param Field $field 223 | * @param DatabaseQuerySelect $query 224 | * @return null 225 | */ 226 | public function getLoadQueryAutojoin(Field $field, DatabaseQuerySelect $query) { 227 | return null; 228 | } 229 | 230 | /** 231 | * @param Page $page 232 | * @param Field $field 233 | * @param $value 234 | * @return int|object|WireArray|string 235 | */ 236 | public function sanitizeValue(Page $page, Field $field, $value) { 237 | return $value; 238 | } 239 | 240 | /** 241 | * @param Page $page 242 | * @param Field $field 243 | * @param $value 244 | * @return int|object|WireArray|string 245 | */ 246 | public function ___sleepValue(Page $page, Field $field, $value) { 247 | return $value; 248 | } 249 | 250 | public function savePageField(Page $page, Field $field) { 251 | return true; 252 | } 253 | 254 | public function loadPageField(Page $page, Field $field) { 255 | return ''; 256 | } 257 | 258 | public function getLoadQuery(Field $field, DatabaseQuerySelect $query) { 259 | return $query; 260 | } 261 | 262 | public function ___savePageField(Page $page, Field $field) { 263 | return true; 264 | } 265 | 266 | public function ___deletePageField(Page $page, Field $field) { 267 | return true; 268 | } 269 | 270 | public function ___createField(Field $field) { 271 | return true; 272 | } 273 | 274 | public function ___deleteField(Field $field) { 275 | return true; 276 | } 277 | 278 | public function getDatabaseSchema(Field $field) { 279 | return []; 280 | } 281 | 282 | public function ___install() { 283 | 284 | } 285 | 286 | } 287 | -------------------------------------------------------------------------------- /new/migration.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": { 3 | "changed": { 4 | "/processwire/dbmigrations/bootstrap/": { 5 | "template": "DbMigration", 6 | "parent": "/processwire/dbmigrations/", 7 | "status": 1, 8 | "name": "bootstrap", 9 | "id": 1357, 10 | "title": "bootstrap", 11 | "dbMigrateLogChanges": 2, 12 | "dbMigrateSummary": "This is the initial migration to install all the required fields, templates and pages for the module to work. It is bootstrapped, on first running the ProcessDbMigrate module, from the json files.", 13 | "dbMigrateAdditionalDetails": "

If you want to amend this bootstrap, for example to implement changes to the layout of the DbMigration template, then you may need to first make it 'exportable' in the source (development) environment by removing the meta('installable') from this page.

", 14 | "dbMigrateItem": [ 15 | { 16 | "template": "repeater_dbMigrateItem", 17 | "data": { 18 | "dbMigrateType": 1, 19 | "dbMigrateAction": 1, 20 | "dbMigrateName": "dbMigrateType", 21 | "dbMigrateOldName": "" 22 | } 23 | }, 24 | { 25 | "template": "repeater_dbMigrateItem", 26 | "data": { 27 | "dbMigrateType": 1, 28 | "dbMigrateAction": 1, 29 | "dbMigrateName": "dbMigrateAction", 30 | "dbMigrateOldName": "" 31 | } 32 | }, 33 | { 34 | "template": "repeater_dbMigrateItem", 35 | "data": { 36 | "dbMigrateType": 1, 37 | "dbMigrateAction": 1, 38 | "dbMigrateName": "dbMigrateName", 39 | "dbMigrateOldName": "" 40 | } 41 | }, 42 | { 43 | "template": "repeater_dbMigrateItem", 44 | "data": { 45 | "dbMigrateType": 1, 46 | "dbMigrateAction": 1, 47 | "dbMigrateName": "dbMigrateOldName", 48 | "dbMigrateOldName": "" 49 | } 50 | }, 51 | { 52 | "template": "repeater_dbMigrateItem", 53 | "data": { 54 | "dbMigrateType": 2, 55 | "dbMigrateAction": 1, 56 | "dbMigrateName": "repeater_dbMigrateItem", 57 | "dbMigrateOldName": "" 58 | } 59 | }, 60 | { 61 | "template": "repeater_dbMigrateItem", 62 | "data": { 63 | "dbMigrateType": 1, 64 | "dbMigrateAction": 1, 65 | "dbMigrateName": "dbMigrateItem", 66 | "dbMigrateOldName": "" 67 | } 68 | }, 69 | { 70 | "template": "repeater_dbMigrateItem", 71 | "data": { 72 | "dbMigrateType": 2, 73 | "dbMigrateAction": 1, 74 | "dbMigrateName": "repeater_dbMigrateComparisonItem", 75 | "dbMigrateOldName": "" 76 | } 77 | }, 78 | { 79 | "template": "repeater_dbMigrateItem", 80 | "data": { 81 | "dbMigrateType": 1, 82 | "dbMigrateAction": 1, 83 | "dbMigrateName": "dbMigrateComparisonItem", 84 | "dbMigrateOldName": "" 85 | } 86 | }, 87 | { 88 | "template": "repeater_dbMigrateItem", 89 | "data": { 90 | "dbMigrateType": 1, 91 | "dbMigrateAction": 1, 92 | "dbMigrateName": "dbMigrateSummary", 93 | "dbMigrateOldName": "" 94 | } 95 | }, 96 | { 97 | "template": "repeater_dbMigrateItem", 98 | "data": { 99 | "dbMigrateType": 1, 100 | "dbMigrateAction": 1, 101 | "dbMigrateName": "dbMigrateAdditionalDetails", 102 | "dbMigrateOldName": "" 103 | } 104 | }, 105 | { 106 | "template": "repeater_dbMigrateItem", 107 | "data": { 108 | "dbMigrateType": 1, 109 | "dbMigrateAction": 1, 110 | "dbMigrateName": "dbMigrateRestrictFields", 111 | "dbMigrateOldName": "" 112 | } 113 | }, 114 | { 115 | "template": "repeater_dbMigrateItem", 116 | "data": { 117 | "dbMigrateType": 2, 118 | "dbMigrateAction": 1, 119 | "dbMigrateName": "repeater_dbMigrateSnippets", 120 | "dbMigrateOldName": "" 121 | } 122 | }, 123 | { 124 | "template": "repeater_dbMigrateItem", 125 | "data": { 126 | "dbMigrateType": 1, 127 | "dbMigrateAction": 1, 128 | "dbMigrateName": "dbMigrateSnippets", 129 | "dbMigrateOldName": "" 130 | } 131 | }, 132 | { 133 | "template": "repeater_dbMigrateItem", 134 | "data": { 135 | "dbMigrateType": 1, 136 | "dbMigrateAction": 1, 137 | "dbMigrateName": "dbMigrateRuntimeControl", 138 | "dbMigrateOldName": "" 139 | } 140 | }, 141 | { 142 | "template": "repeater_dbMigrateItem", 143 | "data": { 144 | "dbMigrateType": 1, 145 | "dbMigrateAction": 1, 146 | "dbMigrateName": "dbMigrateRuntimeAction", 147 | "dbMigrateOldName": "" 148 | } 149 | }, 150 | { 151 | "template": "repeater_dbMigrateItem", 152 | "data": { 153 | "dbMigrateType": 1, 154 | "dbMigrateAction": 1, 155 | "dbMigrateName": "dbMigrateRuntimeReady", 156 | "dbMigrateOldName": "" 157 | } 158 | }, 159 | { 160 | "template": "repeater_dbMigrateItem", 161 | "data": { 162 | "dbMigrateType": 1, 163 | "dbMigrateAction": 1, 164 | "dbMigrateName": "dbMigrateLogChanges", 165 | "dbMigrateOldName": "" 166 | } 167 | }, 168 | { 169 | "template": "repeater_dbMigrateItem", 170 | "data": { 171 | "dbMigrateType": 1, 172 | "dbMigrateAction": 1, 173 | "dbMigrateName": "dbMigrateTrackingScope", 174 | "dbMigrateOldName": "" 175 | } 176 | }, 177 | { 178 | "template": "repeater_dbMigrateItem", 179 | "data": { 180 | "dbMigrateType": 1, 181 | "dbMigrateAction": 1, 182 | "dbMigrateName": "dbMigrateFieldTracking", 183 | "dbMigrateOldName": "" 184 | } 185 | }, 186 | { 187 | "template": "repeater_dbMigrateItem", 188 | "data": { 189 | "dbMigrateType": 1, 190 | "dbMigrateAction": 1, 191 | "dbMigrateName": "dbMigrateTemplateTracking", 192 | "dbMigrateOldName": "" 193 | } 194 | }, 195 | { 196 | "template": "repeater_dbMigrateItem", 197 | "data": { 198 | "dbMigrateType": 1, 199 | "dbMigrateAction": 1, 200 | "dbMigrateName": "dbMigratePageTracking", 201 | "dbMigrateOldName": "" 202 | } 203 | }, 204 | { 205 | "template": "repeater_dbMigrateItem", 206 | "data": { 207 | "dbMigrateType": 1, 208 | "dbMigrateAction": 1, 209 | "dbMigrateName": "dbMigrateTrackingScope_END", 210 | "dbMigrateOldName": "" 211 | } 212 | }, 213 | { 214 | "template": "repeater_dbMigrateItem", 215 | "data": { 216 | "dbMigrateType": 2, 217 | "dbMigrateAction": 1, 218 | "dbMigrateName": "DbMigration", 219 | "dbMigrateOldName": "" 220 | } 221 | }, 222 | { 223 | "template": "repeater_dbMigrateItem", 224 | "data": { 225 | "dbMigrateType": 2, 226 | "dbMigrateAction": 1, 227 | "dbMigrateName": "DbComparison", 228 | "dbMigrateOldName": "" 229 | } 230 | }, 231 | { 232 | "template": "repeater_dbMigrateItem", 233 | "data": { 234 | "dbMigrateType": 2, 235 | "dbMigrateAction": 1, 236 | "dbMigrateName": "DbMigrations", 237 | "dbMigrateOldName": "" 238 | } 239 | }, 240 | { 241 | "template": "repeater_dbMigrateItem", 242 | "data": { 243 | "dbMigrateType": 3, 244 | "dbMigrateAction": 1, 245 | "dbMigrateName": "/processwire/dbmigrations/", 246 | "dbMigrateOldName": "" 247 | } 248 | }, 249 | { 250 | "template": "repeater_dbMigrateItem", 251 | "data": { 252 | "dbMigrateType": 3, 253 | "dbMigrateAction": 1, 254 | "dbMigrateName": "/processwire/dbcomparisons/", 255 | "dbMigrateOldName": "" 256 | } 257 | } 258 | ], 259 | "dbMigrateSnippets": [] 260 | } 261 | } 262 | }, 263 | "sourceDb": "MetaTunes Master", 264 | "sourceSiteUrl": "/site/" 265 | } -------------------------------------------------------------------------------- /old/migration.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": { 3 | "changed": { 4 | "/processwire/dbmigrations/bootstrap/": { 5 | "template": "DbMigration", 6 | "parent": "/processwire/dbmigrations/", 7 | "status": 1, 8 | "name": "bootstrap", 9 | "id": 1357, 10 | "title": "bootstrap", 11 | "dbMigrateLogChanges": 2, 12 | "dbMigrateSummary": "This is the initial migration to install all the required fields, templates and pages for the module to work. It is bootstrapped, on first running the ProcessDbMigrate module, from the json files.", 13 | "dbMigrateAdditionalDetails": "

If you want to amend this bootstrap, for example to implement changes to the layout of the DbMigration template, then you may need to first make it 'exportable' in the source (development) environment by removing the meta('installable') from this page.

", 14 | "dbMigrateItem": [ 15 | { 16 | "template": "repeater_dbMigrateItem", 17 | "data": { 18 | "dbMigrateType": 1, 19 | "dbMigrateAction": 1, 20 | "dbMigrateName": "dbMigrateType", 21 | "dbMigrateOldName": "" 22 | } 23 | }, 24 | { 25 | "template": "repeater_dbMigrateItem", 26 | "data": { 27 | "dbMigrateType": 1, 28 | "dbMigrateAction": 1, 29 | "dbMigrateName": "dbMigrateAction", 30 | "dbMigrateOldName": "" 31 | } 32 | }, 33 | { 34 | "template": "repeater_dbMigrateItem", 35 | "data": { 36 | "dbMigrateType": 1, 37 | "dbMigrateAction": 1, 38 | "dbMigrateName": "dbMigrateName", 39 | "dbMigrateOldName": "" 40 | } 41 | }, 42 | { 43 | "template": "repeater_dbMigrateItem", 44 | "data": { 45 | "dbMigrateType": 1, 46 | "dbMigrateAction": 1, 47 | "dbMigrateName": "dbMigrateOldName", 48 | "dbMigrateOldName": "" 49 | } 50 | }, 51 | { 52 | "template": "repeater_dbMigrateItem", 53 | "data": { 54 | "dbMigrateType": 2, 55 | "dbMigrateAction": 1, 56 | "dbMigrateName": "repeater_dbMigrateItem", 57 | "dbMigrateOldName": "" 58 | } 59 | }, 60 | { 61 | "template": "repeater_dbMigrateItem", 62 | "data": { 63 | "dbMigrateType": 1, 64 | "dbMigrateAction": 1, 65 | "dbMigrateName": "dbMigrateItem", 66 | "dbMigrateOldName": "" 67 | } 68 | }, 69 | { 70 | "template": "repeater_dbMigrateItem", 71 | "data": { 72 | "dbMigrateType": 2, 73 | "dbMigrateAction": 1, 74 | "dbMigrateName": "repeater_dbMigrateComparisonItem", 75 | "dbMigrateOldName": "" 76 | } 77 | }, 78 | { 79 | "template": "repeater_dbMigrateItem", 80 | "data": { 81 | "dbMigrateType": 1, 82 | "dbMigrateAction": 1, 83 | "dbMigrateName": "dbMigrateComparisonItem", 84 | "dbMigrateOldName": "" 85 | } 86 | }, 87 | { 88 | "template": "repeater_dbMigrateItem", 89 | "data": { 90 | "dbMigrateType": 1, 91 | "dbMigrateAction": 1, 92 | "dbMigrateName": "dbMigrateSummary", 93 | "dbMigrateOldName": "" 94 | } 95 | }, 96 | { 97 | "template": "repeater_dbMigrateItem", 98 | "data": { 99 | "dbMigrateType": 1, 100 | "dbMigrateAction": 1, 101 | "dbMigrateName": "dbMigrateAdditionalDetails", 102 | "dbMigrateOldName": "" 103 | } 104 | }, 105 | { 106 | "template": "repeater_dbMigrateItem", 107 | "data": { 108 | "dbMigrateType": 1, 109 | "dbMigrateAction": 1, 110 | "dbMigrateName": "dbMigrateRestrictFields", 111 | "dbMigrateOldName": "" 112 | } 113 | }, 114 | { 115 | "template": "repeater_dbMigrateItem", 116 | "data": { 117 | "dbMigrateType": 2, 118 | "dbMigrateAction": 1, 119 | "dbMigrateName": "repeater_dbMigrateSnippets", 120 | "dbMigrateOldName": "" 121 | } 122 | }, 123 | { 124 | "template": "repeater_dbMigrateItem", 125 | "data": { 126 | "dbMigrateType": 1, 127 | "dbMigrateAction": 1, 128 | "dbMigrateName": "dbMigrateSnippets", 129 | "dbMigrateOldName": "" 130 | } 131 | }, 132 | { 133 | "template": "repeater_dbMigrateItem", 134 | "data": { 135 | "dbMigrateType": 1, 136 | "dbMigrateAction": 1, 137 | "dbMigrateName": "dbMigrateRuntimeControl", 138 | "dbMigrateOldName": "" 139 | } 140 | }, 141 | { 142 | "template": "repeater_dbMigrateItem", 143 | "data": { 144 | "dbMigrateType": 1, 145 | "dbMigrateAction": 1, 146 | "dbMigrateName": "dbMigrateRuntimeAction", 147 | "dbMigrateOldName": "" 148 | } 149 | }, 150 | { 151 | "template": "repeater_dbMigrateItem", 152 | "data": { 153 | "dbMigrateType": 1, 154 | "dbMigrateAction": 1, 155 | "dbMigrateName": "dbMigrateRuntimeReady", 156 | "dbMigrateOldName": "" 157 | } 158 | }, 159 | { 160 | "template": "repeater_dbMigrateItem", 161 | "data": { 162 | "dbMigrateType": 1, 163 | "dbMigrateAction": 1, 164 | "dbMigrateName": "dbMigrateLogChanges", 165 | "dbMigrateOldName": "" 166 | } 167 | }, 168 | { 169 | "template": "repeater_dbMigrateItem", 170 | "data": { 171 | "dbMigrateType": 1, 172 | "dbMigrateAction": 1, 173 | "dbMigrateName": "dbMigrateTrackingScope", 174 | "dbMigrateOldName": "" 175 | } 176 | }, 177 | { 178 | "template": "repeater_dbMigrateItem", 179 | "data": { 180 | "dbMigrateType": 1, 181 | "dbMigrateAction": 1, 182 | "dbMigrateName": "dbMigrateFieldTracking", 183 | "dbMigrateOldName": "" 184 | } 185 | }, 186 | { 187 | "template": "repeater_dbMigrateItem", 188 | "data": { 189 | "dbMigrateType": 1, 190 | "dbMigrateAction": 1, 191 | "dbMigrateName": "dbMigrateTemplateTracking", 192 | "dbMigrateOldName": "" 193 | } 194 | }, 195 | { 196 | "template": "repeater_dbMigrateItem", 197 | "data": { 198 | "dbMigrateType": 1, 199 | "dbMigrateAction": 1, 200 | "dbMigrateName": "dbMigratePageTracking", 201 | "dbMigrateOldName": "" 202 | } 203 | }, 204 | { 205 | "template": "repeater_dbMigrateItem", 206 | "data": { 207 | "dbMigrateType": 1, 208 | "dbMigrateAction": 1, 209 | "dbMigrateName": "dbMigrateTrackingScope_END", 210 | "dbMigrateOldName": "" 211 | } 212 | }, 213 | { 214 | "template": "repeater_dbMigrateItem", 215 | "data": { 216 | "dbMigrateType": 2, 217 | "dbMigrateAction": 1, 218 | "dbMigrateName": "DbMigration", 219 | "dbMigrateOldName": "" 220 | } 221 | }, 222 | { 223 | "template": "repeater_dbMigrateItem", 224 | "data": { 225 | "dbMigrateType": 2, 226 | "dbMigrateAction": 1, 227 | "dbMigrateName": "DbComparison", 228 | "dbMigrateOldName": "" 229 | } 230 | }, 231 | { 232 | "template": "repeater_dbMigrateItem", 233 | "data": { 234 | "dbMigrateType": 2, 235 | "dbMigrateAction": 1, 236 | "dbMigrateName": "DbMigrations", 237 | "dbMigrateOldName": "" 238 | } 239 | }, 240 | { 241 | "template": "repeater_dbMigrateItem", 242 | "data": { 243 | "dbMigrateType": 3, 244 | "dbMigrateAction": 1, 245 | "dbMigrateName": "/processwire/dbmigrations/", 246 | "dbMigrateOldName": "" 247 | } 248 | }, 249 | { 250 | "template": "repeater_dbMigrateItem", 251 | "data": { 252 | "dbMigrateType": 3, 253 | "dbMigrateAction": 1, 254 | "dbMigrateName": "/processwire/dbcomparisons/", 255 | "dbMigrateOldName": "" 256 | } 257 | } 258 | ], 259 | "dbMigrateSnippets": [] 260 | } 261 | } 262 | }, 263 | "sourceDb": "MetaTunes Master", 264 | "sourceSiteUrl": "/site/" 265 | } -------------------------------------------------------------------------------- /bootstrap/new/migration.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": { 3 | "changed": { 4 | "/processwire/dbmigrations/bootstrap/": { 5 | "template": "DbMigration", 6 | "parent": "/processwire/dbmigrations/", 7 | "status": 1, 8 | "name": "bootstrap", 9 | "id": 1357, 10 | "title": "bootstrap", 11 | "dbMigrateLogChanges": 2, 12 | "dbMigrateSummary": "This is the initial migration to install all the required fields, templates and pages for the module to work. It is bootstrapped, on first running the ProcessDbMigrate module, from the json files.", 13 | "dbMigrateAdditionalDetails": "

If you want to amend this bootstrap, for example to implement changes to the layout of the DbMigration template, then you may need to first make it 'exportable' in the source (development) environment by removing the meta('installable') from this page.

", 14 | "dbMigrateItem": [ 15 | { 16 | "template": "repeater_dbMigrateItem", 17 | "data": { 18 | "dbMigrateType": 1, 19 | "dbMigrateAction": 1, 20 | "dbMigrateName": "dbMigrateType", 21 | "dbMigrateOldName": "" 22 | } 23 | }, 24 | { 25 | "template": "repeater_dbMigrateItem", 26 | "data": { 27 | "dbMigrateType": 1, 28 | "dbMigrateAction": 1, 29 | "dbMigrateName": "dbMigrateAction", 30 | "dbMigrateOldName": "" 31 | } 32 | }, 33 | { 34 | "template": "repeater_dbMigrateItem", 35 | "data": { 36 | "dbMigrateType": 1, 37 | "dbMigrateAction": 1, 38 | "dbMigrateName": "dbMigrateName", 39 | "dbMigrateOldName": "" 40 | } 41 | }, 42 | { 43 | "template": "repeater_dbMigrateItem", 44 | "data": { 45 | "dbMigrateType": 1, 46 | "dbMigrateAction": 1, 47 | "dbMigrateName": "dbMigrateOldName", 48 | "dbMigrateOldName": "" 49 | } 50 | }, 51 | { 52 | "template": "repeater_dbMigrateItem", 53 | "data": { 54 | "dbMigrateType": 2, 55 | "dbMigrateAction": 1, 56 | "dbMigrateName": "repeater_dbMigrateItem", 57 | "dbMigrateOldName": "" 58 | } 59 | }, 60 | { 61 | "template": "repeater_dbMigrateItem", 62 | "data": { 63 | "dbMigrateType": 1, 64 | "dbMigrateAction": 1, 65 | "dbMigrateName": "dbMigrateItem", 66 | "dbMigrateOldName": "" 67 | } 68 | }, 69 | { 70 | "template": "repeater_dbMigrateItem", 71 | "data": { 72 | "dbMigrateType": 2, 73 | "dbMigrateAction": 1, 74 | "dbMigrateName": "repeater_dbMigrateComparisonItem", 75 | "dbMigrateOldName": "" 76 | } 77 | }, 78 | { 79 | "template": "repeater_dbMigrateItem", 80 | "data": { 81 | "dbMigrateType": 1, 82 | "dbMigrateAction": 1, 83 | "dbMigrateName": "dbMigrateComparisonItem", 84 | "dbMigrateOldName": "" 85 | } 86 | }, 87 | { 88 | "template": "repeater_dbMigrateItem", 89 | "data": { 90 | "dbMigrateType": 1, 91 | "dbMigrateAction": 1, 92 | "dbMigrateName": "dbMigrateSummary", 93 | "dbMigrateOldName": "" 94 | } 95 | }, 96 | { 97 | "template": "repeater_dbMigrateItem", 98 | "data": { 99 | "dbMigrateType": 1, 100 | "dbMigrateAction": 1, 101 | "dbMigrateName": "dbMigrateAdditionalDetails", 102 | "dbMigrateOldName": "" 103 | } 104 | }, 105 | { 106 | "template": "repeater_dbMigrateItem", 107 | "data": { 108 | "dbMigrateType": 1, 109 | "dbMigrateAction": 1, 110 | "dbMigrateName": "dbMigrateRestrictFields", 111 | "dbMigrateOldName": "" 112 | } 113 | }, 114 | { 115 | "template": "repeater_dbMigrateItem", 116 | "data": { 117 | "dbMigrateType": 2, 118 | "dbMigrateAction": 1, 119 | "dbMigrateName": "repeater_dbMigrateSnippets", 120 | "dbMigrateOldName": "" 121 | } 122 | }, 123 | { 124 | "template": "repeater_dbMigrateItem", 125 | "data": { 126 | "dbMigrateType": 1, 127 | "dbMigrateAction": 1, 128 | "dbMigrateName": "dbMigrateSnippets", 129 | "dbMigrateOldName": "" 130 | } 131 | }, 132 | { 133 | "template": "repeater_dbMigrateItem", 134 | "data": { 135 | "dbMigrateType": 1, 136 | "dbMigrateAction": 1, 137 | "dbMigrateName": "dbMigrateRuntimeControl", 138 | "dbMigrateOldName": "" 139 | } 140 | }, 141 | { 142 | "template": "repeater_dbMigrateItem", 143 | "data": { 144 | "dbMigrateType": 1, 145 | "dbMigrateAction": 1, 146 | "dbMigrateName": "dbMigrateRuntimeAction", 147 | "dbMigrateOldName": "" 148 | } 149 | }, 150 | { 151 | "template": "repeater_dbMigrateItem", 152 | "data": { 153 | "dbMigrateType": 1, 154 | "dbMigrateAction": 1, 155 | "dbMigrateName": "dbMigrateRuntimeReady", 156 | "dbMigrateOldName": "" 157 | } 158 | }, 159 | { 160 | "template": "repeater_dbMigrateItem", 161 | "data": { 162 | "dbMigrateType": 1, 163 | "dbMigrateAction": 1, 164 | "dbMigrateName": "dbMigrateLogChanges", 165 | "dbMigrateOldName": "" 166 | } 167 | }, 168 | { 169 | "template": "repeater_dbMigrateItem", 170 | "data": { 171 | "dbMigrateType": 1, 172 | "dbMigrateAction": 1, 173 | "dbMigrateName": "dbMigrateTrackingScope", 174 | "dbMigrateOldName": "" 175 | } 176 | }, 177 | { 178 | "template": "repeater_dbMigrateItem", 179 | "data": { 180 | "dbMigrateType": 1, 181 | "dbMigrateAction": 1, 182 | "dbMigrateName": "dbMigrateFieldTracking", 183 | "dbMigrateOldName": "" 184 | } 185 | }, 186 | { 187 | "template": "repeater_dbMigrateItem", 188 | "data": { 189 | "dbMigrateType": 1, 190 | "dbMigrateAction": 1, 191 | "dbMigrateName": "dbMigrateTemplateTracking", 192 | "dbMigrateOldName": "" 193 | } 194 | }, 195 | { 196 | "template": "repeater_dbMigrateItem", 197 | "data": { 198 | "dbMigrateType": 1, 199 | "dbMigrateAction": 1, 200 | "dbMigrateName": "dbMigratePageTracking", 201 | "dbMigrateOldName": "" 202 | } 203 | }, 204 | { 205 | "template": "repeater_dbMigrateItem", 206 | "data": { 207 | "dbMigrateType": 1, 208 | "dbMigrateAction": 1, 209 | "dbMigrateName": "dbMigrateTrackingScope_END", 210 | "dbMigrateOldName": "" 211 | } 212 | }, 213 | { 214 | "template": "repeater_dbMigrateItem", 215 | "data": { 216 | "dbMigrateType": 2, 217 | "dbMigrateAction": 1, 218 | "dbMigrateName": "DbMigration", 219 | "dbMigrateOldName": "" 220 | } 221 | }, 222 | { 223 | "template": "repeater_dbMigrateItem", 224 | "data": { 225 | "dbMigrateType": 2, 226 | "dbMigrateAction": 1, 227 | "dbMigrateName": "DbComparison", 228 | "dbMigrateOldName": "" 229 | } 230 | }, 231 | { 232 | "template": "repeater_dbMigrateItem", 233 | "data": { 234 | "dbMigrateType": 2, 235 | "dbMigrateAction": 1, 236 | "dbMigrateName": "DbMigrations", 237 | "dbMigrateOldName": "" 238 | } 239 | }, 240 | { 241 | "template": "repeater_dbMigrateItem", 242 | "data": { 243 | "dbMigrateType": 3, 244 | "dbMigrateAction": 1, 245 | "dbMigrateName": "/processwire/dbmigrations/", 246 | "dbMigrateOldName": "" 247 | } 248 | }, 249 | { 250 | "template": "repeater_dbMigrateItem", 251 | "data": { 252 | "dbMigrateType": 3, 253 | "dbMigrateAction": 1, 254 | "dbMigrateName": "/processwire/dbcomparisons/", 255 | "dbMigrateOldName": "" 256 | } 257 | } 258 | ], 259 | "dbMigrateSnippets": [] 260 | } 261 | } 262 | }, 263 | "sourceDb": "MetaTunes Master", 264 | "sourceSiteUrl": "/site/" 265 | } -------------------------------------------------------------------------------- /bootstrap/old/migration.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": { 3 | "changed": { 4 | "/processwire/dbmigrations/bootstrap/": { 5 | "template": "DbMigration", 6 | "parent": "/processwire/dbmigrations/", 7 | "status": 1, 8 | "name": "bootstrap", 9 | "id": 1357, 10 | "title": "bootstrap", 11 | "dbMigrateLogChanges": 2, 12 | "dbMigrateSummary": "This is the initial migration to install all the required fields, templates and pages for the module to work. It is bootstrapped, on first running the ProcessDbMigrate module, from the json files.", 13 | "dbMigrateAdditionalDetails": "

If you want to amend this bootstrap, for example to implement changes to the layout of the DbMigration template, then you may need to first make it 'exportable' in the source (development) environment by removing the meta('installable') from this page.

", 14 | "dbMigrateItem": [ 15 | { 16 | "template": "repeater_dbMigrateItem", 17 | "data": { 18 | "dbMigrateType": 1, 19 | "dbMigrateAction": 1, 20 | "dbMigrateName": "dbMigrateType", 21 | "dbMigrateOldName": "" 22 | } 23 | }, 24 | { 25 | "template": "repeater_dbMigrateItem", 26 | "data": { 27 | "dbMigrateType": 1, 28 | "dbMigrateAction": 1, 29 | "dbMigrateName": "dbMigrateAction", 30 | "dbMigrateOldName": "" 31 | } 32 | }, 33 | { 34 | "template": "repeater_dbMigrateItem", 35 | "data": { 36 | "dbMigrateType": 1, 37 | "dbMigrateAction": 1, 38 | "dbMigrateName": "dbMigrateName", 39 | "dbMigrateOldName": "" 40 | } 41 | }, 42 | { 43 | "template": "repeater_dbMigrateItem", 44 | "data": { 45 | "dbMigrateType": 1, 46 | "dbMigrateAction": 1, 47 | "dbMigrateName": "dbMigrateOldName", 48 | "dbMigrateOldName": "" 49 | } 50 | }, 51 | { 52 | "template": "repeater_dbMigrateItem", 53 | "data": { 54 | "dbMigrateType": 2, 55 | "dbMigrateAction": 1, 56 | "dbMigrateName": "repeater_dbMigrateItem", 57 | "dbMigrateOldName": "" 58 | } 59 | }, 60 | { 61 | "template": "repeater_dbMigrateItem", 62 | "data": { 63 | "dbMigrateType": 1, 64 | "dbMigrateAction": 1, 65 | "dbMigrateName": "dbMigrateItem", 66 | "dbMigrateOldName": "" 67 | } 68 | }, 69 | { 70 | "template": "repeater_dbMigrateItem", 71 | "data": { 72 | "dbMigrateType": 2, 73 | "dbMigrateAction": 1, 74 | "dbMigrateName": "repeater_dbMigrateComparisonItem", 75 | "dbMigrateOldName": "" 76 | } 77 | }, 78 | { 79 | "template": "repeater_dbMigrateItem", 80 | "data": { 81 | "dbMigrateType": 1, 82 | "dbMigrateAction": 1, 83 | "dbMigrateName": "dbMigrateComparisonItem", 84 | "dbMigrateOldName": "" 85 | } 86 | }, 87 | { 88 | "template": "repeater_dbMigrateItem", 89 | "data": { 90 | "dbMigrateType": 1, 91 | "dbMigrateAction": 1, 92 | "dbMigrateName": "dbMigrateSummary", 93 | "dbMigrateOldName": "" 94 | } 95 | }, 96 | { 97 | "template": "repeater_dbMigrateItem", 98 | "data": { 99 | "dbMigrateType": 1, 100 | "dbMigrateAction": 1, 101 | "dbMigrateName": "dbMigrateAdditionalDetails", 102 | "dbMigrateOldName": "" 103 | } 104 | }, 105 | { 106 | "template": "repeater_dbMigrateItem", 107 | "data": { 108 | "dbMigrateType": 1, 109 | "dbMigrateAction": 1, 110 | "dbMigrateName": "dbMigrateRestrictFields", 111 | "dbMigrateOldName": "" 112 | } 113 | }, 114 | { 115 | "template": "repeater_dbMigrateItem", 116 | "data": { 117 | "dbMigrateType": 2, 118 | "dbMigrateAction": 1, 119 | "dbMigrateName": "repeater_dbMigrateSnippets", 120 | "dbMigrateOldName": "" 121 | } 122 | }, 123 | { 124 | "template": "repeater_dbMigrateItem", 125 | "data": { 126 | "dbMigrateType": 1, 127 | "dbMigrateAction": 1, 128 | "dbMigrateName": "dbMigrateSnippets", 129 | "dbMigrateOldName": "" 130 | } 131 | }, 132 | { 133 | "template": "repeater_dbMigrateItem", 134 | "data": { 135 | "dbMigrateType": 1, 136 | "dbMigrateAction": 1, 137 | "dbMigrateName": "dbMigrateRuntimeControl", 138 | "dbMigrateOldName": "" 139 | } 140 | }, 141 | { 142 | "template": "repeater_dbMigrateItem", 143 | "data": { 144 | "dbMigrateType": 1, 145 | "dbMigrateAction": 1, 146 | "dbMigrateName": "dbMigrateRuntimeAction", 147 | "dbMigrateOldName": "" 148 | } 149 | }, 150 | { 151 | "template": "repeater_dbMigrateItem", 152 | "data": { 153 | "dbMigrateType": 1, 154 | "dbMigrateAction": 1, 155 | "dbMigrateName": "dbMigrateRuntimeReady", 156 | "dbMigrateOldName": "" 157 | } 158 | }, 159 | { 160 | "template": "repeater_dbMigrateItem", 161 | "data": { 162 | "dbMigrateType": 1, 163 | "dbMigrateAction": 1, 164 | "dbMigrateName": "dbMigrateLogChanges", 165 | "dbMigrateOldName": "" 166 | } 167 | }, 168 | { 169 | "template": "repeater_dbMigrateItem", 170 | "data": { 171 | "dbMigrateType": 1, 172 | "dbMigrateAction": 1, 173 | "dbMigrateName": "dbMigrateTrackingScope", 174 | "dbMigrateOldName": "" 175 | } 176 | }, 177 | { 178 | "template": "repeater_dbMigrateItem", 179 | "data": { 180 | "dbMigrateType": 1, 181 | "dbMigrateAction": 1, 182 | "dbMigrateName": "dbMigrateFieldTracking", 183 | "dbMigrateOldName": "" 184 | } 185 | }, 186 | { 187 | "template": "repeater_dbMigrateItem", 188 | "data": { 189 | "dbMigrateType": 1, 190 | "dbMigrateAction": 1, 191 | "dbMigrateName": "dbMigrateTemplateTracking", 192 | "dbMigrateOldName": "" 193 | } 194 | }, 195 | { 196 | "template": "repeater_dbMigrateItem", 197 | "data": { 198 | "dbMigrateType": 1, 199 | "dbMigrateAction": 1, 200 | "dbMigrateName": "dbMigratePageTracking", 201 | "dbMigrateOldName": "" 202 | } 203 | }, 204 | { 205 | "template": "repeater_dbMigrateItem", 206 | "data": { 207 | "dbMigrateType": 1, 208 | "dbMigrateAction": 1, 209 | "dbMigrateName": "dbMigrateTrackingScope_END", 210 | "dbMigrateOldName": "" 211 | } 212 | }, 213 | { 214 | "template": "repeater_dbMigrateItem", 215 | "data": { 216 | "dbMigrateType": 2, 217 | "dbMigrateAction": 1, 218 | "dbMigrateName": "DbMigration", 219 | "dbMigrateOldName": "" 220 | } 221 | }, 222 | { 223 | "template": "repeater_dbMigrateItem", 224 | "data": { 225 | "dbMigrateType": 2, 226 | "dbMigrateAction": 1, 227 | "dbMigrateName": "DbComparison", 228 | "dbMigrateOldName": "" 229 | } 230 | }, 231 | { 232 | "template": "repeater_dbMigrateItem", 233 | "data": { 234 | "dbMigrateType": 2, 235 | "dbMigrateAction": 1, 236 | "dbMigrateName": "DbMigrations", 237 | "dbMigrateOldName": "" 238 | } 239 | }, 240 | { 241 | "template": "repeater_dbMigrateItem", 242 | "data": { 243 | "dbMigrateType": 3, 244 | "dbMigrateAction": 1, 245 | "dbMigrateName": "/processwire/dbmigrations/", 246 | "dbMigrateOldName": "" 247 | } 248 | }, 249 | { 250 | "template": "repeater_dbMigrateItem", 251 | "data": { 252 | "dbMigrateType": 3, 253 | "dbMigrateAction": 1, 254 | "dbMigrateName": "/processwire/dbcomparisons/", 255 | "dbMigrateOldName": "" 256 | } 257 | } 258 | ], 259 | "dbMigrateSnippets": [] 260 | } 261 | } 262 | }, 263 | "sourceDb": "MetaTunes Master", 264 | "sourceSiteUrl": "/site/" 265 | } -------------------------------------------------------------------------------- /RuntimeFields/dbMigrateRuntimeAction.php: -------------------------------------------------------------------------------- 1 | template == ProcessDbMigrate::MIGRATION_TEMPLATE) { 9 | /* @var $page \ProcessWire\DbMigrationPage */ 10 | $migrationPath = $config->paths->templates . ProcessDbMigrate::MIGRATION_PATH . $page->name . '/'; 11 | $config->js('dbMigrateRuntimeAction', [ 12 | 13 | 'confirmRemoveFiles' => __("Are you sure you want to remove the migration files? \nAll files (including those required for uninstallation in this environment) will be removed. 14 | \nThis may mean that some image files may be lost if they are not installed. Please check that all required image files are in /site/assets/files/ before proceeding. 15 | \nThis page will remain and can be re-exported based on the current database (and files)."), 16 | 17 | 'confirmInstall' => __("Installing or uninstalling a migration will change your database. 18 | \nWhile this should be reversible, it is strongly recommended that you BACK UP your database before carrying out this action. 19 | \nClick OK to proceed or cancel if not."), 20 | 21 | 'confirmRemoveOld' => __("You are about to remove the migration files required to uninstall the migration.\n") . __("If you do this, you will no longer be able to uninstall the migration back to its original state.\n") . 22 | sprintf(__('Instead, if re-installing the migration, a new set of %sold/ files will be created to allow uninstallation back to just the current state.'), $migrationPath) . 23 | __("\nPlease only proceed if you accept this.") . sprintf(__(' It may be advisable to take a copy of the current %s/old/ files before proceeding'), $page->name), 24 | 25 | ]); 26 | echo ProcessDbMigrate::helpPopout('Help'); 27 | if($page->status != 1) { 28 | echo __("Page must be published before any actions are available"); 29 | } else { 30 | $installedStatus = $page->meta('installedStatus'); // set by DbMigrationPage::exportData('compare') 31 | $form = wire(new InputfieldWrapper()); 32 | $form->attr('id', 'actions_form'); 33 | 34 | // Only show actions if unlocked 35 | if(!$page->meta('locked')) { 36 | $updated = $page->meta('updated'); 37 | //bd($installedStatus, '$installedStatus in migration actions'); 38 | wire('modules')->get('JqueryUI')->use('modal'); 39 | //bd($migrationPath, 'mig path'); 40 | if($page->meta('installable') and file_exists($migrationPath . 'new/data.json')) { 41 | //bd($page, 'REMOVING DRAFT meta'); 42 | if($page->meta('draft')) $page->meta()->remove('draft'); 43 | if(!$installedStatus['installed'] and is_dir($migrationPath . 'new/') and $updated) { 44 | 45 | //Install button 46 | $install = wire(new InputfieldWrapper()); 47 | $install->label(__('Install actions')); //Install is adjective 48 | $install->description(__('This migration is not (fully) installed. Install it or preview to see the effect of installation.')); 49 | $btn = wire('modules')->get("InputfieldButton"); 50 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/install-migration/?id=" . $page->id); 51 | $btn->attr('id', "install_migration"); 52 | $btn->attr('value', __("Install Migration")); // Install is verb 53 | $btn->notes(__("If an installation did not work completely,\n try redoing it before diagnosing differences with previews.")); 54 | $install->append($btn); 55 | 56 | //Preview button 57 | if(!$installedStatus['installed']) { 58 | $btn = wire('modules')->get("InputfieldButton"); 59 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/preview-diffs/?id=" . $page->id . '&target=install&modal=1'); 60 | $btn->attr('id', "preview-diffs-install"); 61 | $btn->attr('value', __("Preview differences")); 62 | $btn->addClass("pw-modal"); 63 | $install->append($btn); 64 | } 65 | 66 | $form->append($install); 67 | 68 | } else { 69 | $install = wire(new InputfieldWrapper()); 70 | $install->label(__('Install actions')); //Install is adjective 71 | $mkup = wire('modules')->get("InputfieldMarkup"); 72 | if($updated) { 73 | $annotate = (is_dir($migrationPath . 'old/')) ? __("You may uninstall it.") : __("It is not possible to uninstall it."); 74 | $mkup->attr('value', __("This migration is installed. No further install actions are required.\n") . $annotate); //Install is adjective 75 | } else { 76 | if(!$page->meta('installedStatus')['uninstalledMigrationKey']) { 77 | $mkup->attr('value', __("The migration definition on this page has a different scope than that in /old/migration.json. 78 | Perhaps you have restored an earlier backup database, in which case find the matching /archive/old/ files and restore those to /old/.")); 79 | } else { 80 | $mkup->attr('value', __("The definition for this migration has changed. You need to uninstall it fully then refresh it before you can install the new version.")); 81 | } 82 | $btn = wire('modules')->get("InputfieldButton"); 83 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/remove-files/?id=" . $page->id . "&oldOnly=1"); 84 | $btn->attr('id', "remove_old"); 85 | $btn->attr('value', __("Remove uninstallation files - caution!")); 86 | $btn->attr('style', 'background-color:red'); 87 | $btn->notes(__("If all else fails, this will remove the /old/ directory and refresh the page. Be aware that this will reset the uninstall action to only restore the current state, not the original state.")); 88 | } 89 | $install->append($mkup); 90 | if(isset($btn)) $install->append($btn); 91 | $form->append($install); 92 | } 93 | if(!$installedStatus['uninstalled'] and is_dir($migrationPath . 'old/')) { 94 | 95 | //Uninstall button 96 | $uninstall = wire(new InputfieldWrapper()); 97 | $uninstall->label(__('Uninstall actions')); //Uninstall is adjective 98 | if($page->name != 'bootstrap') { 99 | $uninstall->description(__('This migration is not (fully) uninstalled. Uninstall it or preview to see the effect of uninstallation.')); 100 | $btn = wire('modules')->get("InputfieldButton"); 101 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/uninstall-migration/?id=" . $page->id); 102 | $btn->attr('id', "uninstall_migration"); 103 | $btn->attr('value', __("Uninstall Migration")); // Uninstall is verb 104 | $btn->notes(__("If an uninstallation did not work completely,\n try redoing it before diagnosing differences with previews.")); 105 | $uninstall->append($btn); 106 | } else { 107 | $uninstall->notes(__("Bootstrap is only uninstallable by uninstalling ProcessDbMigrate module")); 108 | } 109 | 110 | //Preview button 111 | if(!$installedStatus['uninstalled']) { 112 | $btn = wire('modules')->get("InputfieldButton"); 113 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/preview-diffs/?id=" . $page->id . '&target=uninstall&modal=1'); 114 | $btn->attr('id', "preview-diffs-uninstall"); 115 | $btn->attr('value', __("Preview differences")); 116 | $btn->addClass("pw-modal"); 117 | $uninstall->append($btn); 118 | } 119 | 120 | $form->append($uninstall); 121 | } 122 | 123 | } else if(!$page->meta('installable')) { 124 | 125 | // Export button 126 | $btn = wire('modules')->get("InputfieldButton"); 127 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/export-data/?id=" . $page->id); 128 | $btn->attr('id', "export_data"); 129 | $btn->attr('value', __("Export Data")); 130 | $form->append($btn); 131 | 132 | // Preview button 133 | if(!isset($installedStatus['installed']) || !$installedStatus['installed']) { 134 | $btn = wire('modules')->get("InputfieldButton"); 135 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/preview-diffs/?id=" . $page->id . '&target=export&modal=1'); 136 | $btn->attr('id', "preview-diffs-export"); 137 | $btn->attr('value', __("Preview differences")); 138 | $btn->notes(__('No differences will be shown for "removed" actions as these objects do not (or, at least, should not) exist here.')); 139 | $btn->addClass("pw-modal"); 140 | $form->append($btn); 141 | } 142 | 143 | //Remove migration files button 144 | if(is_dir($migrationPath . 'old/') or is_dir($migrationPath . 'new/')) { 145 | $btn = wire('modules')->get("InputfieldButton"); 146 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/remove-files/?id=" . $page->id); 147 | $btn->attr('id', "remove_files"); 148 | $btn->attr('value', __("Remove migration files")); 149 | $btn->notes(__('Removes all files, but only files')); 150 | $form->append($btn); 151 | } 152 | 153 | } else { 154 | echo __("You need to export data from the source database in order to install this migration"); 155 | if($page->meta('draft')) echo('
' . __("The migration files need to be sync'd first") . ': ' . $migrationPath); 156 | } 157 | 158 | } else { 159 | // for locked installable migrations show the complete diffs between old and new 160 | if($page->meta('installable') and $installedStatus['reviewedDataDiffs']) { 161 | $review = wire(new InputfieldWrapper()); 162 | $review->label(__('Review all changes')); 163 | $review->description(__('No actions are available, but you can review all the changes included in this migration')); 164 | $review->notes(__('Note that it is assumed the migration was fully installed before locking. Subsequent changes may have occurred.')); 165 | $btn = wire('modules')->get("InputfieldButton"); 166 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/preview-diffs/?id=" . $page->id . '&target=review&modal=1'); 167 | $btn->attr('id', "preview-diffs-review"); 168 | $btn->attr('value', __("Review total differences")); 169 | $btn->addClass("pw-modal"); 170 | $review->append($btn); 171 | $form->append($review); 172 | } 173 | } 174 | echo $form->render(); 175 | } 176 | } 177 | 178 | if($page->template == ProcessDbMigrate::COMPARISON_TEMPLATE) { 179 | /* @var $page \ProcessWire\DbComparisonPage */ 180 | if($page->status != 1) { 181 | echo __("Page must be published before any actions are available"); 182 | } else { 183 | $installedStatus = $page->meta('installedStatus'); 184 | $comparisonPath = $page->comparisonsPath . $page->name . '/'; 185 | $form = wire(new InputfieldWrapper()); 186 | $form->attr('id', 'actions_form'); 187 | if($page->meta('installable')) { 188 | 189 | // Compare button 190 | $btn = wire('modules')->get("InputfieldButton"); 191 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/preview-diffs/?id=" . $page->id . '&target=install&modal=1'); 192 | $btn->attr('id', "compare-diffs"); 193 | $btn->attr('value', __("Compare database")); 194 | $btn->notes(__('Differences will only be shown within the scope of the items below.') . ' '); 195 | $btn->addClass("pw-modal"); 196 | $form->append($btn); 197 | 198 | // Button to create draft migration from comparison 199 | $btn = wire('modules')->get("InputfieldButton"); 200 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/preview-diffs/?id=" . $page->id . '&target=install&button=draft&modal=1'); 201 | $btn->attr('id', "prepare-draft"); 202 | $btn->attr('value', __("Create a draft migration for this comparison")); 203 | $btn->notes(__('Migration will be restricted to the scope of the items below. ')); 204 | $btn->addClass("pw-modal"); 205 | $form->append($btn); 206 | 207 | } else { 208 | // Export button 209 | $btn = wire('modules')->get("InputfieldButton"); 210 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/export-data/?id=" . $page->id . "&type=comparison"); 211 | $btn->attr('id', "export_data"); 212 | $btn->attr('value', __("Export Data")); 213 | $form->append($btn); 214 | 215 | 216 | // Preview button 217 | if(!isset($installedStatus['installed']) || !$installedStatus['installed']) { 218 | $btn = wire('modules')->get("InputfieldButton"); 219 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/preview-diffs/?id=" . $page->id . '&target=export&modal=1'); 220 | $btn->attr('id', "preview-diffs-export"); 221 | $btn->attr('value', __("Preview differences")); 222 | // $btn->notes(__('')); 223 | $btn->addClass("pw-modal"); 224 | $form->append($btn); 225 | } 226 | 227 | //Remove migration files button 228 | if(is_dir($comparisonPath . 'old/') or is_dir($comparisonPath . 'new/')) { 229 | $btn = wire('modules')->get("InputfieldButton"); 230 | $btn->attr('href', wire('config')->urls->admin . "setup/dbmigrations/remove-files/?id=" . $page->id); 231 | $btn->attr('id', "remove_files"); 232 | $btn->attr('value', __("Remove comparison files")); 233 | $btn->notes(__('Removes all files, but only files')); 234 | $form->append($btn); 235 | } 236 | } 237 | echo $form->render(); 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /new/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "new": { 5 | "dbMigrateType": { 6 | "name": "dbMigrateType", 7 | "label": "Object type", 8 | "flags": 8, 9 | "type": "FieldtypeOptions", 10 | "inputfieldClass": "InputfieldSelect", 11 | "export_options": { 12 | "default": "1=fields|Field\n2=templates|Template\n3=pages|Page" 13 | }, 14 | "tags": "dbMigrate", 15 | "initValue": "", 16 | "collapsed": 0, 17 | "showIf": "", 18 | "themeInputSize": "", 19 | "themeInputWidth": "", 20 | "themeOffset": "", 21 | "themeBorder": "", 22 | "themeColor": "", 23 | "columnWidth": "", 24 | "required": "", 25 | "requiredIf": "", 26 | "defaultValue": "" 27 | } 28 | } 29 | } 30 | }, 31 | { 32 | "fields": { 33 | "new": { 34 | "dbMigrateAction": { 35 | "name": "dbMigrateAction", 36 | "label": "Action", 37 | "flags": 8, 38 | "type": "FieldtypeOptions", 39 | "inputfieldClass": "InputfieldSelect", 40 | "export_options": { 41 | "default": "1=new|New\n2=changed|Changed\n3=removed|Removed" 42 | }, 43 | "tags": "dbMigrate", 44 | "initValue": "", 45 | "collapsed": 0, 46 | "showIf": "", 47 | "themeInputSize": "", 48 | "themeInputWidth": "", 49 | "themeOffset": "", 50 | "themeBorder": "", 51 | "themeColor": "", 52 | "columnWidth": "", 53 | "required": "", 54 | "requiredIf": "", 55 | "defaultValue": "" 56 | } 57 | } 58 | } 59 | }, 60 | { 61 | "fields": { 62 | "new": { 63 | "dbMigrateName": { 64 | "name": "dbMigrateName", 65 | "label": "Name (path for pages) or selector", 66 | "flags": 8, 67 | "type": "FieldtypeText", 68 | "maxlength": 2048, 69 | "tags": "dbMigrate", 70 | "textformatters": [ 71 | "TextformatterEntities" 72 | ], 73 | "inputfieldClass": "", 74 | "collapsed": 0, 75 | "showIf": "", 76 | "themeInputSize": "", 77 | "themeInputWidth": "", 78 | "themeOffset": "", 79 | "themeBorder": "", 80 | "themeColor": "", 81 | "themeBlank": "", 82 | "columnWidth": "", 83 | "required": "", 84 | "requiredAttr": "", 85 | "requiredIf": "", 86 | "minlength": 0, 87 | "showCount": 0, 88 | "size": 0, 89 | "stripTags": "", 90 | "placeholder": "", 91 | "pattern": "" 92 | } 93 | } 94 | } 95 | }, 96 | { 97 | "fields": { 98 | "new": { 99 | "dbMigrateOldName": { 100 | "name": "dbMigrateOldName", 101 | "label": "Old name if different (n/a for selectors)", 102 | "flags": 8, 103 | "type": "FieldtypeText", 104 | "maxlength": 2048, 105 | "tags": "dbMigrate", 106 | "textformatters": [ 107 | "TextformatterEntities" 108 | ], 109 | "inputfieldClass": "", 110 | "collapsed": 0, 111 | "showIf": "", 112 | "themeInputSize": "", 113 | "themeInputWidth": "", 114 | "themeOffset": "", 115 | "themeBorder": "", 116 | "themeColor": "", 117 | "themeBlank": "", 118 | "columnWidth": "", 119 | "required": "", 120 | "requiredAttr": "", 121 | "requiredIf": "", 122 | "minlength": 0, 123 | "showCount": 0, 124 | "size": 0, 125 | "stripTags": "", 126 | "placeholder": "", 127 | "pattern": "" 128 | } 129 | } 130 | } 131 | }, 132 | { 133 | "templates": { 134 | "new": { 135 | "repeater_dbMigrateItem": { 136 | "name": "repeater_dbMigrateItem", 137 | "fieldgroups_id": "repeater_dbMigrateItem", 138 | "flags": 8, 139 | "cache_time": 0, 140 | "useRoles": 0, 141 | "noInherit": 0, 142 | "childrenTemplatesID": 0, 143 | "sortfield": "", 144 | "noChildren": 1, 145 | "noParents": 1, 146 | "childTemplates": [], 147 | "parentTemplates": [], 148 | "allowPageNum": 0, 149 | "allowChangeUser": 0, 150 | "redirectLogin": 0, 151 | "urlSegments": 0, 152 | "https": 0, 153 | "slashUrls": 1, 154 | "slashPageNum": 0, 155 | "slashUrlSegments": 0, 156 | "altFilename": "", 157 | "guestSearchable": 0, 158 | "pageClass": "RepeaterPage", 159 | "childNameFormat": "", 160 | "pageLabelField": "", 161 | "noGlobal": 1, 162 | "noMove": 0, 163 | "noTrash": 0, 164 | "noSettings": 0, 165 | "noChangeTemplate": 0, 166 | "noShortcut": 0, 167 | "noUnpublish": 0, 168 | "noLang": 0, 169 | "compile": 3, 170 | "nameContentTab": 0, 171 | "noCacheGetVars": "", 172 | "noCachePostVars": "", 173 | "useCacheForUsers": 0, 174 | "cacheExpire": 0, 175 | "cacheExpirePages": [], 176 | "cacheExpireSelector": "", 177 | "label": "", 178 | "tags": "dbMigrate", 179 | "titleNames": 0, 180 | "noPrependTemplateFile": 0, 181 | "noAppendTemplateFile": 0, 182 | "prependFile": "", 183 | "appendFile": "", 184 | "pagefileSecure": 0, 185 | "tabContent": "", 186 | "tabChildren": "", 187 | "nameLabel": "", 188 | "contentType": "", 189 | "errorAction": 0, 190 | "connectedFieldID": null, 191 | "ns": "", 192 | "fieldgroupFields": [ 193 | "dbMigrateType", 194 | "dbMigrateAction", 195 | "dbMigrateName", 196 | "dbMigrateOldName" 197 | ], 198 | "fieldgroupContexts": { 199 | "dbMigrateType": { 200 | "columnWidth": 10 201 | }, 202 | "dbMigrateAction": { 203 | "columnWidth": 10 204 | }, 205 | "dbMigrateName": { 206 | "columnWidth": 55 207 | }, 208 | "dbMigrateOldName": { 209 | "columnWidth": 25 210 | } 211 | } 212 | } 213 | } 214 | } 215 | }, 216 | { 217 | "fields": { 218 | "new": { 219 | "dbMigrateItem": { 220 | "name": "dbMigrateItem", 221 | "label": "Migration item", 222 | "flags": 8, 223 | "type": "FieldtypeRepeater", 224 | "repeaterLoading": 1, 225 | "repeaterTitle": "#n: {dbMigrateAction} {dbMigrateType}: {dbMigrateName}", 226 | "tags": "dbMigrate", 227 | "notes": "Migration items are colour-coded by object type (green fields, brown templates and blue pages).\n'Magic wand' icons indicate 'magic' items that have been added automatically by 'log changes'.\n'Down-arrow' icons indicate magic items that are dependent on other items (where known).\nNote that (with automatic sorting) dependent items will appear later if a 'new' item or earlier if 'removed'.\nNon-magic 'removed' items will need to be sorted manually as the system has no data for them.", 228 | "familyFriendly": 0, 229 | "repeaterCollapse": 0, 230 | "rememberOpen": 0, 231 | "accordionMode": 0, 232 | "loudControls": 0, 233 | "repeaterDepth": "", 234 | "repeaterAddLabel": "", 235 | "repeaterMaxItems": "", 236 | "repeaterMinItems": "", 237 | "lazyParents": "", 238 | "collapsed": 0, 239 | "showIf": "", 240 | "themeOffset": "", 241 | "themeBorder": "", 242 | "themeColor": "", 243 | "columnWidth": "", 244 | "required": "", 245 | "requiredIf": "", 246 | "template_name": "repeater_dbMigrateItem" 247 | } 248 | } 249 | } 250 | }, 251 | { 252 | "templates": { 253 | "new": { 254 | "repeater_dbMigrateComparisonItem": { 255 | "name": "repeater_dbMigrateComparisonItem", 256 | "fieldgroups_id": "repeater_dbMigrateComparisonItem", 257 | "flags": 8, 258 | "cache_time": 0, 259 | "useRoles": 0, 260 | "noInherit": 0, 261 | "childrenTemplatesID": 0, 262 | "sortfield": "", 263 | "noChildren": 1, 264 | "noParents": 1, 265 | "childTemplates": [], 266 | "parentTemplates": [], 267 | "allowPageNum": 0, 268 | "allowChangeUser": 0, 269 | "redirectLogin": 0, 270 | "urlSegments": 0, 271 | "https": 0, 272 | "slashUrls": 1, 273 | "slashPageNum": 0, 274 | "slashUrlSegments": 0, 275 | "altFilename": "", 276 | "guestSearchable": 0, 277 | "pageClass": "RepeaterPage", 278 | "childNameFormat": "", 279 | "pageLabelField": "", 280 | "noGlobal": 1, 281 | "noMove": 0, 282 | "noTrash": 0, 283 | "noSettings": 0, 284 | "noChangeTemplate": 0, 285 | "noShortcut": 0, 286 | "noUnpublish": 0, 287 | "noLang": 0, 288 | "compile": 3, 289 | "nameContentTab": 0, 290 | "noCacheGetVars": "", 291 | "noCachePostVars": "", 292 | "useCacheForUsers": 0, 293 | "cacheExpire": 0, 294 | "cacheExpirePages": [], 295 | "cacheExpireSelector": "", 296 | "label": "", 297 | "tags": "dbMigrate", 298 | "titleNames": 0, 299 | "noPrependTemplateFile": 0, 300 | "noAppendTemplateFile": 0, 301 | "prependFile": "", 302 | "appendFile": "", 303 | "pagefileSecure": 0, 304 | "tabContent": "", 305 | "tabChildren": "", 306 | "nameLabel": "", 307 | "contentType": "", 308 | "errorAction": 0, 309 | "connectedFieldID": null, 310 | "ns": "", 311 | "fieldgroupFields": [ 312 | "dbMigrateType", 313 | "dbMigrateName" 314 | ], 315 | "fieldgroupContexts": { 316 | "dbMigrateType": [], 317 | "dbMigrateName": [] 318 | } 319 | } 320 | } 321 | } 322 | }, 323 | { 324 | "fields": { 325 | "new": { 326 | "dbMigrateComparisonItem": { 327 | "name": "dbMigrateComparisonItem", 328 | "label": "Comparison item", 329 | "flags": 8, 330 | "type": "FieldtypeRepeater", 331 | "repeaterLoading": 1, 332 | "repeaterTitle": "#1: {dbMigrateType} - {dbMigrateName}", 333 | "tags": "dbMigrate", 334 | "repeaterDepth": "", 335 | "familyFriendly": 0, 336 | "repeaterAddLabel": "", 337 | "repeaterCollapse": 0, 338 | "rememberOpen": 0, 339 | "accordionMode": 0, 340 | "loudControls": 0, 341 | "repeaterMaxItems": "", 342 | "repeaterMinItems": "", 343 | "lazyParents": "", 344 | "collapsed": 0, 345 | "showIf": "", 346 | "themeOffset": "", 347 | "themeBorder": "", 348 | "themeColor": "", 349 | "columnWidth": "", 350 | "required": "", 351 | "requiredIf": "", 352 | "template_name": "repeater_dbMigrateComparisonItem" 353 | } 354 | } 355 | } 356 | }, 357 | { 358 | "fields": { 359 | "new": { 360 | "dbMigrateSummary": { 361 | "name": "dbMigrateSummary", 362 | "label": "Summary", 363 | "flags": 8, 364 | "type": "FieldtypeTextarea", 365 | "textformatters": [ 366 | "TextformatterEntities" 367 | ], 368 | "inputfieldClass": "InputfieldTextarea", 369 | "rows": 5, 370 | "tags": "dbMigrate", 371 | "contentType": 0, 372 | "htmlOptions": "", 373 | "collapsed": 0, 374 | "showIf": "", 375 | "themeInputSize": "", 376 | "themeOffset": "", 377 | "themeBorder": "", 378 | "themeColor": "", 379 | "themeBlank": "", 380 | "columnWidth": "", 381 | "required": "", 382 | "requiredAttr": "", 383 | "requiredIf": "", 384 | "minlength": 0, 385 | "maxlength": 0, 386 | "showCount": 0, 387 | "stripTags": "", 388 | "placeholder": "" 389 | } 390 | } 391 | } 392 | }, 393 | { 394 | "fields": { 395 | "new": { 396 | "dbMigrateAdditionalDetails": { 397 | "name": "dbMigrateAdditionalDetails", 398 | "label": "Additional details", 399 | "flags": 8, 400 | "type": "FieldtypeTextarea", 401 | "inputfieldClass": "InputfieldCKEditor", 402 | "contentType": 1, 403 | "rows": 8, 404 | "toolbar": "Format, Styles, -, Bold, Italic, -, RemoveFormat\nNumberedList, BulletedList, -, Blockquote\nPWLink, Unlink, Anchor\nPWImage, Table, HorizontalRule, SpecialChar\nPasteText, PasteFromWord\nTextColor, BGColor\nScayt, -, Sourcedialog", 405 | "useACF": 1, 406 | "usePurifier": 1, 407 | "toggles": [ 408 | 2, 409 | 4, 410 | 8 411 | ], 412 | "formatTags": "p;h1;h2;h3;h4;h5;h6;pre;address", 413 | "extraPlugins": [ 414 | "colorbutton", 415 | "pwimage", 416 | "pwlink", 417 | "sourcedialog" 418 | ], 419 | "removePlugins": "image,magicline", 420 | "extraAllowedContent": "br\ntd(box-top,box-middle,box-bottom,box-total)\ntable(uk-table)\ndiv(uk-overflow-auto)\nth(uk-table-shrink)\ntd(uk-table-shrink)\nblockquote(clearfix)\nimg[alt,!src,width,height]", 421 | "tags": "dbMigrate", 422 | "textformatters": "", 423 | "htmlOptions": "", 424 | "collapsed": 0, 425 | "showIf": "", 426 | "themeOffset": "", 427 | "themeBorder": "", 428 | "themeColor": "", 429 | "columnWidth": "", 430 | "required": "", 431 | "requiredAttr": "", 432 | "requiredIf": "", 433 | "minlength": 0, 434 | "maxlength": 0, 435 | "showCount": 0, 436 | "inheritField": "", 437 | "inlineMode": 0, 438 | "imageFields": "", 439 | "contentsCss": "", 440 | "contentsInlineCss": "", 441 | "stylesSet": "", 442 | "customOptions": "", 443 | "plugin_sourcedialog": "" 444 | } 445 | } 446 | } 447 | }, 448 | { 449 | "fields": { 450 | "new": { 451 | "dbMigrateRestrictFields": { 452 | "name": "dbMigrateRestrictFields", 453 | "label": "Restrict fields", 454 | "flags": 8, 455 | "type": "FieldtypeTextarea", 456 | "description": "Enter list of field names (comma-separated) that will be migrated for selected pages (leave blank to migrate all except globally excluded fields)", 457 | "notes": "This only affects this migration. To exclude specific fields or field types from all page migrations, use the module config settings.", 458 | "textformatters": [ 459 | "TextformatterEntities" 460 | ], 461 | "inputfieldClass": "InputfieldTextarea", 462 | "rows": 5, 463 | "tags": "dbMigrate", 464 | "contentType": 0, 465 | "htmlOptions": "", 466 | "collapsed": 0, 467 | "showIf": "", 468 | "themeInputSize": "", 469 | "themeOffset": "", 470 | "themeBorder": "", 471 | "themeColor": "", 472 | "themeBlank": "", 473 | "columnWidth": "", 474 | "required": "", 475 | "requiredAttr": "", 476 | "requiredIf": "", 477 | "minlength": 0, 478 | "maxlength": 0, 479 | "showCount": 0, 480 | "stripTags": "", 481 | "placeholder": "" 482 | } 483 | } 484 | } 485 | }, 486 | { 487 | "templates": { 488 | "new": { 489 | "repeater_dbMigrateSnippets": { 490 | "name": "repeater_dbMigrateSnippets", 491 | "fieldgroups_id": "repeater_dbMigrateSnippets", 492 | "flags": 8, 493 | "cache_time": 0, 494 | "useRoles": 0, 495 | "noInherit": 0, 496 | "childrenTemplatesID": 0, 497 | "sortfield": "", 498 | "noChildren": 1, 499 | "noParents": 1, 500 | "childTemplates": [], 501 | "parentTemplates": [], 502 | "allowPageNum": 0, 503 | "allowChangeUser": 0, 504 | "redirectLogin": 0, 505 | "urlSegments": 0, 506 | "https": 0, 507 | "slashUrls": 1, 508 | "slashPageNum": 0, 509 | "slashUrlSegments": 0, 510 | "altFilename": "", 511 | "guestSearchable": 0, 512 | "pageClass": "RepeaterPage", 513 | "childNameFormat": "", 514 | "pageLabelField": "", 515 | "noGlobal": 1, 516 | "noMove": 0, 517 | "noTrash": 0, 518 | "noSettings": 0, 519 | "noChangeTemplate": 0, 520 | "noShortcut": 0, 521 | "noUnpublish": 0, 522 | "noLang": 0, 523 | "compile": 3, 524 | "nameContentTab": 0, 525 | "noCacheGetVars": "", 526 | "noCachePostVars": "", 527 | "useCacheForUsers": 0, 528 | "cacheExpire": 0, 529 | "cacheExpirePages": [], 530 | "cacheExpireSelector": "", 531 | "label": "", 532 | "tags": "dbMigrate", 533 | "titleNames": 0, 534 | "noPrependTemplateFile": 0, 535 | "noAppendTemplateFile": 0, 536 | "prependFile": "", 537 | "appendFile": "", 538 | "pagefileSecure": 0, 539 | "tabContent": "", 540 | "tabChildren": "", 541 | "nameLabel": "", 542 | "contentType": "", 543 | "errorAction": 0, 544 | "connectedFieldID": null, 545 | "ns": "", 546 | "fieldgroupFields": [ 547 | "title", 548 | "dbMigrateSummary" 549 | ], 550 | "fieldgroupContexts": { 551 | "title": { 552 | "label": "Description" 553 | }, 554 | "dbMigrateSummary": { 555 | "label": "Snippet" 556 | } 557 | } 558 | } 559 | } 560 | } 561 | }, 562 | { 563 | "fields": { 564 | "new": { 565 | "dbMigrateSnippets": { 566 | "name": "dbMigrateSnippets", 567 | "label": "Snippets", 568 | "flags": 8, 569 | "type": "FieldtypeRepeater", 570 | "repeaterLoading": 1, 571 | "repeaterTitle": "#n: {title}", 572 | "tags": "dbMigrate", 573 | "repeaterDepth": "", 574 | "familyFriendly": 0, 575 | "repeaterAddLabel": "", 576 | "repeaterCollapse": 0, 577 | "rememberOpen": 0, 578 | "accordionMode": 0, 579 | "loudControls": 0, 580 | "repeaterMaxItems": "", 581 | "repeaterMinItems": "", 582 | "lazyParents": "", 583 | "collapsed": 0, 584 | "showIf": "", 585 | "themeOffset": "", 586 | "themeBorder": "", 587 | "themeColor": "", 588 | "columnWidth": "", 589 | "required": "", 590 | "requiredIf": "", 591 | "template_name": "repeater_dbMigrateSnippets" 592 | } 593 | } 594 | } 595 | }, 596 | { 597 | "fields": { 598 | "new": { 599 | "dbMigrateRuntimeControl": { 600 | "name": "dbMigrateRuntimeControl", 601 | "label": "Page Status", 602 | "flags": 8, 603 | "type": "FieldtypeDbMigrateRuntime", 604 | "tags": "dbMigrate", 605 | "collapsed": 0, 606 | "showIf": "", 607 | "themeOffset": "", 608 | "themeBorder": "", 609 | "themeColor": "", 610 | "columnWidth": "", 611 | "required": "", 612 | "requiredIf": "" 613 | } 614 | } 615 | } 616 | }, 617 | { 618 | "fields": { 619 | "new": { 620 | "dbMigrateRuntimeAction": { 621 | "name": "dbMigrateRuntimeAction", 622 | "label": "Migration Actions", 623 | "flags": 8, 624 | "type": "FieldtypeDbMigrateRuntime", 625 | "tags": "dbMigrate", 626 | "collapsed": 0, 627 | "showIf": "", 628 | "themeOffset": "", 629 | "themeBorder": "", 630 | "themeColor": "", 631 | "columnWidth": "", 632 | "required": "", 633 | "requiredIf": "" 634 | } 635 | } 636 | } 637 | }, 638 | { 639 | "fields": { 640 | "new": { 641 | "dbMigrateRuntimeReady": { 642 | "name": "dbMigrateRuntimeReady", 643 | "label": "ready.php", 644 | "flags": 8, 645 | "type": "FieldtypeDbMigrateRuntime", 646 | "description": "Contents of site/templates/DbMigrate/migrations/{migration name}/ready.php", 647 | "notes": "This migration-specific ready.php file is for hooks after install etc.", 648 | "tags": "dbMigrate", 649 | "collapsed": 0, 650 | "showIf": "", 651 | "themeOffset": "", 652 | "themeBorder": "", 653 | "themeColor": "", 654 | "columnWidth": "", 655 | "required": "", 656 | "requiredIf": "" 657 | } 658 | } 659 | } 660 | }, 661 | { 662 | "fields": { 663 | "new": { 664 | "dbMigrateLogChanges": { 665 | "name": "dbMigrateLogChanges", 666 | "label": "Log changes", 667 | "flags": 8, 668 | "type": "FieldtypeToggle", 669 | "description": "If *log changes* is selected, any changes to fields, templates or pages which are **within the scope of the selectors set in the module configuration** will be added to the migration items list.", 670 | "formatType": 0, 671 | "labelType": 100, 672 | "inputfieldClass": 0, 673 | "useVertical": 0, 674 | "yesLabel": "Log changes", 675 | "noLabel": "Sort items on save", 676 | "otherLabel": "Manual", 677 | "defaultOption": "other", 678 | "useOther": 1, 679 | "notes": "Alternatively, you can turn change logging off and either have the module sort your items into dependency order or only allow manual changes to the items and sort order.", 680 | "tags": "dbMigrate", 681 | "useReverse": "", 682 | "useDeselect": "", 683 | "collapsed": 0, 684 | "showIf": "", 685 | "themeOffset": "", 686 | "themeBorder": "", 687 | "themeColor": "", 688 | "columnWidth": "", 689 | "required": "", 690 | "requiredIf": "" 691 | } 692 | } 693 | } 694 | }, 695 | { 696 | "fields": { 697 | "new": { 698 | "dbMigrateTrackingScope": { 699 | "name": "dbMigrateTrackingScope", 700 | "label": "Scope of change tracking", 701 | "flags": 8, 702 | "type": "FieldtypeFieldsetOpen", 703 | "description": "Use selectors to define scope of object changes to be tracked", 704 | "notes": "If you do not enter a selector then no changes will be tracked. Enter id>0 to (potentially) track everything.", 705 | "closeFieldID": 142, 706 | "tags": "dbMigrate", 707 | "collapsed": 0, 708 | "showIf": "", 709 | "columnWidth": "" 710 | } 711 | } 712 | } 713 | }, 714 | { 715 | "fields": { 716 | "new": { 717 | "dbMigrateFieldTracking": { 718 | "name": "dbMigrateFieldTracking", 719 | "label": "Fields to track", 720 | "flags": 8, 721 | "type": "FieldtypeText", 722 | "description": "Use selector to specify fields to track", 723 | "notes": "Note that any excluded fields and dbMigrate fields will not be tracked", 724 | "textformatters": [ 725 | "TextformatterEntities" 726 | ], 727 | "tags": "dbMigrate", 728 | "collapsed": 0, 729 | "minlength": 0, 730 | "maxlength": 2048, 731 | "showCount": 0, 732 | "size": 0, 733 | "placeholder": "e.g. id>0 to select all fields", 734 | "inputfieldClass": "", 735 | "showIf": "", 736 | "themeInputSize": "", 737 | "themeInputWidth": "", 738 | "themeOffset": "", 739 | "themeBorder": "", 740 | "themeColor": "", 741 | "themeBlank": "", 742 | "columnWidth": "", 743 | "required": "", 744 | "requiredAttr": "", 745 | "requiredIf": "", 746 | "stripTags": "", 747 | "pattern": "" 748 | } 749 | } 750 | } 751 | }, 752 | { 753 | "fields": { 754 | "new": { 755 | "dbMigrateTemplateTracking": { 756 | "name": "dbMigrateTemplateTracking", 757 | "label": "Templates to track", 758 | "flags": 8, 759 | "type": "FieldtypeText", 760 | "description": "Use selector to specify templates to track", 761 | "textformatters": [ 762 | "TextformatterEntities" 763 | ], 764 | "tags": "dbMigrate", 765 | "collapsed": 0, 766 | "minlength": 0, 767 | "maxlength": 2048, 768 | "showCount": 0, 769 | "size": 0, 770 | "placeholder": "e.g. id>0 to select all templates", 771 | "inputfieldClass": "", 772 | "showIf": "", 773 | "themeInputSize": "", 774 | "themeInputWidth": "", 775 | "themeOffset": "", 776 | "themeBorder": "", 777 | "themeColor": "", 778 | "themeBlank": "", 779 | "columnWidth": "", 780 | "required": "", 781 | "requiredAttr": "", 782 | "requiredIf": "", 783 | "stripTags": "", 784 | "pattern": "" 785 | } 786 | } 787 | } 788 | }, 789 | { 790 | "fields": { 791 | "new": { 792 | "dbMigratePageTracking": { 793 | "name": "dbMigratePageTracking", 794 | "label": "Pages to track", 795 | "flags": 8, 796 | "type": "FieldtypeText", 797 | "description": "Use selector to specify pages to track", 798 | "notes": "Typically these will be pages holding settings etc., not normal user-updated pages", 799 | "textformatters": [ 800 | "TextformatterEntities" 801 | ], 802 | "tags": "dbMigrate", 803 | "collapsed": 0, 804 | "minlength": 0, 805 | "maxlength": 4096, 806 | "showCount": 0, 807 | "size": 0, 808 | "inputfieldClass": "", 809 | "showIf": "", 810 | "themeInputSize": "", 811 | "themeInputWidth": "", 812 | "themeOffset": "", 813 | "themeBorder": "", 814 | "themeColor": "", 815 | "themeBlank": "", 816 | "columnWidth": "", 817 | "required": "", 818 | "requiredAttr": "", 819 | "requiredIf": "", 820 | "stripTags": "", 821 | "placeholder": "", 822 | "pattern": "" 823 | } 824 | } 825 | } 826 | }, 827 | { 828 | "fields": { 829 | "new": { 830 | "dbMigrateTrackingScope_END": { 831 | "name": "dbMigrateTrackingScope_END", 832 | "label": "Close an open fieldset", 833 | "flags": 8, 834 | "type": "FieldtypeFieldsetClose", 835 | "description": "This field was added automatically to accompany fieldset 'dbMigrateScope'. It should be placed in your template/fieldgroup wherever you want the fieldset to end.", 836 | "openFieldID": 141, 837 | "tags": "dbMigrate" 838 | } 839 | } 840 | } 841 | }, 842 | { 843 | "templates": { 844 | "new": { 845 | "DbMigration": { 846 | "name": "DbMigration", 847 | "fieldgroups_id": "DbMigration", 848 | "flags": 8, 849 | "cache_time": 0, 850 | "useRoles": 0, 851 | "noInherit": 0, 852 | "childrenTemplatesID": 0, 853 | "sortfield": "", 854 | "noChildren": "", 855 | "noParents": "", 856 | "childTemplates": [], 857 | "parentTemplates": [], 858 | "allowPageNum": 0, 859 | "allowChangeUser": 0, 860 | "redirectLogin": 0, 861 | "urlSegments": 0, 862 | "https": 0, 863 | "slashUrls": 1, 864 | "slashPageNum": 0, 865 | "slashUrlSegments": 0, 866 | "altFilename": "", 867 | "guestSearchable": 0, 868 | "pageClass": "ProcessWire\\DbMigrationPage", 869 | "childNameFormat": "", 870 | "pageLabelField": "", 871 | "noGlobal": 0, 872 | "noMove": 1, 873 | "noTrash": 0, 874 | "noSettings": 0, 875 | "noChangeTemplate": 1, 876 | "noShortcut": 0, 877 | "noUnpublish": 0, 878 | "noLang": 0, 879 | "compile": 0, 880 | "nameContentTab": 0, 881 | "noCacheGetVars": "", 882 | "noCachePostVars": "", 883 | "useCacheForUsers": 0, 884 | "cacheExpire": 0, 885 | "cacheExpirePages": [], 886 | "cacheExpireSelector": "", 887 | "label": "", 888 | "tags": "dbMigrate", 889 | "titleNames": 0, 890 | "noPrependTemplateFile": 0, 891 | "noAppendTemplateFile": 0, 892 | "prependFile": "", 893 | "appendFile": "", 894 | "pagefileSecure": 0, 895 | "tabContent": "", 896 | "tabChildren": "", 897 | "nameLabel": "", 898 | "contentType": "", 899 | "errorAction": 0, 900 | "connectedFieldID": null, 901 | "ns": "", 902 | "fieldgroupFields": [ 903 | "title", 904 | "dbMigrateRuntimeControl", 905 | "dbMigrateRuntimeAction", 906 | "dbMigrateLogChanges", 907 | "dbMigrateTrackingScope", 908 | "dbMigrateFieldTracking", 909 | "dbMigrateTemplateTracking", 910 | "dbMigratePageTracking", 911 | "dbMigrateTrackingScope_END", 912 | "dbMigrateSummary", 913 | "dbMigrateAdditionalDetails", 914 | "dbMigrateItem", 915 | "dbMigrateRestrictFields", 916 | "dbMigrateSnippets", 917 | "dbMigrateRuntimeReady" 918 | ], 919 | "fieldgroupContexts": { 920 | "title": { 921 | "columnWidth": 50 922 | }, 923 | "dbMigrateRuntimeControl": { 924 | "columnWidth": 50 925 | }, 926 | "dbMigrateRuntimeAction": { 927 | "columnWidth": 50 928 | }, 929 | "dbMigrateLogChanges": { 930 | "columnWidth": 50 931 | }, 932 | "dbMigrateTrackingScope": { 933 | "showIf": "dbMigrateLogChanges=1" 934 | }, 935 | "dbMigrateFieldTracking": { 936 | "columnWidth": 33 937 | }, 938 | "dbMigrateTemplateTracking": { 939 | "columnWidth": 33 940 | }, 941 | "dbMigratePageTracking": { 942 | "columnWidth": 34 943 | }, 944 | "dbMigrateTrackingScope_END": [], 945 | "dbMigrateSummary": { 946 | "columnWidth": 50 947 | }, 948 | "dbMigrateAdditionalDetails": { 949 | "columnWidth": 50 950 | }, 951 | "dbMigrateItem": [], 952 | "dbMigrateRestrictFields": [], 953 | "dbMigrateSnippets": [], 954 | "dbMigrateRuntimeReady": { 955 | "collapsed": "1" 956 | } 957 | } 958 | } 959 | } 960 | } 961 | }, 962 | { 963 | "templates": { 964 | "new": { 965 | "DbComparison": { 966 | "name": "DbComparison", 967 | "fieldgroups_id": "DbComparison", 968 | "flags": 8, 969 | "cache_time": 0, 970 | "useRoles": 0, 971 | "noInherit": 0, 972 | "childrenTemplatesID": 0, 973 | "sortfield": "", 974 | "noChildren": "", 975 | "noParents": "", 976 | "childTemplates": [], 977 | "parentTemplates": [], 978 | "allowPageNum": 0, 979 | "allowChangeUser": 0, 980 | "redirectLogin": 0, 981 | "urlSegments": 0, 982 | "https": 0, 983 | "slashUrls": 1, 984 | "slashPageNum": 0, 985 | "slashUrlSegments": 0, 986 | "altFilename": "", 987 | "guestSearchable": 0, 988 | "pageClass": "ProcessWire\\DbComparisonPage", 989 | "childNameFormat": "", 990 | "pageLabelField": "", 991 | "noGlobal": 0, 992 | "noMove": 0, 993 | "noTrash": 0, 994 | "noSettings": 0, 995 | "noChangeTemplate": 0, 996 | "noShortcut": 0, 997 | "noUnpublish": 0, 998 | "noLang": 0, 999 | "compile": 3, 1000 | "nameContentTab": 0, 1001 | "noCacheGetVars": "", 1002 | "noCachePostVars": "", 1003 | "useCacheForUsers": 0, 1004 | "cacheExpire": 0, 1005 | "cacheExpirePages": [], 1006 | "cacheExpireSelector": "", 1007 | "label": "", 1008 | "tags": "dbMigrate", 1009 | "titleNames": 0, 1010 | "noPrependTemplateFile": 0, 1011 | "noAppendTemplateFile": 0, 1012 | "prependFile": "", 1013 | "appendFile": "", 1014 | "pagefileSecure": 0, 1015 | "tabContent": "", 1016 | "tabChildren": "", 1017 | "nameLabel": "", 1018 | "contentType": "", 1019 | "errorAction": 0, 1020 | "connectedFieldID": null, 1021 | "ns": "", 1022 | "fieldgroupFields": [ 1023 | "title", 1024 | "dbMigrateRuntimeAction", 1025 | "dbMigrateSummary", 1026 | "dbMigrateComparisonItem" 1027 | ], 1028 | "fieldgroupContexts": { 1029 | "title": [], 1030 | "dbMigrateRuntimeAction": [], 1031 | "dbMigrateSummary": [], 1032 | "dbMigrateComparisonItem": [] 1033 | } 1034 | } 1035 | } 1036 | } 1037 | }, 1038 | { 1039 | "templates": { 1040 | "new": { 1041 | "DbMigrations": { 1042 | "name": "DbMigrations", 1043 | "fieldgroups_id": "DbMigrations", 1044 | "flags": 8, 1045 | "cache_time": 0, 1046 | "useRoles": 0, 1047 | "noInherit": 0, 1048 | "childrenTemplatesID": 0, 1049 | "sortfield": "", 1050 | "noChildren": "", 1051 | "noParents": "", 1052 | "childTemplates": [ 1053 | "DbMigration", 1054 | "DbComparison" 1055 | ], 1056 | "parentTemplates": [], 1057 | "allowPageNum": 0, 1058 | "allowChangeUser": 0, 1059 | "redirectLogin": 0, 1060 | "urlSegments": 0, 1061 | "https": 0, 1062 | "slashUrls": 1, 1063 | "slashPageNum": 0, 1064 | "slashUrlSegments": 0, 1065 | "altFilename": "", 1066 | "guestSearchable": 0, 1067 | "pageClass": "", 1068 | "childNameFormat": "", 1069 | "pageLabelField": "", 1070 | "noGlobal": 0, 1071 | "noMove": 1, 1072 | "noTrash": 0, 1073 | "noSettings": 0, 1074 | "noChangeTemplate": 1, 1075 | "noShortcut": 0, 1076 | "noUnpublish": 0, 1077 | "noLang": 0, 1078 | "compile": 3, 1079 | "nameContentTab": 0, 1080 | "noCacheGetVars": "", 1081 | "noCachePostVars": "", 1082 | "useCacheForUsers": 0, 1083 | "cacheExpire": 0, 1084 | "cacheExpirePages": [], 1085 | "cacheExpireSelector": "", 1086 | "label": "", 1087 | "tags": "dbMigrate", 1088 | "titleNames": 0, 1089 | "noPrependTemplateFile": 0, 1090 | "noAppendTemplateFile": 0, 1091 | "prependFile": "", 1092 | "appendFile": "", 1093 | "pagefileSecure": 0, 1094 | "tabContent": "", 1095 | "tabChildren": "", 1096 | "nameLabel": "", 1097 | "contentType": "", 1098 | "errorAction": 0, 1099 | "connectedFieldID": null, 1100 | "ns": "", 1101 | "fieldgroupFields": [ 1102 | "title" 1103 | ], 1104 | "fieldgroupContexts": { 1105 | "title": [] 1106 | } 1107 | } 1108 | } 1109 | } 1110 | }, 1111 | { 1112 | "pages": { 1113 | "new": { 1114 | "/processwire/dbmigrations/": { 1115 | "template": "DbMigrations", 1116 | "parent": "/processwire/", 1117 | "status": 1025, 1118 | "name": "dbmigrations", 1119 | "id": 1353, 1120 | "title": "DB Migrations" 1121 | } 1122 | } 1123 | } 1124 | }, 1125 | { 1126 | "pages": { 1127 | "new": { 1128 | "/processwire/dbcomparisons/": { 1129 | "template": "DbMigrations", 1130 | "parent": "/processwire/", 1131 | "status": 1025, 1132 | "name": "dbcomparisons", 1133 | "id": 1354, 1134 | "title": "DB Comparisons" 1135 | } 1136 | } 1137 | } 1138 | } 1139 | ] -------------------------------------------------------------------------------- /bootstrap/new/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "new": { 5 | "dbMigrateType": { 6 | "name": "dbMigrateType", 7 | "label": "Object type", 8 | "flags": 8, 9 | "type": "FieldtypeOptions", 10 | "inputfieldClass": "InputfieldSelect", 11 | "export_options": { 12 | "default": "1=fields|Field\n2=templates|Template\n3=pages|Page" 13 | }, 14 | "tags": "dbMigrate", 15 | "initValue": "", 16 | "collapsed": 0, 17 | "showIf": "", 18 | "themeInputSize": "", 19 | "themeInputWidth": "", 20 | "themeOffset": "", 21 | "themeBorder": "", 22 | "themeColor": "", 23 | "columnWidth": "", 24 | "required": "", 25 | "requiredIf": "", 26 | "defaultValue": "" 27 | } 28 | } 29 | } 30 | }, 31 | { 32 | "fields": { 33 | "new": { 34 | "dbMigrateAction": { 35 | "name": "dbMigrateAction", 36 | "label": "Action", 37 | "flags": 8, 38 | "type": "FieldtypeOptions", 39 | "inputfieldClass": "InputfieldSelect", 40 | "export_options": { 41 | "default": "1=new|New\n2=changed|Changed\n3=removed|Removed" 42 | }, 43 | "tags": "dbMigrate", 44 | "initValue": "", 45 | "collapsed": 0, 46 | "showIf": "", 47 | "themeInputSize": "", 48 | "themeInputWidth": "", 49 | "themeOffset": "", 50 | "themeBorder": "", 51 | "themeColor": "", 52 | "columnWidth": "", 53 | "required": "", 54 | "requiredIf": "", 55 | "defaultValue": "" 56 | } 57 | } 58 | } 59 | }, 60 | { 61 | "fields": { 62 | "new": { 63 | "dbMigrateName": { 64 | "name": "dbMigrateName", 65 | "label": "Name (path for pages) or selector", 66 | "flags": 8, 67 | "type": "FieldtypeText", 68 | "maxlength": 2048, 69 | "tags": "dbMigrate", 70 | "textformatters": [ 71 | "TextformatterEntities" 72 | ], 73 | "inputfieldClass": "", 74 | "collapsed": 0, 75 | "showIf": "", 76 | "themeInputSize": "", 77 | "themeInputWidth": "", 78 | "themeOffset": "", 79 | "themeBorder": "", 80 | "themeColor": "", 81 | "themeBlank": "", 82 | "columnWidth": "", 83 | "required": "", 84 | "requiredAttr": "", 85 | "requiredIf": "", 86 | "minlength": 0, 87 | "showCount": 0, 88 | "size": 0, 89 | "stripTags": "", 90 | "placeholder": "", 91 | "pattern": "" 92 | } 93 | } 94 | } 95 | }, 96 | { 97 | "fields": { 98 | "new": { 99 | "dbMigrateOldName": { 100 | "name": "dbMigrateOldName", 101 | "label": "Old name if different (n/a for selectors)", 102 | "flags": 8, 103 | "type": "FieldtypeText", 104 | "maxlength": 2048, 105 | "tags": "dbMigrate", 106 | "textformatters": [ 107 | "TextformatterEntities" 108 | ], 109 | "inputfieldClass": "", 110 | "collapsed": 0, 111 | "showIf": "", 112 | "themeInputSize": "", 113 | "themeInputWidth": "", 114 | "themeOffset": "", 115 | "themeBorder": "", 116 | "themeColor": "", 117 | "themeBlank": "", 118 | "columnWidth": "", 119 | "required": "", 120 | "requiredAttr": "", 121 | "requiredIf": "", 122 | "minlength": 0, 123 | "showCount": 0, 124 | "size": 0, 125 | "stripTags": "", 126 | "placeholder": "", 127 | "pattern": "" 128 | } 129 | } 130 | } 131 | }, 132 | { 133 | "templates": { 134 | "new": { 135 | "repeater_dbMigrateItem": { 136 | "name": "repeater_dbMigrateItem", 137 | "fieldgroups_id": "repeater_dbMigrateItem", 138 | "flags": 8, 139 | "cache_time": 0, 140 | "useRoles": 0, 141 | "noInherit": 0, 142 | "childrenTemplatesID": 0, 143 | "sortfield": "", 144 | "noChildren": 1, 145 | "noParents": 1, 146 | "childTemplates": [], 147 | "parentTemplates": [], 148 | "allowPageNum": 0, 149 | "allowChangeUser": 0, 150 | "redirectLogin": 0, 151 | "urlSegments": 0, 152 | "https": 0, 153 | "slashUrls": 1, 154 | "slashPageNum": 0, 155 | "slashUrlSegments": 0, 156 | "altFilename": "", 157 | "guestSearchable": 0, 158 | "pageClass": "RepeaterPage", 159 | "childNameFormat": "", 160 | "pageLabelField": "", 161 | "noGlobal": 1, 162 | "noMove": 0, 163 | "noTrash": 0, 164 | "noSettings": 0, 165 | "noChangeTemplate": 0, 166 | "noShortcut": 0, 167 | "noUnpublish": 0, 168 | "noLang": 0, 169 | "compile": 3, 170 | "nameContentTab": 0, 171 | "noCacheGetVars": "", 172 | "noCachePostVars": "", 173 | "useCacheForUsers": 0, 174 | "cacheExpire": 0, 175 | "cacheExpirePages": [], 176 | "cacheExpireSelector": "", 177 | "label": "", 178 | "tags": "dbMigrate", 179 | "titleNames": 0, 180 | "noPrependTemplateFile": 0, 181 | "noAppendTemplateFile": 0, 182 | "prependFile": "", 183 | "appendFile": "", 184 | "pagefileSecure": 0, 185 | "tabContent": "", 186 | "tabChildren": "", 187 | "nameLabel": "", 188 | "contentType": "", 189 | "errorAction": 0, 190 | "connectedFieldID": null, 191 | "ns": "", 192 | "fieldgroupFields": [ 193 | "dbMigrateType", 194 | "dbMigrateAction", 195 | "dbMigrateName", 196 | "dbMigrateOldName" 197 | ], 198 | "fieldgroupContexts": { 199 | "dbMigrateType": { 200 | "columnWidth": 10 201 | }, 202 | "dbMigrateAction": { 203 | "columnWidth": 10 204 | }, 205 | "dbMigrateName": { 206 | "columnWidth": 55 207 | }, 208 | "dbMigrateOldName": { 209 | "columnWidth": 25 210 | } 211 | } 212 | } 213 | } 214 | } 215 | }, 216 | { 217 | "fields": { 218 | "new": { 219 | "dbMigrateItem": { 220 | "name": "dbMigrateItem", 221 | "label": "Migration item", 222 | "flags": 8, 223 | "type": "FieldtypeRepeater", 224 | "repeaterLoading": 1, 225 | "repeaterTitle": "#n: {dbMigrateAction} {dbMigrateType}: {dbMigrateName}", 226 | "tags": "dbMigrate", 227 | "notes": "Migration items are colour-coded by object type (green fields, brown templates and blue pages).\n'Magic wand' icons indicate 'magic' items that have been added automatically by 'log changes'.\n'Down-arrow' icons indicate magic items that are dependent on other items (where known).\nNote that (with automatic sorting) dependent items will appear later if a 'new' item or earlier if 'removed'.\nNon-magic 'removed' items will need to be sorted manually as the system has no data for them.", 228 | "familyFriendly": 0, 229 | "repeaterCollapse": 0, 230 | "rememberOpen": 0, 231 | "accordionMode": 0, 232 | "loudControls": 0, 233 | "repeaterDepth": "", 234 | "repeaterAddLabel": "", 235 | "repeaterMaxItems": "", 236 | "repeaterMinItems": "", 237 | "lazyParents": "", 238 | "collapsed": 0, 239 | "showIf": "", 240 | "themeOffset": "", 241 | "themeBorder": "", 242 | "themeColor": "", 243 | "columnWidth": "", 244 | "required": "", 245 | "requiredIf": "", 246 | "template_name": "repeater_dbMigrateItem" 247 | } 248 | } 249 | } 250 | }, 251 | { 252 | "templates": { 253 | "new": { 254 | "repeater_dbMigrateComparisonItem": { 255 | "name": "repeater_dbMigrateComparisonItem", 256 | "fieldgroups_id": "repeater_dbMigrateComparisonItem", 257 | "flags": 8, 258 | "cache_time": 0, 259 | "useRoles": 0, 260 | "noInherit": 0, 261 | "childrenTemplatesID": 0, 262 | "sortfield": "", 263 | "noChildren": 1, 264 | "noParents": 1, 265 | "childTemplates": [], 266 | "parentTemplates": [], 267 | "allowPageNum": 0, 268 | "allowChangeUser": 0, 269 | "redirectLogin": 0, 270 | "urlSegments": 0, 271 | "https": 0, 272 | "slashUrls": 1, 273 | "slashPageNum": 0, 274 | "slashUrlSegments": 0, 275 | "altFilename": "", 276 | "guestSearchable": 0, 277 | "pageClass": "RepeaterPage", 278 | "childNameFormat": "", 279 | "pageLabelField": "", 280 | "noGlobal": 1, 281 | "noMove": 0, 282 | "noTrash": 0, 283 | "noSettings": 0, 284 | "noChangeTemplate": 0, 285 | "noShortcut": 0, 286 | "noUnpublish": 0, 287 | "noLang": 0, 288 | "compile": 3, 289 | "nameContentTab": 0, 290 | "noCacheGetVars": "", 291 | "noCachePostVars": "", 292 | "useCacheForUsers": 0, 293 | "cacheExpire": 0, 294 | "cacheExpirePages": [], 295 | "cacheExpireSelector": "", 296 | "label": "", 297 | "tags": "dbMigrate", 298 | "titleNames": 0, 299 | "noPrependTemplateFile": 0, 300 | "noAppendTemplateFile": 0, 301 | "prependFile": "", 302 | "appendFile": "", 303 | "pagefileSecure": 0, 304 | "tabContent": "", 305 | "tabChildren": "", 306 | "nameLabel": "", 307 | "contentType": "", 308 | "errorAction": 0, 309 | "connectedFieldID": null, 310 | "ns": "", 311 | "fieldgroupFields": [ 312 | "dbMigrateType", 313 | "dbMigrateName" 314 | ], 315 | "fieldgroupContexts": { 316 | "dbMigrateType": [], 317 | "dbMigrateName": [] 318 | } 319 | } 320 | } 321 | } 322 | }, 323 | { 324 | "fields": { 325 | "new": { 326 | "dbMigrateComparisonItem": { 327 | "name": "dbMigrateComparisonItem", 328 | "label": "Comparison item", 329 | "flags": 8, 330 | "type": "FieldtypeRepeater", 331 | "repeaterLoading": 1, 332 | "repeaterTitle": "#1: {dbMigrateType} - {dbMigrateName}", 333 | "tags": "dbMigrate", 334 | "repeaterDepth": "", 335 | "familyFriendly": 0, 336 | "repeaterAddLabel": "", 337 | "repeaterCollapse": 0, 338 | "rememberOpen": 0, 339 | "accordionMode": 0, 340 | "loudControls": 0, 341 | "repeaterMaxItems": "", 342 | "repeaterMinItems": "", 343 | "lazyParents": "", 344 | "collapsed": 0, 345 | "showIf": "", 346 | "themeOffset": "", 347 | "themeBorder": "", 348 | "themeColor": "", 349 | "columnWidth": "", 350 | "required": "", 351 | "requiredIf": "", 352 | "template_name": "repeater_dbMigrateComparisonItem" 353 | } 354 | } 355 | } 356 | }, 357 | { 358 | "fields": { 359 | "new": { 360 | "dbMigrateSummary": { 361 | "name": "dbMigrateSummary", 362 | "label": "Summary", 363 | "flags": 8, 364 | "type": "FieldtypeTextarea", 365 | "textformatters": [ 366 | "TextformatterEntities" 367 | ], 368 | "inputfieldClass": "InputfieldTextarea", 369 | "rows": 5, 370 | "tags": "dbMigrate", 371 | "contentType": 0, 372 | "htmlOptions": "", 373 | "collapsed": 0, 374 | "showIf": "", 375 | "themeInputSize": "", 376 | "themeOffset": "", 377 | "themeBorder": "", 378 | "themeColor": "", 379 | "themeBlank": "", 380 | "columnWidth": "", 381 | "required": "", 382 | "requiredAttr": "", 383 | "requiredIf": "", 384 | "minlength": 0, 385 | "maxlength": 0, 386 | "showCount": 0, 387 | "stripTags": "", 388 | "placeholder": "" 389 | } 390 | } 391 | } 392 | }, 393 | { 394 | "fields": { 395 | "new": { 396 | "dbMigrateAdditionalDetails": { 397 | "name": "dbMigrateAdditionalDetails", 398 | "label": "Additional details", 399 | "flags": 8, 400 | "type": "FieldtypeTextarea", 401 | "inputfieldClass": "InputfieldCKEditor", 402 | "contentType": 1, 403 | "rows": 8, 404 | "toolbar": "Format, Styles, -, Bold, Italic, -, RemoveFormat\nNumberedList, BulletedList, -, Blockquote\nPWLink, Unlink, Anchor\nPWImage, Table, HorizontalRule, SpecialChar\nPasteText, PasteFromWord\nTextColor, BGColor\nScayt, -, Sourcedialog", 405 | "useACF": 1, 406 | "usePurifier": 1, 407 | "toggles": [ 408 | 2, 409 | 4, 410 | 8 411 | ], 412 | "formatTags": "p;h1;h2;h3;h4;h5;h6;pre;address", 413 | "extraPlugins": [ 414 | "colorbutton", 415 | "pwimage", 416 | "pwlink", 417 | "sourcedialog" 418 | ], 419 | "removePlugins": "image,magicline", 420 | "extraAllowedContent": "br\ntd(box-top,box-middle,box-bottom,box-total)\ntable(uk-table)\ndiv(uk-overflow-auto)\nth(uk-table-shrink)\ntd(uk-table-shrink)\nblockquote(clearfix)\nimg[alt,!src,width,height]", 421 | "tags": "dbMigrate", 422 | "textformatters": "", 423 | "htmlOptions": "", 424 | "collapsed": 0, 425 | "showIf": "", 426 | "themeOffset": "", 427 | "themeBorder": "", 428 | "themeColor": "", 429 | "columnWidth": "", 430 | "required": "", 431 | "requiredAttr": "", 432 | "requiredIf": "", 433 | "minlength": 0, 434 | "maxlength": 0, 435 | "showCount": 0, 436 | "inheritField": "", 437 | "inlineMode": 0, 438 | "imageFields": "", 439 | "contentsCss": "", 440 | "contentsInlineCss": "", 441 | "stylesSet": "", 442 | "customOptions": "", 443 | "plugin_sourcedialog": "" 444 | } 445 | } 446 | } 447 | }, 448 | { 449 | "fields": { 450 | "new": { 451 | "dbMigrateRestrictFields": { 452 | "name": "dbMigrateRestrictFields", 453 | "label": "Restrict fields", 454 | "flags": 8, 455 | "type": "FieldtypeTextarea", 456 | "description": "Enter list of field names (comma-separated) that will be migrated for selected pages (leave blank to migrate all except globally excluded fields)", 457 | "notes": "This only affects this migration. To exclude specific fields or field types from all page migrations, use the module config settings.", 458 | "textformatters": [ 459 | "TextformatterEntities" 460 | ], 461 | "inputfieldClass": "InputfieldTextarea", 462 | "rows": 5, 463 | "tags": "dbMigrate", 464 | "contentType": 0, 465 | "htmlOptions": "", 466 | "collapsed": 0, 467 | "showIf": "", 468 | "themeInputSize": "", 469 | "themeOffset": "", 470 | "themeBorder": "", 471 | "themeColor": "", 472 | "themeBlank": "", 473 | "columnWidth": "", 474 | "required": "", 475 | "requiredAttr": "", 476 | "requiredIf": "", 477 | "minlength": 0, 478 | "maxlength": 0, 479 | "showCount": 0, 480 | "stripTags": "", 481 | "placeholder": "" 482 | } 483 | } 484 | } 485 | }, 486 | { 487 | "templates": { 488 | "new": { 489 | "repeater_dbMigrateSnippets": { 490 | "name": "repeater_dbMigrateSnippets", 491 | "fieldgroups_id": "repeater_dbMigrateSnippets", 492 | "flags": 8, 493 | "cache_time": 0, 494 | "useRoles": 0, 495 | "noInherit": 0, 496 | "childrenTemplatesID": 0, 497 | "sortfield": "", 498 | "noChildren": 1, 499 | "noParents": 1, 500 | "childTemplates": [], 501 | "parentTemplates": [], 502 | "allowPageNum": 0, 503 | "allowChangeUser": 0, 504 | "redirectLogin": 0, 505 | "urlSegments": 0, 506 | "https": 0, 507 | "slashUrls": 1, 508 | "slashPageNum": 0, 509 | "slashUrlSegments": 0, 510 | "altFilename": "", 511 | "guestSearchable": 0, 512 | "pageClass": "RepeaterPage", 513 | "childNameFormat": "", 514 | "pageLabelField": "", 515 | "noGlobal": 1, 516 | "noMove": 0, 517 | "noTrash": 0, 518 | "noSettings": 0, 519 | "noChangeTemplate": 0, 520 | "noShortcut": 0, 521 | "noUnpublish": 0, 522 | "noLang": 0, 523 | "compile": 3, 524 | "nameContentTab": 0, 525 | "noCacheGetVars": "", 526 | "noCachePostVars": "", 527 | "useCacheForUsers": 0, 528 | "cacheExpire": 0, 529 | "cacheExpirePages": [], 530 | "cacheExpireSelector": "", 531 | "label": "", 532 | "tags": "dbMigrate", 533 | "titleNames": 0, 534 | "noPrependTemplateFile": 0, 535 | "noAppendTemplateFile": 0, 536 | "prependFile": "", 537 | "appendFile": "", 538 | "pagefileSecure": 0, 539 | "tabContent": "", 540 | "tabChildren": "", 541 | "nameLabel": "", 542 | "contentType": "", 543 | "errorAction": 0, 544 | "connectedFieldID": null, 545 | "ns": "", 546 | "fieldgroupFields": [ 547 | "title", 548 | "dbMigrateSummary" 549 | ], 550 | "fieldgroupContexts": { 551 | "title": { 552 | "label": "Description" 553 | }, 554 | "dbMigrateSummary": { 555 | "label": "Snippet" 556 | } 557 | } 558 | } 559 | } 560 | } 561 | }, 562 | { 563 | "fields": { 564 | "new": { 565 | "dbMigrateSnippets": { 566 | "name": "dbMigrateSnippets", 567 | "label": "Snippets", 568 | "flags": 8, 569 | "type": "FieldtypeRepeater", 570 | "repeaterLoading": 1, 571 | "repeaterTitle": "#n: {title}", 572 | "tags": "dbMigrate", 573 | "repeaterDepth": "", 574 | "familyFriendly": 0, 575 | "repeaterAddLabel": "", 576 | "repeaterCollapse": 0, 577 | "rememberOpen": 0, 578 | "accordionMode": 0, 579 | "loudControls": 0, 580 | "repeaterMaxItems": "", 581 | "repeaterMinItems": "", 582 | "lazyParents": "", 583 | "collapsed": 0, 584 | "showIf": "", 585 | "themeOffset": "", 586 | "themeBorder": "", 587 | "themeColor": "", 588 | "columnWidth": "", 589 | "required": "", 590 | "requiredIf": "", 591 | "template_name": "repeater_dbMigrateSnippets" 592 | } 593 | } 594 | } 595 | }, 596 | { 597 | "fields": { 598 | "new": { 599 | "dbMigrateRuntimeControl": { 600 | "name": "dbMigrateRuntimeControl", 601 | "label": "Page Status", 602 | "flags": 8, 603 | "type": "FieldtypeDbMigrateRuntime", 604 | "tags": "dbMigrate", 605 | "collapsed": 0, 606 | "showIf": "", 607 | "themeOffset": "", 608 | "themeBorder": "", 609 | "themeColor": "", 610 | "columnWidth": "", 611 | "required": "", 612 | "requiredIf": "" 613 | } 614 | } 615 | } 616 | }, 617 | { 618 | "fields": { 619 | "new": { 620 | "dbMigrateRuntimeAction": { 621 | "name": "dbMigrateRuntimeAction", 622 | "label": "Migration Actions", 623 | "flags": 8, 624 | "type": "FieldtypeDbMigrateRuntime", 625 | "tags": "dbMigrate", 626 | "collapsed": 0, 627 | "showIf": "", 628 | "themeOffset": "", 629 | "themeBorder": "", 630 | "themeColor": "", 631 | "columnWidth": "", 632 | "required": "", 633 | "requiredIf": "" 634 | } 635 | } 636 | } 637 | }, 638 | { 639 | "fields": { 640 | "new": { 641 | "dbMigrateRuntimeReady": { 642 | "name": "dbMigrateRuntimeReady", 643 | "label": "ready.php", 644 | "flags": 8, 645 | "type": "FieldtypeDbMigrateRuntime", 646 | "description": "Contents of site/templates/DbMigrate/migrations/{migration name}/ready.php", 647 | "notes": "This migration-specific ready.php file is for hooks after install etc.", 648 | "tags": "dbMigrate", 649 | "collapsed": 0, 650 | "showIf": "", 651 | "themeOffset": "", 652 | "themeBorder": "", 653 | "themeColor": "", 654 | "columnWidth": "", 655 | "required": "", 656 | "requiredIf": "" 657 | } 658 | } 659 | } 660 | }, 661 | { 662 | "fields": { 663 | "new": { 664 | "dbMigrateLogChanges": { 665 | "name": "dbMigrateLogChanges", 666 | "label": "Log changes", 667 | "flags": 8, 668 | "type": "FieldtypeToggle", 669 | "description": "If *log changes* is selected, any changes to fields, templates or pages which are **within the scope of the selectors set in the module configuration** will be added to the migration items list.", 670 | "formatType": 0, 671 | "labelType": 100, 672 | "inputfieldClass": 0, 673 | "useVertical": 0, 674 | "yesLabel": "Log changes", 675 | "noLabel": "Sort items on save", 676 | "otherLabel": "Manual", 677 | "defaultOption": "other", 678 | "useOther": 1, 679 | "notes": "Alternatively, you can turn change logging off and either have the module sort your items into dependency order or only allow manual changes to the items and sort order.", 680 | "tags": "dbMigrate", 681 | "useReverse": "", 682 | "useDeselect": "", 683 | "collapsed": 0, 684 | "showIf": "", 685 | "themeOffset": "", 686 | "themeBorder": "", 687 | "themeColor": "", 688 | "columnWidth": "", 689 | "required": "", 690 | "requiredIf": "" 691 | } 692 | } 693 | } 694 | }, 695 | { 696 | "fields": { 697 | "new": { 698 | "dbMigrateTrackingScope": { 699 | "name": "dbMigrateTrackingScope", 700 | "label": "Scope of change tracking", 701 | "flags": 8, 702 | "type": "FieldtypeFieldsetOpen", 703 | "description": "Use selectors to define scope of object changes to be tracked", 704 | "notes": "If you do not enter a selector then no changes will be tracked. Enter id>0 to (potentially) track everything.", 705 | "closeFieldID": 142, 706 | "tags": "dbMigrate", 707 | "collapsed": 0, 708 | "showIf": "", 709 | "columnWidth": "" 710 | } 711 | } 712 | } 713 | }, 714 | { 715 | "fields": { 716 | "new": { 717 | "dbMigrateFieldTracking": { 718 | "name": "dbMigrateFieldTracking", 719 | "label": "Fields to track", 720 | "flags": 8, 721 | "type": "FieldtypeText", 722 | "description": "Use selector to specify fields to track", 723 | "notes": "Note that any excluded fields and dbMigrate fields will not be tracked", 724 | "textformatters": [ 725 | "TextformatterEntities" 726 | ], 727 | "tags": "dbMigrate", 728 | "collapsed": 0, 729 | "minlength": 0, 730 | "maxlength": 2048, 731 | "showCount": 0, 732 | "size": 0, 733 | "placeholder": "e.g. id>0 to select all fields", 734 | "inputfieldClass": "", 735 | "showIf": "", 736 | "themeInputSize": "", 737 | "themeInputWidth": "", 738 | "themeOffset": "", 739 | "themeBorder": "", 740 | "themeColor": "", 741 | "themeBlank": "", 742 | "columnWidth": "", 743 | "required": "", 744 | "requiredAttr": "", 745 | "requiredIf": "", 746 | "stripTags": "", 747 | "pattern": "" 748 | } 749 | } 750 | } 751 | }, 752 | { 753 | "fields": { 754 | "new": { 755 | "dbMigrateTemplateTracking": { 756 | "name": "dbMigrateTemplateTracking", 757 | "label": "Templates to track", 758 | "flags": 8, 759 | "type": "FieldtypeText", 760 | "description": "Use selector to specify templates to track", 761 | "textformatters": [ 762 | "TextformatterEntities" 763 | ], 764 | "tags": "dbMigrate", 765 | "collapsed": 0, 766 | "minlength": 0, 767 | "maxlength": 2048, 768 | "showCount": 0, 769 | "size": 0, 770 | "placeholder": "e.g. id>0 to select all templates", 771 | "inputfieldClass": "", 772 | "showIf": "", 773 | "themeInputSize": "", 774 | "themeInputWidth": "", 775 | "themeOffset": "", 776 | "themeBorder": "", 777 | "themeColor": "", 778 | "themeBlank": "", 779 | "columnWidth": "", 780 | "required": "", 781 | "requiredAttr": "", 782 | "requiredIf": "", 783 | "stripTags": "", 784 | "pattern": "" 785 | } 786 | } 787 | } 788 | }, 789 | { 790 | "fields": { 791 | "new": { 792 | "dbMigratePageTracking": { 793 | "name": "dbMigratePageTracking", 794 | "label": "Pages to track", 795 | "flags": 8, 796 | "type": "FieldtypeText", 797 | "description": "Use selector to specify pages to track", 798 | "notes": "Typically these will be pages holding settings etc., not normal user-updated pages", 799 | "textformatters": [ 800 | "TextformatterEntities" 801 | ], 802 | "tags": "dbMigrate", 803 | "collapsed": 0, 804 | "minlength": 0, 805 | "maxlength": 4096, 806 | "showCount": 0, 807 | "size": 0, 808 | "inputfieldClass": "", 809 | "showIf": "", 810 | "themeInputSize": "", 811 | "themeInputWidth": "", 812 | "themeOffset": "", 813 | "themeBorder": "", 814 | "themeColor": "", 815 | "themeBlank": "", 816 | "columnWidth": "", 817 | "required": "", 818 | "requiredAttr": "", 819 | "requiredIf": "", 820 | "stripTags": "", 821 | "placeholder": "", 822 | "pattern": "" 823 | } 824 | } 825 | } 826 | }, 827 | { 828 | "fields": { 829 | "new": { 830 | "dbMigrateTrackingScope_END": { 831 | "name": "dbMigrateTrackingScope_END", 832 | "label": "Close an open fieldset", 833 | "flags": 8, 834 | "type": "FieldtypeFieldsetClose", 835 | "description": "This field was added automatically to accompany fieldset 'dbMigrateScope'. It should be placed in your template/fieldgroup wherever you want the fieldset to end.", 836 | "openFieldID": 141, 837 | "tags": "dbMigrate" 838 | } 839 | } 840 | } 841 | }, 842 | { 843 | "templates": { 844 | "new": { 845 | "DbMigration": { 846 | "name": "DbMigration", 847 | "fieldgroups_id": "DbMigration", 848 | "flags": 8, 849 | "cache_time": 0, 850 | "useRoles": 0, 851 | "noInherit": 0, 852 | "childrenTemplatesID": 0, 853 | "sortfield": "", 854 | "noChildren": "", 855 | "noParents": "", 856 | "childTemplates": [], 857 | "parentTemplates": [], 858 | "allowPageNum": 0, 859 | "allowChangeUser": 0, 860 | "redirectLogin": 0, 861 | "urlSegments": 0, 862 | "https": 0, 863 | "slashUrls": 1, 864 | "slashPageNum": 0, 865 | "slashUrlSegments": 0, 866 | "altFilename": "", 867 | "guestSearchable": 0, 868 | "pageClass": "ProcessWire\\DbMigrationPage", 869 | "childNameFormat": "", 870 | "pageLabelField": "", 871 | "noGlobal": 0, 872 | "noMove": 1, 873 | "noTrash": 0, 874 | "noSettings": 0, 875 | "noChangeTemplate": 1, 876 | "noShortcut": 0, 877 | "noUnpublish": 0, 878 | "noLang": 0, 879 | "compile": 0, 880 | "nameContentTab": 0, 881 | "noCacheGetVars": "", 882 | "noCachePostVars": "", 883 | "useCacheForUsers": 0, 884 | "cacheExpire": 0, 885 | "cacheExpirePages": [], 886 | "cacheExpireSelector": "", 887 | "label": "", 888 | "tags": "dbMigrate", 889 | "titleNames": 0, 890 | "noPrependTemplateFile": 0, 891 | "noAppendTemplateFile": 0, 892 | "prependFile": "", 893 | "appendFile": "", 894 | "pagefileSecure": 0, 895 | "tabContent": "", 896 | "tabChildren": "", 897 | "nameLabel": "", 898 | "contentType": "", 899 | "errorAction": 0, 900 | "connectedFieldID": null, 901 | "ns": "", 902 | "fieldgroupFields": [ 903 | "title", 904 | "dbMigrateRuntimeControl", 905 | "dbMigrateRuntimeAction", 906 | "dbMigrateLogChanges", 907 | "dbMigrateTrackingScope", 908 | "dbMigrateFieldTracking", 909 | "dbMigrateTemplateTracking", 910 | "dbMigratePageTracking", 911 | "dbMigrateTrackingScope_END", 912 | "dbMigrateSummary", 913 | "dbMigrateAdditionalDetails", 914 | "dbMigrateItem", 915 | "dbMigrateRestrictFields", 916 | "dbMigrateSnippets", 917 | "dbMigrateRuntimeReady" 918 | ], 919 | "fieldgroupContexts": { 920 | "title": { 921 | "columnWidth": 50 922 | }, 923 | "dbMigrateRuntimeControl": { 924 | "columnWidth": 50 925 | }, 926 | "dbMigrateRuntimeAction": { 927 | "columnWidth": 50 928 | }, 929 | "dbMigrateLogChanges": { 930 | "columnWidth": 50 931 | }, 932 | "dbMigrateTrackingScope": { 933 | "showIf": "dbMigrateLogChanges=1" 934 | }, 935 | "dbMigrateFieldTracking": { 936 | "columnWidth": 33 937 | }, 938 | "dbMigrateTemplateTracking": { 939 | "columnWidth": 33 940 | }, 941 | "dbMigratePageTracking": { 942 | "columnWidth": 34 943 | }, 944 | "dbMigrateTrackingScope_END": [], 945 | "dbMigrateSummary": { 946 | "columnWidth": 50 947 | }, 948 | "dbMigrateAdditionalDetails": { 949 | "columnWidth": 50 950 | }, 951 | "dbMigrateItem": [], 952 | "dbMigrateRestrictFields": [], 953 | "dbMigrateSnippets": [], 954 | "dbMigrateRuntimeReady": { 955 | "collapsed": "1" 956 | } 957 | } 958 | } 959 | } 960 | } 961 | }, 962 | { 963 | "templates": { 964 | "new": { 965 | "DbComparison": { 966 | "name": "DbComparison", 967 | "fieldgroups_id": "DbComparison", 968 | "flags": 8, 969 | "cache_time": 0, 970 | "useRoles": 0, 971 | "noInherit": 0, 972 | "childrenTemplatesID": 0, 973 | "sortfield": "", 974 | "noChildren": "", 975 | "noParents": "", 976 | "childTemplates": [], 977 | "parentTemplates": [], 978 | "allowPageNum": 0, 979 | "allowChangeUser": 0, 980 | "redirectLogin": 0, 981 | "urlSegments": 0, 982 | "https": 0, 983 | "slashUrls": 1, 984 | "slashPageNum": 0, 985 | "slashUrlSegments": 0, 986 | "altFilename": "", 987 | "guestSearchable": 0, 988 | "pageClass": "ProcessWire\\DbComparisonPage", 989 | "childNameFormat": "", 990 | "pageLabelField": "", 991 | "noGlobal": 0, 992 | "noMove": 0, 993 | "noTrash": 0, 994 | "noSettings": 0, 995 | "noChangeTemplate": 0, 996 | "noShortcut": 0, 997 | "noUnpublish": 0, 998 | "noLang": 0, 999 | "compile": 3, 1000 | "nameContentTab": 0, 1001 | "noCacheGetVars": "", 1002 | "noCachePostVars": "", 1003 | "useCacheForUsers": 0, 1004 | "cacheExpire": 0, 1005 | "cacheExpirePages": [], 1006 | "cacheExpireSelector": "", 1007 | "label": "", 1008 | "tags": "dbMigrate", 1009 | "titleNames": 0, 1010 | "noPrependTemplateFile": 0, 1011 | "noAppendTemplateFile": 0, 1012 | "prependFile": "", 1013 | "appendFile": "", 1014 | "pagefileSecure": 0, 1015 | "tabContent": "", 1016 | "tabChildren": "", 1017 | "nameLabel": "", 1018 | "contentType": "", 1019 | "errorAction": 0, 1020 | "connectedFieldID": null, 1021 | "ns": "", 1022 | "fieldgroupFields": [ 1023 | "title", 1024 | "dbMigrateRuntimeAction", 1025 | "dbMigrateSummary", 1026 | "dbMigrateComparisonItem" 1027 | ], 1028 | "fieldgroupContexts": { 1029 | "title": [], 1030 | "dbMigrateRuntimeAction": [], 1031 | "dbMigrateSummary": [], 1032 | "dbMigrateComparisonItem": [] 1033 | } 1034 | } 1035 | } 1036 | } 1037 | }, 1038 | { 1039 | "templates": { 1040 | "new": { 1041 | "DbMigrations": { 1042 | "name": "DbMigrations", 1043 | "fieldgroups_id": "DbMigrations", 1044 | "flags": 8, 1045 | "cache_time": 0, 1046 | "useRoles": 0, 1047 | "noInherit": 0, 1048 | "childrenTemplatesID": 0, 1049 | "sortfield": "", 1050 | "noChildren": "", 1051 | "noParents": "", 1052 | "childTemplates": [ 1053 | "DbMigration", 1054 | "DbComparison" 1055 | ], 1056 | "parentTemplates": [], 1057 | "allowPageNum": 0, 1058 | "allowChangeUser": 0, 1059 | "redirectLogin": 0, 1060 | "urlSegments": 0, 1061 | "https": 0, 1062 | "slashUrls": 1, 1063 | "slashPageNum": 0, 1064 | "slashUrlSegments": 0, 1065 | "altFilename": "", 1066 | "guestSearchable": 0, 1067 | "pageClass": "", 1068 | "childNameFormat": "", 1069 | "pageLabelField": "", 1070 | "noGlobal": 0, 1071 | "noMove": 1, 1072 | "noTrash": 0, 1073 | "noSettings": 0, 1074 | "noChangeTemplate": 1, 1075 | "noShortcut": 0, 1076 | "noUnpublish": 0, 1077 | "noLang": 0, 1078 | "compile": 3, 1079 | "nameContentTab": 0, 1080 | "noCacheGetVars": "", 1081 | "noCachePostVars": "", 1082 | "useCacheForUsers": 0, 1083 | "cacheExpire": 0, 1084 | "cacheExpirePages": [], 1085 | "cacheExpireSelector": "", 1086 | "label": "", 1087 | "tags": "dbMigrate", 1088 | "titleNames": 0, 1089 | "noPrependTemplateFile": 0, 1090 | "noAppendTemplateFile": 0, 1091 | "prependFile": "", 1092 | "appendFile": "", 1093 | "pagefileSecure": 0, 1094 | "tabContent": "", 1095 | "tabChildren": "", 1096 | "nameLabel": "", 1097 | "contentType": "", 1098 | "errorAction": 0, 1099 | "connectedFieldID": null, 1100 | "ns": "", 1101 | "fieldgroupFields": [ 1102 | "title" 1103 | ], 1104 | "fieldgroupContexts": { 1105 | "title": [] 1106 | } 1107 | } 1108 | } 1109 | } 1110 | }, 1111 | { 1112 | "pages": { 1113 | "new": { 1114 | "/processwire/dbmigrations/": { 1115 | "template": "DbMigrations", 1116 | "parent": "/processwire/", 1117 | "status": 1025, 1118 | "name": "dbmigrations", 1119 | "id": 1353, 1120 | "title": "DB Migrations" 1121 | } 1122 | } 1123 | } 1124 | }, 1125 | { 1126 | "pages": { 1127 | "new": { 1128 | "/processwire/dbcomparisons/": { 1129 | "template": "DbMigrations", 1130 | "parent": "/processwire/", 1131 | "status": 1025, 1132 | "name": "dbcomparisons", 1133 | "id": 1354, 1134 | "title": "DB Comparisons" 1135 | } 1136 | } 1137 | } 1138 | } 1139 | ] --------------------------------------------------------------------------------