Version Description
(14 January 2019) =
Changes:
- Implemented a new import process, which should be more reliable with large form imports.
- Upgraded our data structure to reduce loading times for forms and the form builder.
=
Download this release
Release Info
Developer | krmoorhouse |
Plugin | Ninja Forms – The Easy and Powerful Forms Builder |
Version | 3.4.0 |
Comparing to | |
See all releases |
Code changes from version 3.3.21.3 to 3.4.0
- assets/css/admin-settings.css +4 -1
- assets/css/required-updates.css +156 -0
- assets/js/admin-import-export.js +102 -0
- assets/js/admin-settings.js +55 -79
- assets/js/lib/batch-processor.js +117 -0
- assets/js/lib/ninjaModal.js +6 -0
- assets/js/min/dashboard.min.js +2 -1
- assets/js/min/dashboard.min.js.map +1 -1
- client/dashboard/main.js +17 -8
- client/dashboard/views/dashboardView.js +67 -116
- client/dashboard/views/sections/requiredUpdates.js +345 -0
- client/dashboard/views/widgets/forms/forms.js +2 -3
- client/dashboard/views/widgets/forms/newFormTemplate.js +33 -15
- deprecated/ninja-forms.php +1 -1
- includes/AJAX/Controllers/Form.php +16 -0
- includes/AJAX/Controllers/Submission.php +13 -0
- includes/AJAX/REST/BatchProcess.php +9 -17
- includes/AJAX/REST/NewFormTemplates.php +3 -3
- includes/AJAX/REST/RequiredUpdate.php +165 -0
- includes/Abstracts/BatchProcess.php +127 -1
- includes/Abstracts/Migration.php +102 -23
- includes/Abstracts/Model.php +28 -3
- includes/Abstracts/RequiredUpdate.php +224 -0
- includes/Admin/Menus/AddNew.php +13 -0
- includes/Admin/Menus/Addons.php +13 -0
- includes/Admin/Menus/Forms.php +32 -3
- includes/Admin/Menus/ImportExport.php +38 -1
- includes/Admin/Menus/Settings.php +34 -1
- includes/Admin/Menus/Submissions.php +18 -1
- includes/Admin/Menus/SystemStatus.php +2 -0
- includes/Admin/Processes/ChunkPublish.php +1 -1
- includes/Admin/Processes/DataCleanup.php +0 -131
- includes/Admin/Processes/ExpiredSubmissionCleanup.php +43 -67
- includes/Admin/Processes/ImportForm.php +856 -0
- includes/Admin/Processes/ImportFormTemplate.php +82 -0
- includes/Config/BatchProcesses.php +19 -0
- includes/Config/NewFormTemplates.php +3 -3
- includes/Config/PluginSettingsAdvanced.php +9 -0
- includes/Config/RequiredUpdates.php +31 -0
- includes/Database/FieldsController.php +253 -37
- includes/Database/Migrations.php +63 -8
- includes/Database/Migrations/ActionMeta.php +39 -1
- includes/Database/Migrations/Actions.php +38 -1
- includes/Database/Migrations/Chunks.php +1 -1
- includes/Database/Migrations/FieldMeta.php +37 -2
- includes/Database/Migrations/Fields.php +47 -1
- includes/Database/Migrations/FormMeta.php +34 -7
- includes/Database/Migrations/Forms.php +42 -23
- includes/Database/Migrations/ObjectMeta.php +33 -1
- includes/Database/Migrations/Objects.php +32 -1
- includes/Database/Migrations/Relationships.php +26 -1
- includes/Database/Migrations/Upgrades.php +32 -1
- includes/Database/Models/Action.php +21 -1
- includes/Database/Models/Form.php +172 -8
- includes/Database/Models/Object.php +21 -1
- includes/Display/Render.php +14 -0
- includes/Helper.php +153 -5
- includes/Templates/admin-menu-dashboard.html.php +33 -0
- includes/Templates/admin-metabox-import-export-forms-import.html.php +15 -29
- includes/Updates/CacheCollateActions.php +342 -0
- includes/Updates/CacheCollateCleanup.php +507 -0
- includes/Updates/CacheCollateFields.php +720 -0
- includes/Updates/CacheCollateForms.php +243 -0
- includes/Updates/CacheCollateObjects.php +298 -0
- lib/NF_Upgrade.php +1 -0
- ninja-forms.php +164 -52
- readme.txt +12 -4
assets/css/admin-settings.css
CHANGED
@@ -69,7 +69,10 @@
|
|
69 |
border-radius: 4px;
|
70 |
}
|
71 |
|
72 |
-
|
|
|
|
|
|
|
73 |
@media screen and ( max-width: 782px ) {
|
74 |
.tablenav.top .actions, .tablenav .view-switch {
|
75 |
display:block;
|
69 |
border-radius: 4px;
|
70 |
}
|
71 |
|
72 |
+
.jBox-content {
|
73 |
+
overflow: hidden !important;
|
74 |
+
}
|
75 |
+
|
76 |
@media screen and ( max-width: 782px ) {
|
77 |
.tablenav.top .actions, .tablenav .view-switch {
|
78 |
display:block;
|
assets/css/required-updates.css
ADDED
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
html,
|
2 |
+
body {
|
3 |
+
background: #fff;
|
4 |
+
}
|
5 |
+
h1 {
|
6 |
+
line-height: 32px;
|
7 |
+
}
|
8 |
+
h2 {
|
9 |
+
/*margin: 40px auto 20px;*/
|
10 |
+
}
|
11 |
+
p {
|
12 |
+
font-size: 16px;
|
13 |
+
/*padding-top: 20px;*/
|
14 |
+
}
|
15 |
+
ol {
|
16 |
+
font-size: 16px;
|
17 |
+
margin-left: 40px;
|
18 |
+
list-style-type: none;
|
19 |
+
}
|
20 |
+
hr {
|
21 |
+
margin: 50px 20px;
|
22 |
+
}
|
23 |
+
img {
|
24 |
+
width: 100%;
|
25 |
+
}
|
26 |
+
|
27 |
+
table {
|
28 |
+
width: 100%;
|
29 |
+
margin-bottom: 20px;
|
30 |
+
border-collapse: collapse;
|
31 |
+
}
|
32 |
+
|
33 |
+
tr {
|
34 |
+
height: 65px;
|
35 |
+
}
|
36 |
+
|
37 |
+
th {
|
38 |
+
text-align: left;
|
39 |
+
}
|
40 |
+
th, td {
|
41 |
+
padding: 15px;
|
42 |
+
text-align: left;
|
43 |
+
border-bottom: 1px solid #ddd;
|
44 |
+
}
|
45 |
+
|
46 |
+
th:nth-child( 1 ),
|
47 |
+
td:nth-child( 1 ) {
|
48 |
+
width: 30%;
|
49 |
+
}
|
50 |
+
th:nth-child( 2 ),
|
51 |
+
td:nth-child( 2 ) {
|
52 |
+
width: 70%;
|
53 |
+
text-align: center;
|
54 |
+
}
|
55 |
+
|
56 |
+
|
57 |
+
tbody tr:nth-child(odd) {
|
58 |
+
background-color: #f2f2f2
|
59 |
+
}
|
60 |
+
|
61 |
+
.opt-in {
|
62 |
+
text-align: center;
|
63 |
+
}
|
64 |
+
|
65 |
+
.nf-logo {
|
66 |
+
display: block;
|
67 |
+
margin: 0 auto;
|
68 |
+
max-width: 300px;
|
69 |
+
}
|
70 |
+
.nf-update {
|
71 |
+
margin: 0 auto 50px auto;
|
72 |
+
max-width: 800px;
|
73 |
+
}
|
74 |
+
|
75 |
+
/*
|
76 |
+
* Dashicons
|
77 |
+
*/
|
78 |
+
|
79 |
+
.dashicons-yes {
|
80 |
+
color: green;
|
81 |
+
}
|
82 |
+
.dashicons-no {
|
83 |
+
color: #EF4748;
|
84 |
+
}
|
85 |
+
.dashicons-flag {
|
86 |
+
color: #ffba00; /* WP Update Nag Yellow */
|
87 |
+
}
|
88 |
+
.dashicons-warning {
|
89 |
+
color: gray;
|
90 |
+
}
|
91 |
+
|
92 |
+
.dashicons-update {
|
93 |
+
margin-left: -1px;
|
94 |
+
animation: dashicons-spin 1s infinite;
|
95 |
+
animation-timing-function: linear;
|
96 |
+
}
|
97 |
+
@keyframes dashicons-spin {
|
98 |
+
0% {
|
99 |
+
transform: rotate( 0deg );
|
100 |
+
}
|
101 |
+
100% {
|
102 |
+
transform: rotate( 360deg );
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
ol .dashicons {
|
107 |
+
margin-top: 2px;
|
108 |
+
margin-right: 8px;
|
109 |
+
margin-left: -30px;
|
110 |
+
}
|
111 |
+
|
112 |
+
/*
|
113 |
+
* Progress Bar
|
114 |
+
*/
|
115 |
+
.progress-bar,
|
116 |
+
.progress-bar--wrapper {
|
117 |
+
height: 10px;
|
118 |
+
}
|
119 |
+
.progress-bar {
|
120 |
+
width: 0;
|
121 |
+
background-color: green;
|
122 |
+
}
|
123 |
+
.progress-bar--wrapper {
|
124 |
+
width: 100%;
|
125 |
+
}
|
126 |
+
|
127 |
+
/*
|
128 |
+
* Button
|
129 |
+
*/
|
130 |
+
|
131 |
+
.nf-update-button {
|
132 |
+
color: white;
|
133 |
+
background-color: #2BAAE7;
|
134 |
+
cursor: pointer;
|
135 |
+
padding: 10px 20px;
|
136 |
+
height: auto;
|
137 |
+
display: none;
|
138 |
+
margin: auto;
|
139 |
+
border: 2px solid transparent;
|
140 |
+
transition: all .5s;
|
141 |
+
position: relative;
|
142 |
+
}
|
143 |
+
.nf-update-button:hover,
|
144 |
+
.nf-update-button:active {
|
145 |
+
color: #2BAAE7;
|
146 |
+
border-color: #2BAAE7;
|
147 |
+
background-color: white;
|
148 |
+
}
|
149 |
+
|
150 |
+
#nf-upgrades-table .nf-progress-bar {
|
151 |
+
margin: 0;
|
152 |
+
}
|
153 |
+
|
154 |
+
.jBox-Modal {
|
155 |
+
max-width: 500px
|
156 |
+
}
|
assets/js/admin-import-export.js
CHANGED
@@ -1,4 +1,106 @@
|
|
1 |
jQuery( document ).ready( function( $ ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
var clickedElement;
|
4 |
|
1 |
jQuery( document ).ready( function( $ ) {
|
2 |
+
/**
|
3 |
+
* Stores the selected file details for form imports.
|
4 |
+
*
|
5 |
+
* name is the filename from the user's computer, including extension.
|
6 |
+
* content is the base64 encoded contents as a result of using the HTML5 FileReader API.
|
7 |
+
* @type {Object}
|
8 |
+
*/
|
9 |
+
var importFormFile = {
|
10 |
+
name: '',
|
11 |
+
content: ''
|
12 |
+
};
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Listen for clicks on our "import" button.
|
16 |
+
* It sets data for our batch processor and then instantiates a batch process.
|
17 |
+
*
|
18 |
+
* @since 3.4.0
|
19 |
+
* @param object e Click Event
|
20 |
+
* @return void
|
21 |
+
*/
|
22 |
+
$( document ).on( 'click', '#nf-import-form-submit', function( e ) {
|
23 |
+
// Make sure that our file field isn't empty.
|
24 |
+
if ( '' == importFormFile.name ) return false;
|
25 |
+
|
26 |
+
// Settings object for our batch processor
|
27 |
+
var settings = {
|
28 |
+
batch_type: 'import_form',
|
29 |
+
extraData: importFormFile,
|
30 |
+
loadingText: 'Importing...',
|
31 |
+
onCompleteCallback: function( response ) {
|
32 |
+
// If we don't get back a form ID, then bail.
|
33 |
+
if ( 'undefined' == typeof response.form_id ) return false;
|
34 |
+
|
35 |
+
jQuery( '#nf-import-file' ).val('');;
|
36 |
+
jQuery( '#nf-import-url' ).attr( 'href', nfAdmin.builderURL + response.form_id );
|
37 |
+
jQuery( '#row-nf-import-response' ).show();
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Instantiate our batch processor.
|
43 |
+
*
|
44 |
+
* This will open the modal and present the user with content and buttons.
|
45 |
+
*/
|
46 |
+
new NinjaBatchProcessor( settings );
|
47 |
+
} );
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Selecting a file within an input field triggers a jQuery change event.
|
51 |
+
*
|
52 |
+
* When we select a form file to import, we need to do a few things:
|
53 |
+
*
|
54 |
+
* Disable the primary button of our batch processing modal.
|
55 |
+
* Grab the file and make sure that it has a .nff extension.
|
56 |
+
* Read the contents and base64 encode them using the HTML5 FileReader API.
|
57 |
+
* Set the contents to our importFormFile variable.
|
58 |
+
*
|
59 |
+
* @since 3.4.0
|
60 |
+
* @param object e Change Event
|
61 |
+
* @return {[type]} [description]
|
62 |
+
*/
|
63 |
+
$( document ).on( 'change', '#nf-import-file', function( e ) {
|
64 |
+
// Hide our success message.
|
65 |
+
jQuery( '#row-nf-import-response' ).hide();
|
66 |
+
// Hide our extension type error.
|
67 |
+
jQuery( '#row-nf-import-type-error' ).hide();
|
68 |
+
|
69 |
+
// Grab the file from the input.
|
70 |
+
var file = e.target.files[0];
|
71 |
+
// If our file var is empty, bail.
|
72 |
+
if ( ! file ) {
|
73 |
+
return false;
|
74 |
+
}
|
75 |
+
|
76 |
+
// Use some Regex to get the extension
|
77 |
+
var extension = file.name.match(/\.[0-9a-z]+$/i);
|
78 |
+
|
79 |
+
// If we don't have a .nff extension, show our type error and bail.
|
80 |
+
if ( '.nff' !== extension[0] ) {
|
81 |
+
jQuery( '#row-nf-import-type-error' ).show();
|
82 |
+
importFormFile.name = '';
|
83 |
+
importFormFile.content = '';
|
84 |
+
return false;
|
85 |
+
}
|
86 |
+
|
87 |
+
// Instantiate the HTML5 FileReader API.
|
88 |
+
var reader = new FileReader();
|
89 |
+
|
90 |
+
/**
|
91 |
+
* When the HTML5 API says that we've successfully loaded the file contents:
|
92 |
+
* Set our importFormFile var.
|
93 |
+
* Enable our batch processor primary button.
|
94 |
+
* We use Javascript's addEventListener to update our var.
|
95 |
+
*/
|
96 |
+
reader.addEventListener( 'load', function () {
|
97 |
+
importFormFile.name = file.name;
|
98 |
+
importFormFile.content = reader.result;
|
99 |
+
}, false);
|
100 |
+
|
101 |
+
// Use the readAsDataURL method of the FileReader API.
|
102 |
+
reader.readAsDataURL( file );
|
103 |
+
} );
|
104 |
|
105 |
var clickedElement;
|
106 |
|
assets/js/admin-settings.js
CHANGED
@@ -68,12 +68,12 @@ jQuery(document).ready(function($) {
|
|
68 |
downgradeInput.style.width = '100%';
|
69 |
downgradeInput.style.height = '3em';
|
70 |
downgradeCTA = document.createElement( 'p' );
|
71 |
-
downgradeCTA.innerHTML =
|
72 |
downgradeWarning = document.createElement( 'p' );
|
73 |
-
downgradeWarning.innerHTML =
|
74 |
downgradeWarning.style.color = 'red';
|
75 |
downgradeTitle = document.createElement( 'h3' );
|
76 |
-
downgradeTitle.innerHTML =
|
77 |
downgradeContainer = document.createElement( 'div' );
|
78 |
downgradeContainer.appendChild( downgradeTitle );
|
79 |
downgradeContainer.appendChild( downgradeWarning );
|
@@ -105,20 +105,20 @@ jQuery(document).ready(function($) {
|
|
105 |
var last_form = 0;
|
106 |
// Gives the user confidence things are happening
|
107 |
$( '#progressMsg' ).html( 'Deleting submissions for '
|
108 |
-
+
|
109 |
-
+
|
110 |
$( '#progressMsg').show();
|
111 |
// notify php this is the last one so it delete data and deactivate NF
|
112 |
-
if( formIndex ===
|
113 |
last_form = 1;
|
114 |
}
|
115 |
// do this deletion thang
|
116 |
$.post(
|
117 |
-
|
118 |
{
|
119 |
'action': 'nf_delete_all_data',
|
120 |
-
'form':
|
121 |
-
'security':
|
122 |
'last_form': last_form
|
123 |
}
|
124 |
).then (function( response ) {
|
@@ -126,7 +126,7 @@ jQuery(document).ready(function($) {
|
|
126 |
response = JSON.parse( response );
|
127 |
// we expect success and then move to the next form
|
128 |
if( response.data.success ) {
|
129 |
-
if( formIndex <
|
130 |
doAllDataDeletions( formIndex )
|
131 |
} else {
|
132 |
// if we're finished deleting data then redirect to plugins
|
@@ -139,7 +139,7 @@ jQuery(document).ready(function($) {
|
|
139 |
// writes error messages to console to help us debug
|
140 |
console.log( xhr.status + ' ' + error + '\r\n' +
|
141 |
'There was an error deleting submissions for '
|
142 |
-
+
|
143 |
});
|
144 |
};
|
145 |
// Add event listener for delete button
|
@@ -176,10 +176,10 @@ jQuery(document).ready(function($) {
|
|
176 |
'field': {
|
177 |
id: $( that ).data( 'id' )
|
178 |
},
|
179 |
-
'security':
|
180 |
};
|
181 |
|
182 |
-
$.post(
|
183 |
.done( function( response ) {
|
184 |
$( that ).closest( 'tr').fadeOut().remove();
|
185 |
});
|
@@ -194,7 +194,7 @@ jQuery(document).ready(function($) {
|
|
194 |
// TODO: Maybe this should be build using DOM node construction?
|
195 |
content: downgradeContainer.innerHTML,
|
196 |
btnPrimary: {
|
197 |
-
text:
|
198 |
class: 'nfDowngradeButtonPrimary',
|
199 |
callback: function( e ) {
|
200 |
// If our "Downgrade" button does not have have an attribute of disabled...
|
@@ -210,7 +210,7 @@ jQuery(document).ready(function($) {
|
|
210 |
}
|
211 |
},
|
212 |
btnSecondary: {
|
213 |
-
text:
|
214 |
class: 'nfDowngradeButtonSecondary',
|
215 |
callback: function( e ) {
|
216 |
// Close the modal if this button is clicked.
|
@@ -256,7 +256,7 @@ jQuery(document).ready(function($) {
|
|
256 |
} );
|
257 |
|
258 |
// If we're allowed to track site data...
|
259 |
-
if ( '1' ==
|
260 |
// Show the optout button.
|
261 |
$( '#nfTelOptin' ).addClass( 'hidden' );
|
262 |
$( '#nfTelOptout' ).removeClass( 'hidden' );
|
@@ -294,71 +294,47 @@ jQuery(document).ready(function($) {
|
|
294 |
} );
|
295 |
|
296 |
jQuery( '#nfTrashExpiredSubmissions' ).click( function( e ) {
|
297 |
-
var
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
deleteModal.maybeShowActions( false );
|
307 |
-
// Show the progress bar.
|
308 |
-
deleteModal.maybeShowProgress( true );
|
309 |
-
// Begin our cleanup process.
|
310 |
-
that.submissionExpirationProcess( that, -1, deleteModal );
|
311 |
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
|
|
|
|
321 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
322 |
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
batch_type: 'expired_submission_cleanup',
|
327 |
-
security: nf_settings.batch_nonce
|
328 |
-
};
|
329 |
-
jQuery.post( nf_settings.ajax_url, data, function( response ) {
|
330 |
-
response = JSON.parse( response );
|
331 |
-
// If we're done...
|
332 |
-
if ( response.batch_complete ) {
|
333 |
-
// Push our progress bar to 100%.
|
334 |
-
modal.setProgress( 100 );
|
335 |
-
modal.toggleModal( false );
|
336 |
-
// Exit.
|
337 |
-
return false;
|
338 |
-
}
|
339 |
-
// If we do not yet have a determined number of steps...
|
340 |
-
if ( -1 == steps ) {
|
341 |
-
// If step_toal is defined...
|
342 |
-
if ( 'undefined' != typeof response.step_total ) {
|
343 |
-
// Use the step_total.
|
344 |
-
steps = response.step_total;
|
345 |
-
} // Otherwise... (step_total is not defined)
|
346 |
-
else {
|
347 |
-
// Use step_remaining.
|
348 |
-
steps = response.step_remaining;
|
349 |
-
}
|
350 |
-
}
|
351 |
-
// Calculate our current step.
|
352 |
-
var step = steps - response.step_remaining;
|
353 |
-
// Calculate our maximum progress for this step.
|
354 |
-
var maxProgress = Math.round( step / steps * 100 );
|
355 |
-
// Increment the progress.
|
356 |
-
modal.incrementProgress ( maxProgress );
|
357 |
-
// Recall our function...
|
358 |
-
context.submissionExpirationProcess( context, steps, modal );
|
359 |
-
} );
|
360 |
-
}
|
361 |
|
362 |
-
|
363 |
-
|
|
|
|
|
|
|
|
|
|
|
364 |
});
|
68 |
downgradeInput.style.width = '100%';
|
69 |
downgradeInput.style.height = '3em';
|
70 |
downgradeCTA = document.createElement( 'p' );
|
71 |
+
downgradeCTA.innerHTML = nfAdmin.i18n.downgradeConfirmMessage;
|
72 |
downgradeWarning = document.createElement( 'p' );
|
73 |
+
downgradeWarning.innerHTML = nfAdmin.i18n.downgradeWarningMessage;
|
74 |
downgradeWarning.style.color = 'red';
|
75 |
downgradeTitle = document.createElement( 'h3' );
|
76 |
+
downgradeTitle.innerHTML = nfAdmin.i18n.downgradeMessage;
|
77 |
downgradeContainer = document.createElement( 'div' );
|
78 |
downgradeContainer.appendChild( downgradeTitle );
|
79 |
downgradeContainer.appendChild( downgradeWarning );
|
105 |
var last_form = 0;
|
106 |
// Gives the user confidence things are happening
|
107 |
$( '#progressMsg' ).html( 'Deleting submissions for '
|
108 |
+
+ nfAdmin.forms[ formIndex ].title + "" + ' ( ID: '
|
109 |
+
+ nfAdmin.forms[ formIndex ].id + ' )' );
|
110 |
$( '#progressMsg').show();
|
111 |
// notify php this is the last one so it delete data and deactivate NF
|
112 |
+
if( formIndex === nfAdmin.forms.length - 1 ) {
|
113 |
last_form = 1;
|
114 |
}
|
115 |
// do this deletion thang
|
116 |
$.post(
|
117 |
+
nfAdmin.ajax_url,
|
118 |
{
|
119 |
'action': 'nf_delete_all_data',
|
120 |
+
'form': nfAdmin.forms[ formIndex ].id,
|
121 |
+
'security': nfAdmin.nonce,
|
122 |
'last_form': last_form
|
123 |
}
|
124 |
).then (function( response ) {
|
126 |
response = JSON.parse( response );
|
127 |
// we expect success and then move to the next form
|
128 |
if( response.data.success ) {
|
129 |
+
if( formIndex < nfAdmin.forms.length ) {
|
130 |
doAllDataDeletions( formIndex )
|
131 |
} else {
|
132 |
// if we're finished deleting data then redirect to plugins
|
139 |
// writes error messages to console to help us debug
|
140 |
console.log( xhr.status + ' ' + error + '\r\n' +
|
141 |
'There was an error deleting submissions for '
|
142 |
+
+ nfAdmin.forms[ formIndex ].title );
|
143 |
});
|
144 |
};
|
145 |
// Add event listener for delete button
|
176 |
'field': {
|
177 |
id: $( that ).data( 'id' )
|
178 |
},
|
179 |
+
'security': nfAdmin.nonce
|
180 |
};
|
181 |
|
182 |
+
$.post( nfAdmin.ajax_url, data )
|
183 |
.done( function( response ) {
|
184 |
$( that ).closest( 'tr').fadeOut().remove();
|
185 |
});
|
194 |
// TODO: Maybe this should be build using DOM node construction?
|
195 |
content: downgradeContainer.innerHTML,
|
196 |
btnPrimary: {
|
197 |
+
text: nfAdmin.i18n.downgradeButtonPrimary,
|
198 |
class: 'nfDowngradeButtonPrimary',
|
199 |
callback: function( e ) {
|
200 |
// If our "Downgrade" button does not have have an attribute of disabled...
|
210 |
}
|
211 |
},
|
212 |
btnSecondary: {
|
213 |
+
text: nfAdmin.i18n.downgradeButtonSecondary,
|
214 |
class: 'nfDowngradeButtonSecondary',
|
215 |
callback: function( e ) {
|
216 |
// Close the modal if this button is clicked.
|
256 |
} );
|
257 |
|
258 |
// If we're allowed to track site data...
|
259 |
+
if ( '1' == nfAdmin.allow_telemetry ) {
|
260 |
// Show the optout button.
|
261 |
$( '#nfTelOptin' ).addClass( 'hidden' );
|
262 |
$( '#nfTelOptout' ).removeClass( 'hidden' );
|
294 |
} );
|
295 |
|
296 |
jQuery( '#nfTrashExpiredSubmissions' ).click( function( e ) {
|
297 |
+
var settings = {
|
298 |
+
content: '<p>' + nfAdmin.i18n.trashExpiredSubsMessage + '</p>',
|
299 |
+
btnPrimaryText: nfAdmin.i18n.trashExpiredSubsButtonPrimary,
|
300 |
+
btnSecondaryText: nfAdmin.i18n.trashExpiredSubsButtonSecondary,
|
301 |
+
batch_type: 'expired_submission_cleanup',
|
302 |
+
// extraData: [ 'test1', 'test2', 'test3' ]
|
303 |
+
}
|
304 |
+
new NinjaBatchProcessor( settings );
|
305 |
+
});
|
|
|
|
|
|
|
|
|
|
|
306 |
|
307 |
+
jQuery( '#nfRemoveMaintenanceMode' ).click( function( e ) {
|
308 |
+
|
309 |
+
var that = this;
|
310 |
+
|
311 |
+
jQuery( this ).addClass( 'disabled' ).attr( 'disabled', 'disabled' );
|
312 |
+
jQuery( '#nf_maintenanceModeProgress' ).html("<strong>Removing Maintenance Mode...</strong>" );
|
313 |
+
jQuery( '#nf_maintenanceModeProgress' ).fadeIn( 1 );
|
314 |
+
|
315 |
+
var data = {
|
316 |
+
action: 'nf_remove_maintenance_mode',
|
317 |
+
security: nf_settings.nonce,
|
318 |
};
|
319 |
+
$.post(
|
320 |
+
nf_settings.ajax_url,
|
321 |
+
data
|
322 |
+
).then (function( response ) {
|
323 |
+
response = JSON.parse( response );
|
324 |
+
// if there are errors then, console it out
|
325 |
+
if( response.data.errors ) {
|
326 |
+
console.log( response.data.errors );
|
327 |
+
}
|
328 |
|
329 |
+
jQuery( that ).removeClass( 'disabled' ).removeAttr( 'disabled' );
|
330 |
+
jQuery( '#nf_maintenanceModeProgress' ).html("<strong>Done.</strong>" );
|
331 |
+
jQuery( '#nf_maintenanceModeProgress' ).fadeOut( 600 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
|
333 |
+
} ).fail( function( xhr, status, error ) {
|
334 |
+
// writes error messages to console to help us debug
|
335 |
+
console.log( xhr.status + ' ' + error + '\r\n' +
|
336 |
+
'There was an error resetting maintenance mode' );
|
337 |
+
});
|
338 |
+
|
339 |
+
} );
|
340 |
});
|
assets/js/lib/batch-processor.js
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Batch Processor JS Object
|
3 |
+
*/
|
4 |
+
function NinjaBatchProcessor( settings ) {
|
5 |
+
var that = this;
|
6 |
+
var modalData = {
|
7 |
+
closeOnClick: false,
|
8 |
+
closeOnEsc: true,
|
9 |
+
useProgressBar: true
|
10 |
+
};
|
11 |
+
|
12 |
+
/**
|
13 |
+
* If we haven't been passed any content, make sure we pass an empty content var.
|
14 |
+
*/
|
15 |
+
if ( 'undefined' == typeof settings.content ) {
|
16 |
+
settings.content = '';
|
17 |
+
}
|
18 |
+
// Set our modalData content var.
|
19 |
+
modalData.content = settings.content;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* If we've been passed a loadingText var, pass that along.
|
23 |
+
*/
|
24 |
+
if ( 'undefined' != typeof settings.loadingText ) {
|
25 |
+
modalData.loadingText = settings.loadingText;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* If we haven't defined button text for our primary button, we don't want to pass button settings.
|
30 |
+
*
|
31 |
+
* Check to see if we've defined primary button text, and if we have, add button settings to the modalData.
|
32 |
+
*/
|
33 |
+
if ( 'undefined' != typeof settings.btnPrimaryText ) {
|
34 |
+
modalData.btnPrimary = {
|
35 |
+
text: settings.btnPrimaryText,
|
36 |
+
callback: function( e ) {
|
37 |
+
// Hide the buttons.
|
38 |
+
modalInstance.maybeShowActions( false );
|
39 |
+
// Show the progress bar.
|
40 |
+
modalInstance.maybeShowProgress( true );
|
41 |
+
// Begin our cleanup process.
|
42 |
+
that.postToProcessor( that, -1, modalInstance );
|
43 |
+
|
44 |
+
}
|
45 |
+
};
|
46 |
+
|
47 |
+
modalData.btnSecondary = {
|
48 |
+
text: settings.btnSecondaryText,
|
49 |
+
callback: function( e ) {
|
50 |
+
modalInstance.toggleModal( false );
|
51 |
+
}
|
52 |
+
};
|
53 |
+
} else { // If we don't have any buttons defined, then we want to run the batch process on modal open.
|
54 |
+
modalData.onOpenCallback = function() {
|
55 |
+
// Hide the buttons.
|
56 |
+
this.maybeShowActions( false );
|
57 |
+
// Show the progress bar.
|
58 |
+
this.maybeShowProgress( true );
|
59 |
+
// Begin our cleanup process.
|
60 |
+
that.postToProcessor( that, -1, this );
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
this.postToProcessor = function( context, steps, modal, data ) {
|
65 |
+
if ( 'undefined' == typeof data ) {
|
66 |
+
var data = {
|
67 |
+
action: 'nf_batch_process',
|
68 |
+
batch_type: settings.batch_type,
|
69 |
+
security: nfAdmin.batchNonce,
|
70 |
+
extraData: settings.extraData
|
71 |
+
};
|
72 |
+
}
|
73 |
+
|
74 |
+
jQuery.post( ajaxurl, data, function( response ) {
|
75 |
+
response = JSON.parse( response );
|
76 |
+
// If we're done...
|
77 |
+
if ( response.batch_complete ) {
|
78 |
+
// Push our progress bar to 100%.
|
79 |
+
modal.setProgress( 100 );
|
80 |
+
modal.toggleModal( false );
|
81 |
+
if ( 'undefined' != typeof settings.onCompleteCallback ) {
|
82 |
+
settings.onCompleteCallback( response );
|
83 |
+
}
|
84 |
+
// Exit.
|
85 |
+
return false;
|
86 |
+
}
|
87 |
+
// If we do not yet have a determined number of steps...
|
88 |
+
if ( -1 == steps ) {
|
89 |
+
// If step_toal is defined...
|
90 |
+
if ( 'undefined' != typeof response.step_total ) {
|
91 |
+
// Use the step_total.
|
92 |
+
steps = response.step_total;
|
93 |
+
} // Otherwise... (step_total is not defined)
|
94 |
+
else {
|
95 |
+
// Use step_remaining.
|
96 |
+
steps = response.step_remaining;
|
97 |
+
}
|
98 |
+
}
|
99 |
+
// If our PHP edited our extraData variable, update our JS var and pass it along.
|
100 |
+
if ( 'undefined' != typeof response.extraData ) {
|
101 |
+
// Update our extraData property.
|
102 |
+
data.extraData = response.extraData;
|
103 |
+
}
|
104 |
+
|
105 |
+
// Calculate our current step.
|
106 |
+
var step = steps - response.step_remaining;
|
107 |
+
// Calculate our maximum progress for this step.
|
108 |
+
var maxProgress = Math.round( step / steps * 100 );
|
109 |
+
// Increment the progress.
|
110 |
+
modal.incrementProgress ( maxProgress );
|
111 |
+
// Recall our function...
|
112 |
+
context.postToProcessor( context, steps, modal, data );
|
113 |
+
} );
|
114 |
+
}
|
115 |
+
|
116 |
+
var modalInstance = new NinjaModal( modalData );
|
117 |
+
}
|
assets/js/lib/ninjaModal.js
CHANGED
@@ -37,6 +37,7 @@ function NinjaModal ( data ) {
|
|
37 |
this.buttons.secondary = {};
|
38 |
this.buttons.primary.data = ( 'undefined' != typeof data.btnPrimary ? data.btnPrimary : false );
|
39 |
this.buttons.secondary.data = ( 'undefined' != typeof data.btnSecondary ? data.btnSecondary : false );
|
|
|
40 |
// See if we need the progress bar.
|
41 |
this.useProgressBar = ( 'undefined' != typeof data.useProgressBar ? data.useProgressBar : false );
|
42 |
if ( this.useProgressBar ) {
|
@@ -170,6 +171,10 @@ NinjaModal.prototype.initModal = function () {
|
|
170 |
// Attach the callback.
|
171 |
jQuery( this.content ).find( '#nf-button-secondary-' + this.dataId ).click( that.buttons.secondary.callback );
|
172 |
}
|
|
|
|
|
|
|
|
|
173 |
},
|
174 |
} );
|
175 |
// Setup our data id to keep the DOM ids unique.
|
@@ -268,6 +273,7 @@ NinjaModal.prototype.renderContent = function () {
|
|
268 |
this.buttons.secondary.dom.onclick = this.buttons.secondary.callback;
|
269 |
}
|
270 |
}
|
|
|
271 |
// Set our content.
|
272 |
this.popup.setContent( document.createElement( 'div' ).appendChild( contentBox ).parentElement.innerHTML );
|
273 |
}
|
37 |
this.buttons.secondary = {};
|
38 |
this.buttons.primary.data = ( 'undefined' != typeof data.btnPrimary ? data.btnPrimary : false );
|
39 |
this.buttons.secondary.data = ( 'undefined' != typeof data.btnSecondary ? data.btnSecondary : false );
|
40 |
+
this.onOpenCallback = ( 'undefined' != typeof data.onOpenCallback ? data.onOpenCallback : false );
|
41 |
// See if we need the progress bar.
|
42 |
this.useProgressBar = ( 'undefined' != typeof data.useProgressBar ? data.useProgressBar : false );
|
43 |
if ( this.useProgressBar ) {
|
171 |
// Attach the callback.
|
172 |
jQuery( this.content ).find( '#nf-button-secondary-' + this.dataId ).click( that.buttons.secondary.callback );
|
173 |
}
|
174 |
+
|
175 |
+
if ( that.onOpenCallback ) {
|
176 |
+
that.onOpenCallback();
|
177 |
+
}
|
178 |
},
|
179 |
} );
|
180 |
// Setup our data id to keep the DOM ids unique.
|
273 |
this.buttons.secondary.dom.onclick = this.buttons.secondary.callback;
|
274 |
}
|
275 |
}
|
276 |
+
|
277 |
// Set our content.
|
278 |
this.popup.setContent( document.createElement( 'div' ).appendChild( contentBox ).parentElement.innerHTML );
|
279 |
}
|
assets/js/min/dashboard.min.js
CHANGED
@@ -1,2 +1,3 @@
|
|
1 |
-
!function(){var e,t,n;!function(i){function o(e,t){return y.call(e,t)}function s(e,t){var n,i,o,s,r,a,l,c,d,u,h,m=t&&t.split("/"),f=v.map,p=f&&f["*"]||{};if(e&&"."===e.charAt(0))if(t){for(e=e.split("/"),r=e.length-1,v.nodeIdCompat&&j.test(e[r])&&(e[r]=e[r].replace(j,"")),e=m.slice(0,m.length-1).concat(e),d=0;d<e.length;d+=1)if("."===(h=e[d]))e.splice(d,1),d-=1;else if(".."===h){if(1===d&&(".."===e[2]||".."===e[0]))break;d>0&&(e.splice(d-1,2),d-=2)}e=e.join("/")}else 0===e.indexOf("./")&&(e=e.substring(2));if((m||p)&&f){for(n=e.split("/"),d=n.length;d>0;d-=1){if(i=n.slice(0,d).join("/"),m)for(u=m.length;u>0;u-=1)if((o=f[m.slice(0,u).join("/")])&&(o=o[i])){s=o,a=d;break}if(s)break;!l&&p&&p[i]&&(l=p[i],c=d)}!s&&l&&(s=l,a=c),s&&(n.splice(0,a,s),e=n.join("/"))}return e}function r(e,t){return function(){var n=C.call(arguments,0);return"string"!=typeof n[0]&&1===n.length&&n.push(null),m.apply(i,n.concat([e,t]))}}function a(e){return function(t){return s(t,e)}}function l(e){return function(t){w[e]=t}}function c(e){if(o(g,e)){var t=g[e];delete g[e],b[e]=!0,h.apply(i,t)}if(!o(w,e)&&!o(b,e))throw new Error("No "+e);return w[e]}function d(e){var t,n=e?e.indexOf("!"):-1;return n>-1&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function u(e){return function(){return v&&v.config&&v.config[e]||{}}}var h,m,f,p,w={},g={},v={},b={},y=Object.prototype.hasOwnProperty,C=[].slice,j=/\.js$/;f=function(e,t){var n,i=d(e),o=i[0];return e=i[1],o&&(o=s(o,t),n=c(o)),o?e=n&&n.normalize?n.normalize(e,a(t)):s(e,t):(e=s(e,t),i=d(e),o=i[0],e=i[1],o&&(n=c(o))),{f:o?o+"!"+e:e,n:e,pr:o,p:n}},p={require:function(e){return r(e)},exports:function(e){var t=w[e];return void 0!==t?t:w[e]={}},module:function(e){return{id:e,uri:"",exports:w[e],config:u(e)}}},h=function(e,t,n,s){var a,d,u,h,m,v,y=[],C=typeof n;if(s=s||e,"undefined"===C||"function"===C){for(t=!t.length&&n.length?["require","exports","module"]:t,m=0;m<t.length;m+=1)if(h=f(t[m],s),"require"===(d=h.f))y[m]=p.require(e);else if("exports"===d)y[m]=p.exports(e),v=!0;else if("module"===d)a=y[m]=p.module(e);else if(o(w,d)||o(g,d)||o(b,d))y[m]=c(d);else{if(!h.p)throw new Error(e+" missing "+d);h.p.load(h.n,r(s,!0),l(d),{}),y[m]=w[d]}u=n?n.apply(w[e],y):void 0,e&&(a&&a.exports!==i&&a.exports!==w[e]?w[e]=a.exports:u===i&&v||(w[e]=u))}else e&&(w[e]=n)},e=t=m=function(e,t,n,o,s){if("string"==typeof e)return p[e]?p[e](t):c(f(e,t).f);if(!e.splice){if(v=e,v.deps&&m(v.deps,v.callback),!t)return;t.splice?(e=t,t=n,n=null):e=i}return t=t||function(){},"function"==typeof n&&(n=o,o=s),o?h(i,e,t,n):setTimeout(function(){h(i,e,t,n)},4),m},m.config=function(e){return m(e)},e._defined=w,n=function(e,t,n){if("string"!=typeof e)throw new Error("See almond README: incorrect module build, no module name");t.splice||(n=t,t=[]),o(w,e)||o(g,e)||(g[e]=[e,t,n])},n.amd={jQuery:!0}}(),n("../../assets/js/lib/almond",function(){}),n("models/formModel",[],function(){return Backbone.Model.extend({defaults:{objectType:"form",id:0,title:"unknown",created_at:"unknown"},url:function(){return ajaxurl+"?action=nf_forms&form_id="+this.get("id")},initialize:function(){this.set("id",Number(this.get("id"))),this.get("id")&&this.initShortcode(this.get("id")),this.get("title")&&this.set("title",this.get("title").replace(/<\/?[^>]+(>|$)/g,""))},initShortcode:function(e){var t="[ninja_form id="+e+"]";this.set("shortcode",t)},destroy:function(){var e=this;jQuery.ajax({type:"POST",url:ajaxurl+"?action=nf_forms&method_override=delete&form_id="+this.get("id"),success:function(t){var t=JSON.parse(t);e.collection.remove(e)}})}})}),n("models/formCollection",["models/formModel"],function(e){return Backbone.Collection.extend({model:e,comparator:"title",tmpNum:1,url:function(){return ajaxurl+"?action=nf_forms"},initialize:function(){this.newIDs=[],this.baseUrl=window.location.href.split("?")[0],this.listenTo(i.channel("dashboard"),"forms:delete",this.modalConfirm),this.listenTo(i.channel("dashboard"),"forms:duplicate",this.duplicate),this.modal=new jBox("Modal",{width:400,addClass:"dashboard-modal",overlay:!0,closeOnClick:"body"})},parse:function(e,t){return e.data},modalConfirm:function(e){var t,n,i,o,s,r,a,l=e.model.get("id"),c=e.model.get("title");n=document.createElement("div"),n.style.paddingRight="20px",n.style.paddingLeft="20px",n.style.paddingBottom="20px",i=document.createElement("p"),o=document.createElement("em"),s=document.createElement("div"),r=document.createElement("button"),a=document.createElement("div"),n.classList.add("message"),o.innerHTML=c,i.innerHTML+=nfi18n.deleteWarningA+" (<strong>"+c+"</strong>). "+nfi18n.deleteWarningB,i.appendChild(document.createElement("br")),i.appendChild(document.createElement("br"));var d=document.createElement("a");d.href=this.baseUrl+"?page=nf-import-export&exportFormId="+l,d.innerHTML='<i class="fa fa-download" style="padding:5px;"></i>'+nfi18n.deleteXForm,d.target="_blank",i.appendChild(d),i.appendChild(document.createElement("br"));var u=document.createElement("a");u.href=this.baseUrl+"?page=nf-processing&action=download_all_subs&form_id="+l+"&redirect="+encodeURIComponent(this.baseUrl.replace("admin.php","edit.php")+"?post_status=all&post_type=nf_sub&form_id="+l),u.target="_blank",u.innerHTML='<i class="fa fa-download" style="padding:5px;"></i>'+nfi18n.deleteXSubs,i.appendChild(u),i.appendChild(document.createElement("br")),n.appendChild(i);var h=document.createElement("label");h.for="confirmDeleteFormInput",h.innerHTML=nfi18n.deleteConfirmA+' <span style="color:red;">DELETE</span> '+nfi18n.deleteConfirmB;var m=document.createElement("input");m.type="text",m.id="confirmDeleteFormInput",m.style.marginTop="10px",m.style.width="100%",m.style.height="2.5em",m.style.fontSize="1em",n.appendChild(h),n.appendChild(document.createElement("br")),n.appendChild(m),n.appendChild(document.createElement("br")),n.appendChild(document.createElement("br")),r.innerHTML=nfi18n.delete,r.classList.add("confirm","nf-button","primary","pull-right"),a.innerHTML=nfi18n.cancel,a.classList.add("cancel","nf-button","secondary"),s.appendChild(a),s.appendChild(r),s.classList.add("buttons"),n.appendChild(s),t=document.createElement("div"),t.appendChild(n),this.modal.setContent(t.innerHTML),this.modal.setTitle(nfi18n.deleteTitle),this.modal.open();var f=this;this.modal.container[0].getElementsByClassName("cancel")[0].addEventListener("click",function(){f.modalClose()}),this.modal.container[0].getElementsByClassName("confirm")[0].addEventListener("click",function(t){t.preventDefault(),"DELETE"===document.getElementById("confirmDeleteFormInput").value?f.confirmDelete(e):f.modalClose()})},modalClose:function(){this.modal.close()},confirmDelete:function(e){jQuery(e.el).removeClass("show-actions"),jQuery(e.el).addClass("deleting"),jQuery(e.el).animate({opacity:0,"line-height":0,display:"none"},500),console.log(e),e.model.destroy(),this.modalClose()},duplicate:function(e){var t='<div class="message">Duplicating <em>'+e.model.get("title")+'</em>...<div class="nf-loading-spinner"></div></div>';this.modal.setContent(t),this.modal.setTitle("Please Wait"),this.modal.open();var n=this;jQuery.ajax({type:"POST",url:ajaxurl+"?action=nf_forms&clone_id="+e.model.get("id"),success:function(t){var t=JSON.parse(t),i=t.data.new_form_id,o=e.model.clone();o.set({id:i,title:o.get("title")+" - copy",created_at:new Date}),o.initShortcode(i),e.model.collection.add(o),n.modalClose()}})}})}),n("controllers/formsController",["models/formModel","models/formCollection"],function(e,t){return Marionette.Object.extend({initialize:function(){this.forms=new t,i.channel("dashboard").reply("get:forms",this.getForms,this),this.forms.fetch({success:function(e){i.channel("dashboard").trigger("fetch:forms",e)}})},getForms:function(){return this.forms}})}),n("models/oauthModel",[],function(){return Backbone.Model.extend({defaults:{connected:null,connect_url:""},url:function(){return ajaxurl+"?action=nf_oauth"},initialize:function(){},parse:function(e,t){return e.data}})}),n("controllers/oauthController",["models/oauthModel"],function(e){return Marionette.Object.extend({initialize:function(){this.oauth=new e,i.channel("dashboard").reply("get:oauth",this.getOAuth,this),i.channel("dashboard").reply("disconnect:oauth",this.disconnect,this),i.channel("dashboard").reply("oauth:learn-more",this.learnMoreModal,this),this.initOAuth()},getOAuth:function(){return this.oauth},initOAuth:function(){this.oauth.fetch({success:function(e){i.channel("dashboard").trigger("fetch:oauth")}})},disconnect:function(){var e=this;new jBox("Confirm",{width:750,content:nfi18n.oauthDisconnectContent,confirmButton:nfi18n.oauthDisconnectConfirm,cancelButton:nfi18n.oauthDisconnectCancel,closeOnConfirm:!0,confirm:function(){jQuery.ajax({type:"POST",url:ajaxurl+"?action=nf_oauth_disconnect",success:function(t){console.log(t),e.initOAuth()}})}}).open()},learnMoreModal:function(){new jBox("Modal",{width:500,content:nfi18n.oauthLearnMoreContent}).open()}})}),n("models/serviceModel",[],function(){return Backbone.Model.extend({defaults:{objectType:"service",name:"",slug:"",installPath:"",description:"",enabled:null,infoLink:null,serviceLink:null,is_installing:!1,classes:""},url:function(){return ajaxurl+"?action=nf_service_"+this.get("slug")},initialize:function(){this.get("slug")==serviceSuccess&&this.get("successMessage")&&new jBox("Modal",{width:300,addClass:"dashboard-modal",overlay:!0,closeOnClick:!0,content:this.get("successMessage"),title:this.get("successMessageTitle"),closeButton:"box"}).open();var e=this;i.channel("dashboard").reply("install:service:"+this.get("slug"),function(){if(e.get("serviceLink")&&e.get("serviceLink").href){var t=e.get("serviceLink").href;new jBox("Modal",{width:300,addClass:"dashboard-modal",overlay:!0,closeOnClick:"body",content:nfi18n.serviceRedirect}).open();var n=i.channel("dashboard").request("get:oauth");if(n.get("connected"))window.location=t;else{if(e.get("connect_url"))return window.location=e.get("connect_url")+"&redirect="+t;window.location=n.get("connect_url")+"&redirect="+t}}})},save:function(){var e=this;jQuery.ajax({type:"POST",url:this.url(),data:this.toJSON()}).done(function(t){var n=JSON.parse(t);void 0!==n.error&&(alert(nfi18n.serviceUpdateError+" "+n.error),e.set("enabled",!e.get("enabled"))),i.channel("dashboard").trigger("save:service-"+e.get("slug"))})}})}),n("models/serviceCollection",["models/serviceModel"],function(e){return Backbone.Collection.extend({model:e,comparator:"name",url:function(){return ajaxurl+"?action=nf_services"},initialize:function(){},parse:function(e,t){return e.data}})}),n("controllers/servicesController",["models/serviceCollection"],function(e){return Marionette.Object.extend({initialize:function(){this.services=new e,i.channel("dashboard").reply("install:service",this.installService,this),i.channel("dashboard").reply("get:services",this.getServices,this),this.fetchServices()},getServices:function(){return this.services},fetchServices:function(e){this.services.fetch({success:function(t){e&&e(t),i.channel("dashboard").trigger("fetch:services")}})},installService:function(e){var t=this;if(!(e instanceof Backbone.Model))var e=this.services.find(function(t){return e==t.get("slug")});e.set("is_installing",!0);var n=e.get("slug"),o=e.get("installPath");jQuery.post(ajaxurl,{action:"nf_services_install",plugin:n,install_path:o},function(e){t.fetchServices(function(){i.channel("dashboard").request("install:service:"+n)})})}})}),n("views/widgets/forms/formsFilter",[],function(){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-filter",ui:{input:"input"},events:{"keyup @ui.input":"updateFilter"},initialize:function(){this.listenTo(i.channel("widget-forms"),"change:content",this.clearFilter)},updateFilter:function(){var e=this.getUI("input").val();i.channel("widget-forms").trigger("update:filter",e)},clearFilter:function(){this.getUI("input").val("")},updatePlaceholder:function(e){this.getUI("input").attr("placeholder",e)}})}),n("views/widgets/forms/formsTableRow",[],function(){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-table-row",tagName:"tr",replaceElement:!0,ui:{delete:".delete",duplicate:".duplicate",edit:".nf-item-edit"},events:{"click @ui.delete":function(){i.channel("dashboard").trigger("forms:delete",this)},"click @ui.duplicate":function(){i.channel("dashboard").trigger("forms:duplicate",this)},"click @ui.edit":function(e){this.$el.toggleClass("show-actions").siblings().removeClass("show-actions")}},templateContext:function(){var e=this.model;return{created_at:moment(e.get("created_at")).format("MM/DD/YY h:mm A")}}})}),n("views/widgets/forms/formsTableEmpty",[],function(){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-table-empty",tagName:"tr"})}),n("views/widgets/forms/formsTableBody",["views/widgets/forms/formsTableRow","views/widgets/forms/formsTableEmpty"],function(e,t){return Marionette.CollectionView.extend({childView:e,emptyView:t,className:"forms-collection",tagName:"tbody",initialize:function(){this.listenTo(i.channel("widget-forms"),"update:filter",this.updateFilter)},updateFilter:function(e){this.setFilter(function(t,n,i){return 0<=t.get("title").toLowerCase().indexOf(e.toLowerCase())})}})}),n("views/widgets/forms/formsTableLoading",[],function(){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-table-loading",tagName:"tr"})}),n("views/widgets/forms/formsTable",["views/widgets/forms/formsTableBody","views/widgets/forms/formsTableLoading","models/formCollection"],function(e,t,n){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-table",className:"nf-table-display",tagName:"table",initialize:function(){var t=this;this.listenTo(i.channel("dashboard"),"fetch:forms",function(n){t.showChildView("body",new e({collection:n}))})},regions:{body:{el:"tbody",replaceElement:!0}},ui:{sortable:".sortable",body:"tbody",action2:".action2",more:".more",less:".less"},onRender:function(){this.getUI("less").hide();var n=i.channel("dashboard").request("get:forms");void 0===n?this.showChildView("body",new t):this.showChildView("body",new e({collection:n})),this.maybeHideMoreButton()},events:{"click @ui.sortable":"sortFormsTable","click @ui.more":"showMore","click @ui.less":"showLess"},sortFormsTable:function(e){this.getUI("sortable").removeClass("sorted-asc"),this.getUI("sortable").removeClass("sorted-desc");var t=jQuery(e.target).data("sort"),n=jQuery(e.target).data("reverse")||0;n?(jQuery(e.target).addClass("sorted-desc"),jQuery(e.target).removeClass("sorted-asc")):(jQuery(e.target).addClass("sorted-asc"),jQuery(e.target).removeClass("sorted-desc"));var i=this.getChildView("body").collection;i.comparator=function(e,i){return name1=e.get(t).toLowerCase(),name2=i.get(t).toLowerCase(),name1<name2?ret=-1:name1>name2?ret=1:ret=0,n&&(ret=-ret),ret},i.sort(),n?(i.models.reverse(),jQuery(e.target).data("reverse",0)):jQuery(e.target).data("reverse",1)},showMore:function(){this.getUI("more").hide(),this.getUI("less").show(),this.getUI("body").addClass("more")},showLess:function(){this.getUI("less").hide(),this.getUI("more").show(),this.getUI("body").removeClass("more")},maybeHideMoreButton:function(){void 0!==this.collection&&10<this.collection.length||this.getUI("action2").hide()}})}),n("models/formTemplateModel",[],function(){return Backbone.Model.extend({defaults:{objectType:"template",id:"none",title:"unknown",type:""},initialize:function(){this.set("desc",this.get("template-desc")),this.set("modal-content",this.get("modal-content")),this.set("modal-title",this.get("modal-title"))}})}),n("models/formTemplateCollection",["models/formTemplateModel"],function(e){return Backbone.Collection.extend({model:e,tmpNum:1,url:function(){return ajaxurl+"?action=nf_new_form_templates"},parse:function(e,t){return e.data},initialize:function(){this.fetch({success:function(e){},error:function(e){}})}})}),n("views/widgets/forms/newFormTemplate",[],function(){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-template",events:{click:"maybeOpenModal"},maybeOpenModal:function(e){if("ad"!=this.model.get("type"))return!0;e.preventDefault(),new jBox("Modal",{width:450,title:this.model.get("modal-title"),content:this.model.get("modal-content"),closeButton:"box",blockScroll:!0}).open()}})}),n("views/widgets/forms/newFormGrid",["models/formTemplateCollection","views/widgets/forms/newFormTemplate"],function(e,t){return Marionette.CollectionView.extend({tagName:"div",className:"template-list",collection:new e,childView:t,initialize:function(){this.listenTo(i.channel("widget-forms"),"update:filter",this.updateFilter)},updateFilter:function(e){this.setFilter(function(t,n,i){return 0<=t.get("title").toLowerCase().indexOf(e.toLowerCase())})}})}),n("views/widgets/forms/forms",["views/widgets/forms/formsFilter","views/widgets/forms/formsTable","views/widgets/forms/newFormGrid"],function(e,t,n){return Marionette.View.extend({template:"#tmpl-nf-widget-forms",regions:{filter:".filter",content:".content"},ui:{add:".add",cancel:".cancel"},initialize:function(){i.channel("widget-forms").reply("show:newFormsGrid",this.showNewFormGrid,this),i.channel("widget-forms").reply("show:formsTable",this.showFormsTable,this)},onRender:function(){this.getUI("cancel").hide(),this.showChildView("filter",new e),"#new-form"==window.location.hash?(this.getUI("add").hide(),this.getUI("cancel").show(),this.showChildView("content",new n)):this.showChildView("content",new t)},events:{"click @ui.add":"showNewFormGrid","click @ui.cancel":"showFormsTable"},showNewFormGrid:function(){window.location.hash="new-form",this.showChildView("content",new n),i.channel("widget-forms").trigger("change:content"),this.getUI("add").hide(),this.getUI("cancel").show(),this.getChildView("filter").updatePlaceholder("Search Templates")},showFormsTable:function(){console.log(this),window.location.hash="forms",this.showChildView("content",new t),i.channel("widget-forms").trigger("change:content"),this.getUI("cancel").hide(),this.getUI("add").show(),this.getChildView("filter").updatePlaceholder("Search Forms")}})}),n("views/sections/widgets.js",["views/widgets/forms/forms"],function(e){return Marionette.View.extend({template:"#tmpl-nf-widgets",regions:{forms:".widget-forms"},onRender:function(){this.showChildView("forms",new e)}})}),n("views/services/service",[],function(){return Marionette.View.extend({template:"#tmpl-nf-service",className:function(){return"nf-extend nf-box "+this.model.get("classes")},ui:{install:".js--install",learnMore:".js--learn-more",enabled:".nf-toggle.setting",toggleEnable:".nf-toggle + label"},events:{"click @ui.install":function(){i.channel("dashboard").request("install:service",this.model)},"click @ui.learnMore":function(){this.showLearnMore()},"click @ui.toggleEnable":function(){if(null==this.model.get("enabled")&&this.model.get("link"))return window.location=this.model.get("link"),this.render();this.model.set("enabled",!this.model.get("enabled")),this.model.save("enabled"),this.render()}},initialize:function(e){this.updateOAuth(),this.listenTo(this.model,"change",this.render),i.channel("dashboard").reply("more:service:"+this.model.get("slug"),this.showLearnMore,this),this.listenTo(i.channel("dashboard"),"fetch:oauth",this.updateOAuth),this.listenTo(i.channel("dashboard"),"save:service-"+this.model.get("slug"),this.render)},showLearnMore:function(){var e=new jBox("Modal",{width:750,title:this.model.get("learnMoreTitle")||this.model.get("name"),content:this.model.get("learnMore"),closeButton:"box",blockScroll:!0});e.open(),i.channel("dashboard").reply("service:"+this.model.get("slug")+":modal",function(){return e})},updateOAuth:function(){var e=i.channel("dashboard").request("get:oauth");this.connected=e.get("connected"),this.render()},templateContext:function(){return{is_connected:this.connected}}})}),n("views/services/services",["views/services/service","models/serviceCollection"],function(e,t){return Marionette.CollectionView.extend({collection:new t,className:"wrap apps-container",childView:e,initialize:function(){this.updateCollection(),this.listenTo(i.channel("dashboard"),"fetch:services",this.updateCollection)},updateCollection:function(){this.collection=i.channel("dashboard").request("get:services"),this.render()}})}),n("views/sections/services.js",["views/services/services"],function(e){return Marionette.View.extend({template:"#tmpl-nf-services",regions:{services:".services"},onRender:function(){this.showChildView("services",new e)}})}),n("views/sections/apps.js",[],function(){return Marionette.View.extend({template:"#tmpl-nf-apps"})}),n("views/sections/memberships.js",[],function(){return Marionette.View.extend({template:"#tmpl-nf-memberships"})}),n("views/oauth.js",["models/oauthModel"],function(e){return Marionette.View.extend({model:new e,template:"#tmpl-nf-notices-oauth",className:"nf-notices--oauth",ui:{disconnect:".js--disconnect"},initialize:function(e){this.listenTo(i.channel("dashboard"),"fetch:oauth",this.updateModel)},updateModel:function(){this.model=i.channel("dashboard").request("get:oauth"),this.render()},events:{"click @ui.disconnect":function(){i.channel("dashboard").request("disconnect:oauth")}}})}),n("models/promotionModel",[],function(){return Backbone.Model.extend({defaults:{id:"",content:""},initialize:function(){}})}),n("views/promotion.js",["models/promotionModel"],function(e){return Marionette.View.extend({model:null,template:"#tmpl-nf-promotion",className:"nf-promotion",initialize:function(){var t=nfPromotions[Math.floor(Math.random()*nfPromotions.length)];this.model=new e(t)}})}),n("views/dashboardView",["views/sections/widgets.js","views/sections/services.js","views/sections/apps.js","views/sections/memberships.js","views/oauth.js","views/promotion.js"],function(e,t,n,o,s,r){return Marionette.View.extend({template:"#tmpl-nf-dashboard",currentView:"widgets",regions:{notices:".notices",promotions:".promotions",content:".content"},events:{"click .widgets a":function(t){this.showChildView("content",new e),jQuery("."+this.currentView).find("a").removeClass("active"),t.target.classList.add("active"),this.currentView="widgets"},"click .services a":function(e){this.showChildView("content",new t),jQuery("."+this.currentView).find("a").removeClass("active"),e.target.classList.add("active"),this.currentView="services"},"click .apps a":function(e){this.showChildView("content",new n),jQuery("."+this.currentView).find("a").removeClass("active"),e.target.classList.add("active"),this.currentView="apps"},"click .memberships a":function(e){this.showChildView("content",new o),jQuery("."+this.currentView).find("a").removeClass("active"),e.target.classList.add("active"),this.currentView="memberships"}},initialize:function(){switch(window.location.hash){case"#apps":this.currentView="apps";break;case"#services":this.currentView="services";break;case"#memberships":this.currentView="memberships";break;case"#widgets":default:this.currentView="widgets"}i.channel("dashboard").reply("show:widgets",function(){this.showChildView("content",new e),jQuery("nav.sections a.active").removeClass("active"),jQuery("nav.sections .widgets a").addClass("active"),this.currentView="widgets"},this),i.channel("dashboard").reply("show:services",function(){this.showChildView("content",new t),jQuery("nav.sections a.active").removeClass("active"),jQuery("nav.sections .services a").addClass("active"),this.currentView="services"},this),i.channel("dashboard").reply("show:apps",function(){this.showChildView("content",new n),jQuery("nav.sections a.active").removeClass("active"),jQuery("nav.sections .apps a").addClass("active"),this.currentView="apps"},this)},onRender:function(){switch(useServices&&this.showChildView("notices",new s),useServices&&this.showChildView("promotions",new r),window.location.hash){case"#apps":var i=new n;break;case"#memberships":var i=new o;break;case"#services":var i=new t;break;case"#widgets":default:var i=new e}if(this.showChildView("content",i),"1"==nfAdmin.showOptin){var a=new jBox("Modal",{closeOnEsc:!1,closeOnClick:!1,width:400}),l=document.createElement("div");l.id="optin-modal-title";var c=document.createElement("h2");c.innerHTML="Help make Ninja Forms better!",l.appendChild(c);var d=document.createElement("div");d.classList.add("message"),d.style.padding="0px 20px 20px 20px",d.innerHTML=nfi18n.optinContent;var u=document.createElement("p");u.style.paddingBottom="10px";var h=document.createElement("input");h.id="optin-send-email",h.setAttribute("type","checkbox"),h.style.margin="7px";var m=document.createElement("label");m.setAttribute("for","optin-send-email"),m.innerHTML=nfi18n.optinYesplease,u.appendChild(h),u.appendChild(m),d.appendChild(u),u=document.createElement("p"),u.id="optin-block",u.style.padding="0px 5px 20px 5px",u.style.display="none";var f=document.createElement("input");f.id="optin-email-address",f.setAttribute("type","text"),f.setAttribute("value",nfAdmin.currentUserEmail),f.style.width="100%",f.style.fontSize="16px",u.appendChild(f),d.appendChild(u);var p=document.createElement("span");p.id="optin-spinner",p.classList.add("spinner"),p.style.display="none",d.appendChild(p);var w=document.createElement("div");w.id="optin-buttons",w.classList.add("buttons");var g=document.createElement("div");g.id="optout",g.classList.add("nf-button","secondary"),g.innerHTML=nfi18n.optinSecondary,w.appendChild(g);var v=document.createElement("div");v.id="optin",v.classList.add("nf-button","primary","pull-right"),v.innerHTML=nfi18n.optinPrimary,w.appendChild(v),d.appendChild(w);var b=document.createElement("h2");b.innerHTML=nfi18n.optinAwesome;var y=document.createElement("div");y.id="optin-thankyou",y.classList.add("message"),y.style.padding="20px",y.innerHTML=nfi18n.optinThanks,a.setContent(document.createElement("div").appendChild(d).innerHTML),a.setTitle(document.createElement("div").appendChild(l).innerHTML),a.open(),jQuery("#optin-send-email").click(function(e){jQuery(this).is(":checked")?jQuery("#optin-block").show():jQuery("#optin-block").hide()}),jQuery("#optin").click(function(e){var t;jQuery("#optin-send-email").attr("checked")?(t=1,userEmail=jQuery("#optin-email-address").val()):(t=0,userEmail=""),jQuery("#optin").unbind("click"),jQuery("#optout").unbind("click");var n=jQuery("#optin").width();jQuery("#optin").html('<span class="dashicons dashicons-update dashicons-update-spin"></span>'),jQuery("#optin").width(n),jQuery.post(ajaxurl,{action:"nf_optin",ninja_forms_opt_in:1,send_email:t,user_email:userEmail},function(e){a.setTitle(document.createElement("div").appendChild(b).innerHTML),a.setContent(document.createElement("div").appendChild(y).innerHTML),setTimeout(function(){a.close()},2e3)})}),jQuery("#optout").click(function(e){jQuery("#optin").unbind("click"),jQuery("#optout").unbind("click");var t=jQuery("#optout").width();jQuery("#optout").html('<span class="dashicons dashicons-update dashicons-update-spin"></span>'),jQuery("#optout").width(t),jQuery.post(ajaxurl,{action:"nf_optin",ninja_forms_opt_in:0},function(e){a.close()})})}else if("1"==nfAdmin.doingCleanup)var C=this,j={width:450,closeOnClick:!1,closeOnEsc:!1,content:nfi18n.cleanupContent,useProgressBar:!0,loadingText:nfi18n.cleanupLoading,btnSecondary:{text:nfi18n.cleanupSecondary,callback:function(){x.toggleModal(!1)}},btnPrimary:{text:nfi18n.cleanupPrimary,callback:function(){jQuery(window).bind("beforeunload",function(){return"Are you sure? Leaving before the process completes could cause damage to your data."}),x.maybeShowActions(!1),x.maybeShowProgress(!0),C.cleanupProcess(C,-1,x)}}},x=new NinjaModal(j);if(void 0!==nfAdmin.formTelemetry&&1==nfAdmin.formTelemetry){var M={action:"nf_form_telemetry",security:nfAdmin.ajaxNonce};jQuery.post(ajaxurl,M)}},templateContext:function(){var e=this;return{renderNav:function(){var t=document.createElement("div");return _.each(nfDashItems,function(n){var i=document.createElement("li"),o=document.createElement("a");o.href="#"+n.slug,e.currentView==n.slug&&o.classList.add("active"),o.innerHTML=n.niceName,i.classList.add(n.slug),i.appendChild(o),t.appendChild(i)}),t.innerHTML}}},cleanupProcess:function(e,t,n){var i={action:"nf_batch_process",batch_type:"data_cleanup",security:nfAdmin.batchNonce};jQuery.post(ajaxurl,i,function(i){if(i=JSON.parse(i),i.batch_complete)return n.setProgress(100),jQuery(window).unbind("beforeunload"),n.toggleModal(!1),!1;-1==t&&(t=void 0!==i.step_total?i.step_total:i.step_remaining);var o=t-i.step_remaining,s=Math.round(o/t*100);n.incrementProgress(s),e.cleanupProcess(e,t,n)})}})});var i=Backbone.Radio;useServices||(nfDashItems=nfDashItems.filter(function(e){return"services"!==e.slug})),jQuery(document).ready(function(e){t(["controllers/formsController","controllers/oauthController","controllers/servicesController","views/dashboardView"],function(t,n,i,o){(new(Marionette.Application.extend({region:"#ninja-forms-dashboard",controllers:{},initialize:function(e){var t=this;Marionette.Renderer.render=function(e,n){var e=t.template(e);return e(n)}},onStart:function(){this.showView(new o),this.controllers.forms=new t,useServices&&(this.controllers.oauth=new n),useServices&&(this.controllers.services=new i)},template:function(t){return _.template(e(t).html(),{evaluate:/<#([\s\S]+?)#>/g,interpolate:/\{\{\{([\s\S]+?)\}\}\}/g,escape:/\{\{([^\}]+?)\}\}(?!\})/g,variable:"data"})}}))).start()})}),jQuery('a[href="admin.php?page=ninja-forms#new-form"]').on("click",function(e){e.preventDefault(),window.location.hash="new-form",i.channel("dashboard").request("show:widgets"),i.channel("widget-forms").request("show:newFormsGrid")}),jQuery('a[href="admin.php?page=ninja-forms#apps"]').on("click",function(e){e.preventDefault(),window.location.hash="apps",i.channel("dashboard").request("show:apps")}),jQuery('a[href="admin.php?page=ninja-forms"]').on("click",function(e){e.preventDefault(),window.location.hash="forms",i.channel("dashboard").request("show:widgets"),i.channel("widget-forms").request("show:formsTable")}),jQuery(window).on("hashchange",function(){var e=window.location.hash.substr(1);i.channel("dashboard").request("show:"+e)}),n("main",function(){})}();
|
|
|
2 |
//# sourceMappingURL=dashboard.min.js.map
|
1 |
+
!function(){var e,t,n;!function(i){function s(e,t){return y.call(e,t)}function o(e,t){var n,i,s,o,r,a,l,d,c,u,h,m=t&&t.split("/"),p=v.map,f=p&&p["*"]||{};if(e&&"."===e.charAt(0))if(t){for(e=e.split("/"),r=e.length-1,v.nodeIdCompat&&j.test(e[r])&&(e[r]=e[r].replace(j,"")),e=m.slice(0,m.length-1).concat(e),c=0;c<e.length;c+=1)if("."===(h=e[c]))e.splice(c,1),c-=1;else if(".."===h){if(1===c&&(".."===e[2]||".."===e[0]))break;c>0&&(e.splice(c-1,2),c-=2)}e=e.join("/")}else 0===e.indexOf("./")&&(e=e.substring(2));if((m||f)&&p){for(n=e.split("/"),c=n.length;c>0;c-=1){if(i=n.slice(0,c).join("/"),m)for(u=m.length;u>0;u-=1)if((s=p[m.slice(0,u).join("/")])&&(s=s[i])){o=s,a=c;break}if(o)break;!l&&f&&f[i]&&(l=f[i],d=c)}!o&&l&&(o=l,a=d),o&&(n.splice(0,a,o),e=n.join("/"))}return e}function r(e,t){return function(){var n=C.call(arguments,0);return"string"!=typeof n[0]&&1===n.length&&n.push(null),m.apply(i,n.concat([e,t]))}}function a(e){return function(t){return o(t,e)}}function l(e){return function(t){w[e]=t}}function d(e){if(s(g,e)){var t=g[e];delete g[e],b[e]=!0,h.apply(i,t)}if(!s(w,e)&&!s(b,e))throw new Error("No "+e);return w[e]}function c(e){var t,n=e?e.indexOf("!"):-1;return n>-1&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function u(e){return function(){return v&&v.config&&v.config[e]||{}}}var h,m,p,f,w={},g={},v={},b={},y=Object.prototype.hasOwnProperty,C=[].slice,j=/\.js$/;p=function(e,t){var n,i=c(e),s=i[0];return e=i[1],s&&(s=o(s,t),n=d(s)),s?e=n&&n.normalize?n.normalize(e,a(t)):o(e,t):(e=o(e,t),i=c(e),s=i[0],e=i[1],s&&(n=d(s))),{f:s?s+"!"+e:e,n:e,pr:s,p:n}},f={require:function(e){return r(e)},exports:function(e){var t=w[e];return void 0!==t?t:w[e]={}},module:function(e){return{id:e,uri:"",exports:w[e],config:u(e)}}},h=function(e,t,n,o){var a,c,u,h,m,v,y=[],C=typeof n;if(o=o||e,"undefined"===C||"function"===C){for(t=!t.length&&n.length?["require","exports","module"]:t,m=0;m<t.length;m+=1)if(h=p(t[m],o),"require"===(c=h.f))y[m]=f.require(e);else if("exports"===c)y[m]=f.exports(e),v=!0;else if("module"===c)a=y[m]=f.module(e);else if(s(w,c)||s(g,c)||s(b,c))y[m]=d(c);else{if(!h.p)throw new Error(e+" missing "+c);h.p.load(h.n,r(o,!0),l(c),{}),y[m]=w[c]}u=n?n.apply(w[e],y):void 0,e&&(a&&a.exports!==i&&a.exports!==w[e]?w[e]=a.exports:u===i&&v||(w[e]=u))}else e&&(w[e]=n)},e=t=m=function(e,t,n,s,o){if("string"==typeof e)return f[e]?f[e](t):d(p(e,t).f);if(!e.splice){if(v=e,v.deps&&m(v.deps,v.callback),!t)return;t.splice?(e=t,t=n,n=null):e=i}return t=t||function(){},"function"==typeof n&&(n=s,s=o),s?h(i,e,t,n):setTimeout(function(){h(i,e,t,n)},4),m},m.config=function(e){return m(e)},e._defined=w,n=function(e,t,n){if("string"!=typeof e)throw new Error("See almond README: incorrect module build, no module name");t.splice||(n=t,t=[]),s(w,e)||s(g,e)||(g[e]=[e,t,n])},n.amd={jQuery:!0}}(),n("../../assets/js/lib/almond",function(){}),n("models/formModel",[],function(){return Backbone.Model.extend({defaults:{objectType:"form",id:0,title:"unknown",created_at:"unknown"},url:function(){return ajaxurl+"?action=nf_forms&form_id="+this.get("id")},initialize:function(){this.set("id",Number(this.get("id"))),this.get("id")&&this.initShortcode(this.get("id")),this.get("title")&&this.set("title",this.get("title").replace(/<\/?[^>]+(>|$)/g,""))},initShortcode:function(e){var t="[ninja_form id="+e+"]";this.set("shortcode",t)},destroy:function(){var e=this;jQuery.ajax({type:"POST",url:ajaxurl+"?action=nf_forms&method_override=delete&form_id="+this.get("id"),success:function(t){var t=JSON.parse(t);e.collection.remove(e)}})}})}),n("models/formCollection",["models/formModel"],function(e){return Backbone.Collection.extend({model:e,comparator:"title",tmpNum:1,url:function(){return ajaxurl+"?action=nf_forms"},initialize:function(){this.newIDs=[],this.baseUrl=window.location.href.split("?")[0],this.listenTo(i.channel("dashboard"),"forms:delete",this.modalConfirm),this.listenTo(i.channel("dashboard"),"forms:duplicate",this.duplicate),this.modal=new jBox("Modal",{width:400,addClass:"dashboard-modal",overlay:!0,closeOnClick:"body"})},parse:function(e,t){return e.data},modalConfirm:function(e){var t,n,i,s,o,r,a,l=e.model.get("id"),d=e.model.get("title");n=document.createElement("div"),n.style.paddingRight="20px",n.style.paddingLeft="20px",n.style.paddingBottom="20px",i=document.createElement("p"),s=document.createElement("em"),o=document.createElement("div"),r=document.createElement("button"),a=document.createElement("div"),n.classList.add("message"),s.innerHTML=d,i.innerHTML+=nfi18n.deleteWarningA+" (<strong>"+d+"</strong>). "+nfi18n.deleteWarningB,i.appendChild(document.createElement("br")),i.appendChild(document.createElement("br"));var c=document.createElement("a");c.href=this.baseUrl+"?page=nf-import-export&exportFormId="+l,c.innerHTML='<i class="fa fa-download" style="padding:5px;"></i>'+nfi18n.deleteXForm,c.target="_blank",i.appendChild(c),i.appendChild(document.createElement("br"));var u=document.createElement("a");u.href=this.baseUrl+"?page=nf-processing&action=download_all_subs&form_id="+l+"&redirect="+encodeURIComponent(this.baseUrl.replace("admin.php","edit.php")+"?post_status=all&post_type=nf_sub&form_id="+l),u.target="_blank",u.innerHTML='<i class="fa fa-download" style="padding:5px;"></i>'+nfi18n.deleteXSubs,i.appendChild(u),i.appendChild(document.createElement("br")),n.appendChild(i);var h=document.createElement("label");h.for="confirmDeleteFormInput",h.innerHTML=nfi18n.deleteConfirmA+' <span style="color:red;">DELETE</span> '+nfi18n.deleteConfirmB;var m=document.createElement("input");m.type="text",m.id="confirmDeleteFormInput",m.style.marginTop="10px",m.style.width="100%",m.style.height="2.5em",m.style.fontSize="1em",n.appendChild(h),n.appendChild(document.createElement("br")),n.appendChild(m),n.appendChild(document.createElement("br")),n.appendChild(document.createElement("br")),r.innerHTML=nfi18n.delete,r.classList.add("confirm","nf-button","primary","pull-right"),a.innerHTML=nfi18n.cancel,a.classList.add("cancel","nf-button","secondary"),o.appendChild(a),o.appendChild(r),o.classList.add("buttons"),n.appendChild(o),t=document.createElement("div"),t.appendChild(n),this.modal.setContent(t.innerHTML),this.modal.setTitle(nfi18n.deleteTitle),this.modal.open();var p=this;this.modal.container[0].getElementsByClassName("cancel")[0].addEventListener("click",function(){p.modalClose()}),this.modal.container[0].getElementsByClassName("confirm")[0].addEventListener("click",function(t){t.preventDefault(),"DELETE"===document.getElementById("confirmDeleteFormInput").value?p.confirmDelete(e):p.modalClose()})},modalClose:function(){this.modal.close()},confirmDelete:function(e){jQuery(e.el).removeClass("show-actions"),jQuery(e.el).addClass("deleting"),jQuery(e.el).animate({opacity:0,"line-height":0,display:"none"},500),console.log(e),e.model.destroy(),this.modalClose()},duplicate:function(e){var t='<div class="message">Duplicating <em>'+e.model.get("title")+'</em>...<div class="nf-loading-spinner"></div></div>';this.modal.setContent(t),this.modal.setTitle("Please Wait"),this.modal.open();var n=this;jQuery.ajax({type:"POST",url:ajaxurl+"?action=nf_forms&clone_id="+e.model.get("id"),success:function(t){var t=JSON.parse(t),i=t.data.new_form_id,s=e.model.clone();s.set({id:i,title:s.get("title")+" - copy",created_at:new Date}),s.initShortcode(i),e.model.collection.add(s),n.modalClose()}})}})}),n("controllers/formsController",["models/formModel","models/formCollection"],function(e,t){return Marionette.Object.extend({initialize:function(){this.forms=new t,i.channel("dashboard").reply("get:forms",this.getForms,this),this.forms.fetch({success:function(e){i.channel("dashboard").trigger("fetch:forms",e)}})},getForms:function(){return this.forms}})}),n("models/oauthModel",[],function(){return Backbone.Model.extend({defaults:{connected:null,connect_url:""},url:function(){return ajaxurl+"?action=nf_oauth"},initialize:function(){},parse:function(e,t){return e.data}})}),n("controllers/oauthController",["models/oauthModel"],function(e){return Marionette.Object.extend({initialize:function(){this.oauth=new e,i.channel("dashboard").reply("get:oauth",this.getOAuth,this),i.channel("dashboard").reply("disconnect:oauth",this.disconnect,this),i.channel("dashboard").reply("oauth:learn-more",this.learnMoreModal,this),this.initOAuth()},getOAuth:function(){return this.oauth},initOAuth:function(){this.oauth.fetch({success:function(e){i.channel("dashboard").trigger("fetch:oauth")}})},disconnect:function(){var e=this;new jBox("Confirm",{width:750,content:nfi18n.oauthDisconnectContent,confirmButton:nfi18n.oauthDisconnectConfirm,cancelButton:nfi18n.oauthDisconnectCancel,closeOnConfirm:!0,confirm:function(){jQuery.ajax({type:"POST",url:ajaxurl+"?action=nf_oauth_disconnect",success:function(t){console.log(t),e.initOAuth()}})}}).open()},learnMoreModal:function(){new jBox("Modal",{width:500,content:nfi18n.oauthLearnMoreContent}).open()}})}),n("models/serviceModel",[],function(){return Backbone.Model.extend({defaults:{objectType:"service",name:"",slug:"",installPath:"",description:"",enabled:null,infoLink:null,serviceLink:null,is_installing:!1,classes:""},url:function(){return ajaxurl+"?action=nf_service_"+this.get("slug")},initialize:function(){this.get("slug")==serviceSuccess&&this.get("successMessage")&&new jBox("Modal",{width:300,addClass:"dashboard-modal",overlay:!0,closeOnClick:!0,content:this.get("successMessage"),title:this.get("successMessageTitle"),closeButton:"box"}).open();var e=this;i.channel("dashboard").reply("install:service:"+this.get("slug"),function(){if(e.get("serviceLink")&&e.get("serviceLink").href){var t=e.get("serviceLink").href;new jBox("Modal",{width:300,addClass:"dashboard-modal",overlay:!0,closeOnClick:"body",content:nfi18n.serviceRedirect}).open();var n=i.channel("dashboard").request("get:oauth");if(n.get("connected"))window.location=t;else{if(e.get("connect_url"))return window.location=e.get("connect_url")+"&redirect="+t;window.location=n.get("connect_url")+"&redirect="+t}}})},save:function(){var e=this;jQuery.ajax({type:"POST",url:this.url(),data:this.toJSON()}).done(function(t){var n=JSON.parse(t);void 0!==n.error&&(alert(nfi18n.serviceUpdateError+" "+n.error),e.set("enabled",!e.get("enabled"))),i.channel("dashboard").trigger("save:service-"+e.get("slug"))})}})}),n("models/serviceCollection",["models/serviceModel"],function(e){return Backbone.Collection.extend({model:e,comparator:"name",url:function(){return ajaxurl+"?action=nf_services"},initialize:function(){},parse:function(e,t){return e.data}})}),n("controllers/servicesController",["models/serviceCollection"],function(e){return Marionette.Object.extend({initialize:function(){this.services=new e,i.channel("dashboard").reply("install:service",this.installService,this),i.channel("dashboard").reply("get:services",this.getServices,this),this.fetchServices()},getServices:function(){return this.services},fetchServices:function(e){this.services.fetch({success:function(t){e&&e(t),i.channel("dashboard").trigger("fetch:services")}})},installService:function(e){var t=this;if(!(e instanceof Backbone.Model))var e=this.services.find(function(t){return e==t.get("slug")});e.set("is_installing",!0);var n=e.get("slug"),s=e.get("installPath");jQuery.post(ajaxurl,{action:"nf_services_install",plugin:n,install_path:s},function(e){t.fetchServices(function(){i.channel("dashboard").request("install:service:"+n)})})}})}),n("views/widgets/forms/formsFilter",[],function(){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-filter",ui:{input:"input"},events:{"keyup @ui.input":"updateFilter"},initialize:function(){this.listenTo(i.channel("widget-forms"),"change:content",this.clearFilter)},updateFilter:function(){var e=this.getUI("input").val();i.channel("widget-forms").trigger("update:filter",e)},clearFilter:function(){this.getUI("input").val("")},updatePlaceholder:function(e){this.getUI("input").attr("placeholder",e)}})}),n("views/widgets/forms/formsTableRow",[],function(){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-table-row",tagName:"tr",replaceElement:!0,ui:{delete:".delete",duplicate:".duplicate",edit:".nf-item-edit"},events:{"click @ui.delete":function(){i.channel("dashboard").trigger("forms:delete",this)},"click @ui.duplicate":function(){i.channel("dashboard").trigger("forms:duplicate",this)},"click @ui.edit":function(e){this.$el.toggleClass("show-actions").siblings().removeClass("show-actions")}},templateContext:function(){var e=this.model;return{created_at:moment(e.get("created_at")).format("MM/DD/YY h:mm A")}}})}),n("views/widgets/forms/formsTableEmpty",[],function(){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-table-empty",tagName:"tr"})}),n("views/widgets/forms/formsTableBody",["views/widgets/forms/formsTableRow","views/widgets/forms/formsTableEmpty"],function(e,t){return Marionette.CollectionView.extend({childView:e,emptyView:t,className:"forms-collection",tagName:"tbody",initialize:function(){this.listenTo(i.channel("widget-forms"),"update:filter",this.updateFilter)},updateFilter:function(e){this.setFilter(function(t,n,i){return 0<=t.get("title").toLowerCase().indexOf(e.toLowerCase())})}})}),n("views/widgets/forms/formsTableLoading",[],function(){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-table-loading",tagName:"tr"})}),n("views/widgets/forms/formsTable",["views/widgets/forms/formsTableBody","views/widgets/forms/formsTableLoading","models/formCollection"],function(e,t,n){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-table",className:"nf-table-display",tagName:"table",initialize:function(){var t=this;this.listenTo(i.channel("dashboard"),"fetch:forms",function(n){t.showChildView("body",new e({collection:n}))})},regions:{body:{el:"tbody",replaceElement:!0}},ui:{sortable:".sortable",body:"tbody",action2:".action2",more:".more",less:".less"},onRender:function(){this.getUI("less").hide();var n=i.channel("dashboard").request("get:forms");void 0===n?this.showChildView("body",new t):this.showChildView("body",new e({collection:n})),this.maybeHideMoreButton()},events:{"click @ui.sortable":"sortFormsTable","click @ui.more":"showMore","click @ui.less":"showLess"},sortFormsTable:function(e){this.getUI("sortable").removeClass("sorted-asc"),this.getUI("sortable").removeClass("sorted-desc");var t=jQuery(e.target).data("sort"),n=jQuery(e.target).data("reverse")||0;n?(jQuery(e.target).addClass("sorted-desc"),jQuery(e.target).removeClass("sorted-asc")):(jQuery(e.target).addClass("sorted-asc"),jQuery(e.target).removeClass("sorted-desc"));var i=this.getChildView("body").collection;i.comparator=function(e,i){return name1=e.get(t).toLowerCase(),name2=i.get(t).toLowerCase(),name1<name2?ret=-1:name1>name2?ret=1:ret=0,n&&(ret=-ret),ret},i.sort(),n?(i.models.reverse(),jQuery(e.target).data("reverse",0)):jQuery(e.target).data("reverse",1)},showMore:function(){this.getUI("more").hide(),this.getUI("less").show(),this.getUI("body").addClass("more")},showLess:function(){this.getUI("less").hide(),this.getUI("more").show(),this.getUI("body").removeClass("more")},maybeHideMoreButton:function(){void 0!==this.collection&&10<this.collection.length||this.getUI("action2").hide()}})}),n("models/formTemplateModel",[],function(){return Backbone.Model.extend({defaults:{objectType:"template",id:"none",title:"unknown",type:""},initialize:function(){this.set("desc",this.get("template-desc")),this.set("modal-content",this.get("modal-content")),this.set("modal-title",this.get("modal-title"))}})}),n("models/formTemplateCollection",["models/formTemplateModel"],function(e){return Backbone.Collection.extend({model:e,tmpNum:1,url:function(){return ajaxurl+"?action=nf_new_form_templates"},parse:function(e,t){return e.data},initialize:function(){this.fetch({success:function(e){},error:function(e){}})}})}),n("views/widgets/forms/newFormTemplate",[],function(){return Marionette.View.extend({template:"#tmpl-nf-widget-forms-template",events:{click:"maybeOpenModal"},maybeOpenModal:function(e){if(e.preventDefault(),"ad"==this.model.get("type")){new jBox("Modal",{width:450,title:this.model.get("modal-title"),content:this.model.get("modal-content"),closeButton:"box",blockScroll:!0}).open()}else{var t={batch_type:"import_form_template",loadingText:"Importing...",extraData:{template:this.model.get("id")},onCompleteCallback:function(e){if(void 0===e.form_id)return!1;window.location.href=nfAdmin.builderURL+e.form_id}};new NinjaBatchProcessor(t)}}})}),n("views/widgets/forms/newFormGrid",["models/formTemplateCollection","views/widgets/forms/newFormTemplate"],function(e,t){return Marionette.CollectionView.extend({tagName:"div",className:"template-list",collection:new e,childView:t,initialize:function(){this.listenTo(i.channel("widget-forms"),"update:filter",this.updateFilter)},updateFilter:function(e){this.setFilter(function(t,n,i){return 0<=t.get("title").toLowerCase().indexOf(e.toLowerCase())})}})}),n("views/widgets/forms/forms",["views/widgets/forms/formsFilter","views/widgets/forms/formsTable","views/widgets/forms/newFormGrid"],function(e,t,n){return Marionette.View.extend({template:"#tmpl-nf-widget-forms",regions:{filter:".filter",content:".content"},ui:{add:".add",cancel:".cancel"},initialize:function(){},onRender:function(){this.getUI("cancel").hide(),this.showChildView("filter",new e),"#new-form"==window.location.hash?(this.getUI("add").hide(),this.getUI("cancel").show(),this.showChildView("content",new n)):this.showChildView("content",new t)},events:{"click @ui.add":"showNewFormGrid","click @ui.cancel":"showFormsTable"},showNewFormGrid:function(){window.location.hash="new-form",this.showChildView("content",new n),i.channel("widget-forms").trigger("change:content"),this.getUI("add").hide(),this.getUI("cancel").show(),this.getChildView("filter").updatePlaceholder("Search Templates")},showFormsTable:function(){window.location.hash="forms",this.showChildView("content",new t),i.channel("widget-forms").trigger("change:content"),this.getUI("cancel").hide(),this.getUI("add").show(),this.getChildView("filter").updatePlaceholder("Search Forms")}})}),n("views/sections/widgets.js",["views/widgets/forms/forms"],function(e){return Marionette.View.extend({template:"#tmpl-nf-widgets",regions:{forms:".widget-forms"},onRender:function(){this.showChildView("forms",new e)}})}),n("views/services/service",[],function(){return Marionette.View.extend({template:"#tmpl-nf-service",className:function(){return"nf-extend nf-box "+this.model.get("classes")},ui:{install:".js--install",learnMore:".js--learn-more",enabled:".nf-toggle.setting",toggleEnable:".nf-toggle + label"},events:{"click @ui.install":function(){i.channel("dashboard").request("install:service",this.model)},"click @ui.learnMore":function(){this.showLearnMore()},"click @ui.toggleEnable":function(){if(null==this.model.get("enabled")&&this.model.get("link"))return window.location=this.model.get("link"),this.render();this.model.set("enabled",!this.model.get("enabled")),this.model.save("enabled"),this.render()}},initialize:function(e){this.updateOAuth(),this.listenTo(this.model,"change",this.render),i.channel("dashboard").reply("more:service:"+this.model.get("slug"),this.showLearnMore,this),this.listenTo(i.channel("dashboard"),"fetch:oauth",this.updateOAuth),this.listenTo(i.channel("dashboard"),"save:service-"+this.model.get("slug"),this.render)},showLearnMore:function(){var e=new jBox("Modal",{width:750,title:this.model.get("learnMoreTitle")||this.model.get("name"),content:this.model.get("learnMore"),closeButton:"box",blockScroll:!0});e.open(),i.channel("dashboard").reply("service:"+this.model.get("slug")+":modal",function(){return e})},updateOAuth:function(){var e=i.channel("dashboard").request("get:oauth");this.connected=e.get("connected"),this.render()},templateContext:function(){return{is_connected:this.connected}}})}),n("views/services/services",["views/services/service","models/serviceCollection"],function(e,t){return Marionette.CollectionView.extend({collection:new t,className:"wrap apps-container",childView:e,initialize:function(){this.updateCollection(),this.listenTo(i.channel("dashboard"),"fetch:services",this.updateCollection)},updateCollection:function(){this.collection=i.channel("dashboard").request("get:services"),this.render()}})}),n("views/sections/services.js",["views/services/services"],function(e){return Marionette.View.extend({template:"#tmpl-nf-services",regions:{services:".services"},onRender:function(){this.showChildView("services",new e)}})}),n("views/sections/apps.js",[],function(){return Marionette.View.extend({template:"#tmpl-nf-apps"})}),n("views/sections/memberships.js",[],function(){return Marionette.View.extend({template:"#tmpl-nf-memberships"})}),n("views/oauth.js",["models/oauthModel"],function(e){return Marionette.View.extend({model:new e,template:"#tmpl-nf-notices-oauth",className:"nf-notices--oauth",ui:{disconnect:".js--disconnect"},initialize:function(e){this.listenTo(i.channel("dashboard"),"fetch:oauth",this.updateModel)},updateModel:function(){this.model=i.channel("dashboard").request("get:oauth"),this.render()},events:{"click @ui.disconnect":function(){i.channel("dashboard").request("disconnect:oauth")}}})}),n("models/promotionModel",[],function(){return Backbone.Model.extend({defaults:{id:"",content:""},initialize:function(){}})}),n("views/promotion.js",["models/promotionModel"],function(e){return Marionette.View.extend({model:null,template:"#tmpl-nf-promotion",className:"nf-promotion",initialize:function(){var t=nfPromotions[Math.floor(Math.random()*nfPromotions.length)];this.model=new e(t)}})}),n("views/sections/requiredUpdates.js",[],function(){return Marionette.View.extend({template:"#tmpl-nf-requiredUpdates",updates:[],currentUpdate:0,totalUpdates:-1,updatesRemaining:-1,ui:{requiredUpdates:".nf-required-update"},onRender:function(){this.getRequiredUpdates()},setButtonClickEvent:function(){var e=this;jQuery("#nf-required-updates-btn").off("click").on("click",function(t){t.preventDefault(),e.doRequiredUpdates(),jQuery(this).hide()})},getRequiredUpdates:function(){var e=this;jQuery.get(ajaxurl,{action:"nf_required_update"}).then(function(t){var n=JSON.parse(t);0===n.errors.length&&(e.totalUpdates=n.data.updates.length,e.updates=n.data.updates,0<e.updates.length?(e.requiredUpdates=e.updates.length,e.constructUpdateTable(),e.setButtonClickEvent()):window.location=window.location.origin+window.location.pathname+window.location.search)})},constructUpdateTable:function(){var e=this,t=document.getElementById("nf-upgrades-table"),n=t.getElementsByTagName("thead")[0],i=document.createElement("tr"),s=document.createElement("th");s.innerHTML="Update",s.classList.add("nf-update-name-cell");var o=document.createElement("th");o.innerHTML="Progress",o.classList.add("nf-update-progress-cell"),i.appendChild(s),i.appendChild(o),n.appendChild(i);var r=t.getElementsByTagName("tbody")[0];jQuery.each(this.updates,function(t,n){var i=document.createElement("tr"),s=document.createElement("td");s.innerHTML=n.nicename;var o=document.createElement("td"),a=document.createElement("div");a.id="update-progress-"+t;var l=e.createNewProgressBar(t);a.appendChild(l),o.appendChild(a),i.appendChild(s),i.appendChild(o),r.appendChild(i)}),document.getElementById("nf-required-updates-btn").style.display="block"},doRequiredUpdates:function(){window.location.hash="#requiredUpdates";var e=this;jQuery("#nf-required-updates-btn").addClass("disabled").attr("disabled","disabled"),jQuery.post(ajaxurl,{action:"nf_required_update",security:nfAdmin.updateNonce}).then(function(t){var n=JSON.parse(t);n.updatesRemaining>0?(e.updatesRemaining!==n.updatesRemaining&&n.currentStep===n.stepsTotal?(e.finishUpdate(e.currentUpdate),e.updatesRemaining=n.updatesRemaining):(e.showProgressBars(n),e.updatesRemaining=n.updatesRemaining),e.doRequiredUpdates()):(e.finishUpdate(e.currentUpdate),nfAdmin.requiredUpdates=0,jQuery("#nf-required-updates-btn").removeClass("disabled").removeAttr("disabled").val("Go To Dashboard").off("click").on("click",function(e){e.preventDefault(),window.location=window.location.origin+window.location.pathname+window.location.search}).show(),console.log("UPDATES DONE"))})},showProgressBars:function(e){var t=this.totalUpdates-e.updatesRemaining,n=e.currentStep,i=e.stepsTotal,s=document.getElementById("nf_progressBar_"+t);null==s&&(this.currentUpdate+=1,1===this.currentUpdate&&-1===this.totalUpdates&&(this.totalUpdates=t),s=this.createNewProgressBar(t)),this.incrementProgress(t,n,i)},createNewProgressBar:function(e){var t=document.createElement("div");t.id="nf_progressBar_"+e,t.classList.add("jBox-content"),t.style.display="none";var n=document.createElement("div");n.classList.add("nf-progress-bar");var i=document.createElement("div");return i.id="nf-progress-bar-slider-"+e,i.classList.add("nf-progress-bar-slider"),n.appendChild(i),t.appendChild(n),t},incrementProgress:function(e,t,n){document.getElementById("nf_progressBar_"+e).style.display="block";var i=document.getElementById("nf-progress-bar-slider-"+e),s=Number(t)/Number(n)*100;s>i.offsetWidth/i.parentElement.offsetWidth*100&&this.setProgress(e,s)},setProgress:function(e,t){document.getElementById("nf-progress-bar-slider-"+e).style.width=t+"%",100<=t&&this.finishUpdate(e)},finishUpdate:function(e){var t=document.getElementById("nf_progressBar_"+e),n=t.parentNode;n.removeChild(t);var i=document.createElement("span");i.classList.add("dashicons"),i.classList.add("dashicons-yes"),n.appendChild(i),this.currentUpdate=this.currentUpdate+1}})}),n("views/dashboardView",["views/sections/widgets.js","views/sections/services.js","views/sections/apps.js","views/sections/memberships.js","views/oauth.js","views/promotion.js","views/sections/requiredUpdates.js"],function(e,t,n,s,o,r,a){return Marionette.View.extend({template:"#tmpl-nf-dashboard",currentView:"widgets",regions:{notices:".notices",promotions:".promotions",content:".content"},events:{"click .widgets a":function(t){"1"!=nfAdmin.requiredUpdates&&(this.showChildView("content",new e),jQuery("."+this.currentView).find("a").removeClass("active"),t.target.classList.add("active"),this.currentView="widgets")},"click .services a":function(e){"1"!=nfAdmin.requiredUpdates&&(this.showChildView("content",new t),jQuery("."+this.currentView).find("a").removeClass("active"),e.target.classList.add("active"),this.currentView="services")},"click .apps a":function(e){"1"!=nfAdmin.requiredUpdates&&(this.showChildView("content",new n),jQuery("."+this.currentView).find("a").removeClass("active"),e.target.classList.add("active"),this.currentView="apps")},"click .memberships a":function(e){"1"!=nfAdmin.requiredUpdates&&(this.showChildView("content",new s),jQuery("."+this.currentView).find("a").removeClass("active"),e.target.classList.add("active"),this.currentView="memberships")}},initialize:function(){switch("1"===nfAdmin.requiredUpdates?window.location.hash="#requiredUpdates":"#requiredUpdates"===window.location.hash&&(window.location.hash=""),window.location.hash){case"#apps":this.currentView="apps";break;case"#services":this.currentView="services";break;case"#memberships":this.currentView="memberships";break;case"#requiredUpdates":this.currentView="requiredUpdates";break;case"#widgets":default:this.currentView="widgets"}i.channel("dashboard").reply("show:widgets",function(){"1"!=nfAdmin.requiredUpdates&&(this.showChildView("content",new e),jQuery("nav.sections a.active").removeClass("active"),jQuery("nav.sections .widgets a").addClass("active"),this.currentView="widgets")},this),i.channel("dashboard").reply("show:services",function(){"1"!=nfAdmin.requiredUpdates&&(this.showChildView("content",new t),jQuery("nav.sections a.active").removeClass("active"),jQuery("nav.sections .services a").addClass("active"),this.currentView="services")},this),i.channel("dashboard").reply("show:apps",function(){"1"!=nfAdmin.requiredUpdates&&(this.showChildView("content",new n),jQuery("nav.sections a.active").removeClass("active"),jQuery("nav.sections .apps a").addClass("active"),this.currentView="apps")},this)},onRender:function(){switch(useServices&&this.showChildView("notices",new o),useServices&&"1"!==nfAdmin.requiredUpdates&&this.showChildView("promotions",new r),"0"===nfAdmin.requiredUpdates&&"#requiredUpdates"===window.location.hash&&(window.location.hash=""),window.location.hash){case"#apps":var i=new n;break;case"#memberships":var i=new s;break;case"#services":var i=new t;break;case"#requiredUpdates":var i=new a;break;case"#widgets":default:var i=new e}if(this.showChildView("content",i),"1"==nfAdmin.showOptin){var l=new jBox("Modal",{closeOnEsc:!1,closeOnClick:!1,width:400}),d=document.createElement("div");d.id="optin-modal-title";var c=document.createElement("h2");c.innerHTML="Help make Ninja Forms better!",d.appendChild(c);var u=document.createElement("div");u.classList.add("message"),u.style.padding="0px 20px 20px 20px",u.innerHTML=nfi18n.optinContent;var h=document.createElement("p");h.style.paddingBottom="10px";var m=document.createElement("input");m.id="optin-send-email",m.setAttribute("type","checkbox"),m.style.margin="7px";var p=document.createElement("label");p.setAttribute("for","optin-send-email"),p.innerHTML=nfi18n.optinYesplease,h.appendChild(m),h.appendChild(p),u.appendChild(h),h=document.createElement("p"),h.id="optin-block",h.style.padding="0px 5px 20px 5px",h.style.display="none";var f=document.createElement("input");f.id="optin-email-address",f.setAttribute("type","text"),f.setAttribute("value",nfAdmin.currentUserEmail),f.style.width="100%",f.style.fontSize="16px",h.appendChild(f),u.appendChild(h);var w=document.createElement("span");w.id="optin-spinner",w.classList.add("spinner"),w.style.display="none",u.appendChild(w);var g=document.createElement("div");g.id="optin-buttons",g.classList.add("buttons");var v=document.createElement("div");v.id="optout",v.classList.add("nf-button","secondary"),v.innerHTML=nfi18n.optinSecondary,g.appendChild(v);var b=document.createElement("div");b.id="optin",b.classList.add("nf-button","primary","pull-right"),b.innerHTML=nfi18n.optinPrimary,g.appendChild(b),u.appendChild(g);var y=document.createElement("h2");y.innerHTML=nfi18n.optinAwesome;var C=document.createElement("div");C.id="optin-thankyou",C.classList.add("message"),C.style.padding="20px",C.innerHTML=nfi18n.optinThanks,l.setContent(document.createElement("div").appendChild(u).innerHTML),l.setTitle(document.createElement("div").appendChild(d).innerHTML),l.open(),jQuery("#optin-send-email").click(function(e){jQuery(this).is(":checked")?jQuery("#optin-block").show():jQuery("#optin-block").hide()}),jQuery("#optin").click(function(e){var t;jQuery("#optin-send-email").attr("checked")?(t=1,userEmail=jQuery("#optin-email-address").val()):(t=0,userEmail=""),jQuery("#optin").unbind("click"),jQuery("#optout").unbind("click");var n=jQuery("#optin").width();jQuery("#optin").html('<span class="dashicons dashicons-update dashicons-update-spin"></span>'),jQuery("#optin").width(n),jQuery.post(ajaxurl,{action:"nf_optin",ninja_forms_opt_in:1,send_email:t,user_email:userEmail},function(e){l.setTitle(document.createElement("div").appendChild(y).innerHTML),l.setContent(document.createElement("div").appendChild(C).innerHTML),setTimeout(function(){l.close()},2e3)})}),jQuery("#optout").click(function(e){jQuery("#optin").unbind("click"),jQuery("#optout").unbind("click");var t=jQuery("#optout").width();jQuery("#optout").html('<span class="dashicons dashicons-update dashicons-update-spin"></span>'),jQuery("#optout").width(t),jQuery.post(ajaxurl,{action:"nf_optin",ninja_forms_opt_in:0},function(e){l.close()})})}if(void 0!==nfAdmin.formTelemetry&&1==nfAdmin.formTelemetry){var j={action:"nf_form_telemetry",security:nfAdmin.ajaxNonce};jQuery.post(ajaxurl,j)}},templateContext:function(){var e=this;return{renderNav:function(){var t=document.createElement("div");return _.each(nfDashItems,function(n){var i=document.createElement("li"),s=document.createElement("a");s.href="#"+n.slug,
|
2 |
+
e.currentView==n.slug&&s.classList.add("active"),s.innerHTML=n.niceName,i.classList.add(n.slug),i.appendChild(s),t.appendChild(i)}),t.innerHTML}}}})});var i=Backbone.Radio;useServices||(nfDashItems=nfDashItems.filter(function(e){return"services"!==e.slug})),jQuery(document).ready(function(e){t(["controllers/formsController","controllers/oauthController","controllers/servicesController","views/dashboardView"],function(t,n,i,s){(new(Marionette.Application.extend({region:"#ninja-forms-dashboard",controllers:{},initialize:function(e){var t=this;Marionette.Renderer.render=function(e,n){var e=t.template(e);return e(n)}},onStart:function(){this.showView(new s),this.controllers.forms=new t,useServices&&(this.controllers.oauth=new n),useServices&&(this.controllers.services=new i)},template:function(t){return _.template(e(t).html(),{evaluate:/<#([\s\S]+?)#>/g,interpolate:/\{\{\{([\s\S]+?)\}\}\}/g,escape:/\{\{([^\}]+?)\}\}(?!\})/g,variable:"data"})}}))).start()})}),jQuery('a[href="admin.php?page=ninja-forms#new-form"]').on("click",function(e){e.preventDefault(),"1"!==nfAdmin.requiredUpdates&&(window.location.hash="new-form",i.channel("dashboard").request("show:widgets"),i.channel("widget-forms").request("show:newFormsGrid"))}),jQuery('a[href="admin.php?page=ninja-forms#apps"]').on("click",function(e){e.preventDefault(),"1"!==nfAdmin.requiredUpdates&&(window.location.hash="apps",i.channel("dashboard").request("show:apps"))}),jQuery('a[href="admin.php?page=ninja-forms"]').on("click",function(e){e.preventDefault(),"1"!==nfAdmin.requiredUpdates&&(window.location.hash="forms",i.channel("dashboard").request("show:widgets"),i.channel("widget-forms").request("show:formsTable"))}),jQuery(window).on("hashchange",function(){var e=window.location.hash.substr(1);i.channel("dashboard").request("show:"+e)}),n("main",function(){})}();
|
3 |
//# sourceMappingURL=dashboard.min.js.map
|
assets/js/min/dashboard.min.js.map
CHANGED
@@ -1 +1 @@
|
|
1 |
-
{"version":3,"names":[],"mappings":"","sources":["views/widgets/forms/newFormTemplate.js"],"sourcesContent":["!function(){var e,t,n;!function(i){function o(e,t){return y.call(e,t)}function s(e,t){var n,i,o,s,r,a,l,c,d,u,h,m=t&&t.split(\"/\"),f=v.map,p=f&&f[\"*\"]||{};if(e&&\".\"===e.charAt(0))if(t){for(e=e.split(\"/\"),r=e.length-1,v.nodeIdCompat&&j.test(e[r])&&(e[r]=e[r].replace(j,\"\")),e=m.slice(0,m.length-1).concat(e),d=0;d<e.length;d+=1)if(\".\"===(h=e[d]))e.splice(d,1),d-=1;else if(\"..\"===h){if(1===d&&(\"..\"===e[2]||\"..\"===e[0]))break;d>0&&(e.splice(d-1,2),d-=2)}e=e.join(\"/\")}else 0===e.indexOf(\"./\")&&(e=e.substring(2));if((m||p)&&f){for(n=e.split(\"/\"),d=n.length;d>0;d-=1){if(i=n.slice(0,d).join(\"/\"),m)for(u=m.length;u>0;u-=1)if((o=f[m.slice(0,u).join(\"/\")])&&(o=o[i])){s=o,a=d;break}if(s)break;!l&&p&&p[i]&&(l=p[i],c=d)}!s&&l&&(s=l,a=c),s&&(n.splice(0,a,s),e=n.join(\"/\"))}return e}function r(e,t){return function(){var n=C.call(arguments,0);return\"string\"!=typeof n[0]&&1===n.length&&n.push(null),m.apply(i,n.concat([e,t]))}}function a(e){return function(t){return s(t,e)}}function l(e){return function(t){w[e]=t}}function c(e){if(o(g,e)){var t=g[e];delete g[e],b[e]=!0,h.apply(i,t)}if(!o(w,e)&&!o(b,e))throw new Error(\"No \"+e);return w[e]}function d(e){var t,n=e?e.indexOf(\"!\"):-1;return n>-1&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function u(e){return function(){return v&&v.config&&v.config[e]||{}}}var h,m,f,p,w={},g={},v={},b={},y=Object.prototype.hasOwnProperty,C=[].slice,j=/\\.js$/;f=function(e,t){var n,i=d(e),o=i[0];return e=i[1],o&&(o=s(o,t),n=c(o)),o?e=n&&n.normalize?n.normalize(e,a(t)):s(e,t):(e=s(e,t),i=d(e),o=i[0],e=i[1],o&&(n=c(o))),{f:o?o+\"!\"+e:e,n:e,pr:o,p:n}},p={require:function(e){return r(e)},exports:function(e){var t=w[e];return void 0!==t?t:w[e]={}},module:function(e){return{id:e,uri:\"\",exports:w[e],config:u(e)}}},h=function(e,t,n,s){var a,d,u,h,m,v,y=[],C=typeof n;if(s=s||e,\"undefined\"===C||\"function\"===C){for(t=!t.length&&n.length?[\"require\",\"exports\",\"module\"]:t,m=0;m<t.length;m+=1)if(h=f(t[m],s),\"require\"===(d=h.f))y[m]=p.require(e);else if(\"exports\"===d)y[m]=p.exports(e),v=!0;else if(\"module\"===d)a=y[m]=p.module(e);else if(o(w,d)||o(g,d)||o(b,d))y[m]=c(d);else{if(!h.p)throw new Error(e+\" missing \"+d);h.p.load(h.n,r(s,!0),l(d),{}),y[m]=w[d]}u=n?n.apply(w[e],y):void 0,e&&(a&&a.exports!==i&&a.exports!==w[e]?w[e]=a.exports:u===i&&v||(w[e]=u))}else e&&(w[e]=n)},e=t=m=function(e,t,n,o,s){if(\"string\"==typeof e)return p[e]?p[e](t):c(f(e,t).f);if(!e.splice){if(v=e,v.deps&&m(v.deps,v.callback),!t)return;t.splice?(e=t,t=n,n=null):e=i}return t=t||function(){},\"function\"==typeof n&&(n=o,o=s),o?h(i,e,t,n):setTimeout(function(){h(i,e,t,n)},4),m},m.config=function(e){return m(e)},e._defined=w,n=function(e,t,n){if(\"string\"!=typeof e)throw new Error(\"See almond README: incorrect module build, no module name\");t.splice||(n=t,t=[]),o(w,e)||o(g,e)||(g[e]=[e,t,n])},n.amd={jQuery:!0}}(),n(\"../../assets/js/lib/almond\",function(){}),n(\"models/formModel\",[],function(){return Backbone.Model.extend({defaults:{objectType:\"form\",id:0,title:\"unknown\",created_at:\"unknown\"},url:function(){return ajaxurl+\"?action=nf_forms&form_id=\"+this.get(\"id\")},initialize:function(){this.set(\"id\",Number(this.get(\"id\"))),this.get(\"id\")&&this.initShortcode(this.get(\"id\")),this.get(\"title\")&&this.set(\"title\",this.get(\"title\").replace(/<\\/?[^>]+(>|$)/g,\"\"))},initShortcode:function(e){var t=\"[ninja_form id=\"+e+\"]\";this.set(\"shortcode\",t)},destroy:function(){var e=this;jQuery.ajax({type:\"POST\",url:ajaxurl+\"?action=nf_forms&method_override=delete&form_id=\"+this.get(\"id\"),success:function(t){var t=JSON.parse(t);e.collection.remove(e)}})}})}),n(\"models/formCollection\",[\"models/formModel\"],function(e){return Backbone.Collection.extend({model:e,comparator:\"title\",tmpNum:1,url:function(){return ajaxurl+\"?action=nf_forms\"},initialize:function(){this.newIDs=[],this.baseUrl=window.location.href.split(\"?\")[0],this.listenTo(i.channel(\"dashboard\"),\"forms:delete\",this.modalConfirm),this.listenTo(i.channel(\"dashboard\"),\"forms:duplicate\",this.duplicate),this.modal=new jBox(\"Modal\",{width:400,addClass:\"dashboard-modal\",overlay:!0,closeOnClick:\"body\"})},parse:function(e,t){return e.data},modalConfirm:function(e){var t,n,i,o,s,r,a,l=e.model.get(\"id\"),c=e.model.get(\"title\");n=document.createElement(\"div\"),n.style.paddingRight=\"20px\",n.style.paddingLeft=\"20px\",n.style.paddingBottom=\"20px\",i=document.createElement(\"p\"),o=document.createElement(\"em\"),s=document.createElement(\"div\"),r=document.createElement(\"button\"),a=document.createElement(\"div\"),n.classList.add(\"message\"),o.innerHTML=c,i.innerHTML+=nfi18n.deleteWarningA+\" (<strong>\"+c+\"</strong>). \"+nfi18n.deleteWarningB,i.appendChild(document.createElement(\"br\")),i.appendChild(document.createElement(\"br\"));var d=document.createElement(\"a\");d.href=this.baseUrl+\"?page=nf-import-export&exportFormId=\"+l,d.innerHTML='<i class=\"fa fa-download\" style=\"padding:5px;\"></i>'+nfi18n.deleteXForm,d.target=\"_blank\",i.appendChild(d),i.appendChild(document.createElement(\"br\"));var u=document.createElement(\"a\");u.href=this.baseUrl+\"?page=nf-processing&action=download_all_subs&form_id=\"+l+\"&redirect=\"+encodeURIComponent(this.baseUrl.replace(\"admin.php\",\"edit.php\")+\"?post_status=all&post_type=nf_sub&form_id=\"+l),u.target=\"_blank\",u.innerHTML='<i class=\"fa fa-download\" style=\"padding:5px;\"></i>'+nfi18n.deleteXSubs,i.appendChild(u),i.appendChild(document.createElement(\"br\")),n.appendChild(i);var h=document.createElement(\"label\");h.for=\"confirmDeleteFormInput\",h.innerHTML=nfi18n.deleteConfirmA+' <span style=\"color:red;\">DELETE</span> '+nfi18n.deleteConfirmB;var m=document.createElement(\"input\");m.type=\"text\",m.id=\"confirmDeleteFormInput\",m.style.marginTop=\"10px\",m.style.width=\"100%\",m.style.height=\"2.5em\",m.style.fontSize=\"1em\",n.appendChild(h),n.appendChild(document.createElement(\"br\")),n.appendChild(m),n.appendChild(document.createElement(\"br\")),n.appendChild(document.createElement(\"br\")),r.innerHTML=nfi18n.delete,r.classList.add(\"confirm\",\"nf-button\",\"primary\",\"pull-right\"),a.innerHTML=nfi18n.cancel,a.classList.add(\"cancel\",\"nf-button\",\"secondary\"),s.appendChild(a),s.appendChild(r),s.classList.add(\"buttons\"),n.appendChild(s),t=document.createElement(\"div\"),t.appendChild(n),this.modal.setContent(t.innerHTML),this.modal.setTitle(nfi18n.deleteTitle),this.modal.open();var f=this;this.modal.container[0].getElementsByClassName(\"cancel\")[0].addEventListener(\"click\",function(){f.modalClose()}),this.modal.container[0].getElementsByClassName(\"confirm\")[0].addEventListener(\"click\",function(t){t.preventDefault(),\"DELETE\"===document.getElementById(\"confirmDeleteFormInput\").value?f.confirmDelete(e):f.modalClose()})},modalClose:function(){this.modal.close()},confirmDelete:function(e){jQuery(e.el).removeClass(\"show-actions\"),jQuery(e.el).addClass(\"deleting\"),jQuery(e.el).animate({opacity:0,\"line-height\":0,display:\"none\"},500),console.log(e),e.model.destroy(),this.modalClose()},duplicate:function(e){var t='<div class=\"message\">Duplicating <em>'+e.model.get(\"title\")+'</em>...<div class=\"nf-loading-spinner\"></div></div>';this.modal.setContent(t),this.modal.setTitle(\"Please Wait\"),this.modal.open();var n=this;jQuery.ajax({type:\"POST\",url:ajaxurl+\"?action=nf_forms&clone_id=\"+e.model.get(\"id\"),success:function(t){var t=JSON.parse(t),i=t.data.new_form_id,o=e.model.clone();o.set({id:i,title:o.get(\"title\")+\" - copy\",created_at:new Date}),o.initShortcode(i),e.model.collection.add(o),n.modalClose()}})}})}),n(\"controllers/formsController\",[\"models/formModel\",\"models/formCollection\"],function(e,t){return Marionette.Object.extend({initialize:function(){this.forms=new t,i.channel(\"dashboard\").reply(\"get:forms\",this.getForms,this),this.forms.fetch({success:function(e){i.channel(\"dashboard\").trigger(\"fetch:forms\",e)}})},getForms:function(){return this.forms}})}),n(\"models/oauthModel\",[],function(){return Backbone.Model.extend({defaults:{connected:null,connect_url:\"\"},url:function(){return ajaxurl+\"?action=nf_oauth\"},initialize:function(){},parse:function(e,t){return e.data}})}),n(\"controllers/oauthController\",[\"models/oauthModel\"],function(e){return Marionette.Object.extend({initialize:function(){this.oauth=new e,i.channel(\"dashboard\").reply(\"get:oauth\",this.getOAuth,this),i.channel(\"dashboard\").reply(\"disconnect:oauth\",this.disconnect,this),i.channel(\"dashboard\").reply(\"oauth:learn-more\",this.learnMoreModal,this),this.initOAuth()},getOAuth:function(){return this.oauth},initOAuth:function(){this.oauth.fetch({success:function(e){i.channel(\"dashboard\").trigger(\"fetch:oauth\")}})},disconnect:function(){var e=this;new jBox(\"Confirm\",{width:750,content:nfi18n.oauthDisconnectContent,confirmButton:nfi18n.oauthDisconnectConfirm,cancelButton:nfi18n.oauthDisconnectCancel,closeOnConfirm:!0,confirm:function(){jQuery.ajax({type:\"POST\",url:ajaxurl+\"?action=nf_oauth_disconnect\",success:function(t){console.log(t),e.initOAuth()}})}}).open()},learnMoreModal:function(){new jBox(\"Modal\",{width:500,content:nfi18n.oauthLearnMoreContent}).open()}})}),n(\"models/serviceModel\",[],function(){return Backbone.Model.extend({defaults:{objectType:\"service\",name:\"\",slug:\"\",installPath:\"\",description:\"\",enabled:null,infoLink:null,serviceLink:null,is_installing:!1,classes:\"\"},url:function(){return ajaxurl+\"?action=nf_service_\"+this.get(\"slug\")},initialize:function(){this.get(\"slug\")==serviceSuccess&&this.get(\"successMessage\")&&new jBox(\"Modal\",{width:300,addClass:\"dashboard-modal\",overlay:!0,closeOnClick:!0,content:this.get(\"successMessage\"),title:this.get(\"successMessageTitle\"),closeButton:\"box\"}).open();var e=this;i.channel(\"dashboard\").reply(\"install:service:\"+this.get(\"slug\"),function(){if(e.get(\"serviceLink\")&&e.get(\"serviceLink\").href){var t=e.get(\"serviceLink\").href;new jBox(\"Modal\",{width:300,addClass:\"dashboard-modal\",overlay:!0,closeOnClick:\"body\",content:nfi18n.serviceRedirect}).open();var n=i.channel(\"dashboard\").request(\"get:oauth\");if(n.get(\"connected\"))window.location=t;else{if(e.get(\"connect_url\"))return window.location=e.get(\"connect_url\")+\"&redirect=\"+t;window.location=n.get(\"connect_url\")+\"&redirect=\"+t}}})},save:function(){var e=this;jQuery.ajax({type:\"POST\",url:this.url(),data:this.toJSON()}).done(function(t){var n=JSON.parse(t);void 0!==n.error&&(alert(nfi18n.serviceUpdateError+\" \"+n.error),e.set(\"enabled\",!e.get(\"enabled\"))),i.channel(\"dashboard\").trigger(\"save:service-\"+e.get(\"slug\"))})}})}),n(\"models/serviceCollection\",[\"models/serviceModel\"],function(e){return Backbone.Collection.extend({model:e,comparator:\"name\",url:function(){return ajaxurl+\"?action=nf_services\"},initialize:function(){},parse:function(e,t){return e.data}})}),n(\"controllers/servicesController\",[\"models/serviceCollection\"],function(e){return Marionette.Object.extend({initialize:function(){this.services=new e,i.channel(\"dashboard\").reply(\"install:service\",this.installService,this),i.channel(\"dashboard\").reply(\"get:services\",this.getServices,this),this.fetchServices()},getServices:function(){return this.services},fetchServices:function(e){this.services.fetch({success:function(t){e&&e(t),i.channel(\"dashboard\").trigger(\"fetch:services\")}})},installService:function(e){var t=this;if(!(e instanceof Backbone.Model))var e=this.services.find(function(t){return e==t.get(\"slug\")});e.set(\"is_installing\",!0);var n=e.get(\"slug\"),o=e.get(\"installPath\");jQuery.post(ajaxurl,{action:\"nf_services_install\",plugin:n,install_path:o},function(e){t.fetchServices(function(){i.channel(\"dashboard\").request(\"install:service:\"+n)})})}})}),n(\"views/widgets/forms/formsFilter\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-filter\",ui:{input:\"input\"},events:{\"keyup @ui.input\":\"updateFilter\"},initialize:function(){this.listenTo(i.channel(\"widget-forms\"),\"change:content\",this.clearFilter)},updateFilter:function(){var e=this.getUI(\"input\").val();i.channel(\"widget-forms\").trigger(\"update:filter\",e)},clearFilter:function(){this.getUI(\"input\").val(\"\")},updatePlaceholder:function(e){this.getUI(\"input\").attr(\"placeholder\",e)}})}),n(\"views/widgets/forms/formsTableRow\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-table-row\",tagName:\"tr\",replaceElement:!0,ui:{delete:\".delete\",duplicate:\".duplicate\",edit:\".nf-item-edit\"},events:{\"click @ui.delete\":function(){i.channel(\"dashboard\").trigger(\"forms:delete\",this)},\"click @ui.duplicate\":function(){i.channel(\"dashboard\").trigger(\"forms:duplicate\",this)},\"click @ui.edit\":function(e){this.$el.toggleClass(\"show-actions\").siblings().removeClass(\"show-actions\")}},templateContext:function(){var e=this.model;return{created_at:moment(e.get(\"created_at\")).format(\"MM/DD/YY h:mm A\")}}})}),n(\"views/widgets/forms/formsTableEmpty\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-table-empty\",tagName:\"tr\"})}),n(\"views/widgets/forms/formsTableBody\",[\"views/widgets/forms/formsTableRow\",\"views/widgets/forms/formsTableEmpty\"],function(e,t){return Marionette.CollectionView.extend({childView:e,emptyView:t,className:\"forms-collection\",tagName:\"tbody\",initialize:function(){this.listenTo(i.channel(\"widget-forms\"),\"update:filter\",this.updateFilter)},updateFilter:function(e){this.setFilter(function(t,n,i){return 0<=t.get(\"title\").toLowerCase().indexOf(e.toLowerCase())})}})}),n(\"views/widgets/forms/formsTableLoading\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-table-loading\",tagName:\"tr\"})}),n(\"views/widgets/forms/formsTable\",[\"views/widgets/forms/formsTableBody\",\"views/widgets/forms/formsTableLoading\",\"models/formCollection\"],function(e,t,n){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-table\",className:\"nf-table-display\",tagName:\"table\",initialize:function(){var t=this;this.listenTo(i.channel(\"dashboard\"),\"fetch:forms\",function(n){t.showChildView(\"body\",new e({collection:n}))})},regions:{body:{el:\"tbody\",replaceElement:!0}},ui:{sortable:\".sortable\",body:\"tbody\",action2:\".action2\",more:\".more\",less:\".less\"},onRender:function(){this.getUI(\"less\").hide();var n=i.channel(\"dashboard\").request(\"get:forms\");void 0===n?this.showChildView(\"body\",new t):this.showChildView(\"body\",new e({collection:n})),this.maybeHideMoreButton()},events:{\"click @ui.sortable\":\"sortFormsTable\",\"click @ui.more\":\"showMore\",\"click @ui.less\":\"showLess\"},sortFormsTable:function(e){this.getUI(\"sortable\").removeClass(\"sorted-asc\"),this.getUI(\"sortable\").removeClass(\"sorted-desc\");var t=jQuery(e.target).data(\"sort\"),n=jQuery(e.target).data(\"reverse\")||0;n?(jQuery(e.target).addClass(\"sorted-desc\"),jQuery(e.target).removeClass(\"sorted-asc\")):(jQuery(e.target).addClass(\"sorted-asc\"),jQuery(e.target).removeClass(\"sorted-desc\"));var i=this.getChildView(\"body\").collection;i.comparator=function(e,i){return name1=e.get(t).toLowerCase(),name2=i.get(t).toLowerCase(),name1<name2?ret=-1:name1>name2?ret=1:ret=0,n&&(ret=-ret),ret},i.sort(),n?(i.models.reverse(),jQuery(e.target).data(\"reverse\",0)):jQuery(e.target).data(\"reverse\",1)},showMore:function(){this.getUI(\"more\").hide(),this.getUI(\"less\").show(),this.getUI(\"body\").addClass(\"more\")},showLess:function(){this.getUI(\"less\").hide(),this.getUI(\"more\").show(),this.getUI(\"body\").removeClass(\"more\")},maybeHideMoreButton:function(){void 0!==this.collection&&10<this.collection.length||this.getUI(\"action2\").hide()}})}),n(\"models/formTemplateModel\",[],function(){return Backbone.Model.extend({defaults:{objectType:\"template\",id:\"none\",title:\"unknown\",type:\"\"},initialize:function(){this.set(\"desc\",this.get(\"template-desc\")),this.set(\"modal-content\",this.get(\"modal-content\")),this.set(\"modal-title\",this.get(\"modal-title\"))}})}),n(\"models/formTemplateCollection\",[\"models/formTemplateModel\"],function(e){return Backbone.Collection.extend({model:e,tmpNum:1,url:function(){return ajaxurl+\"?action=nf_new_form_templates\"},parse:function(e,t){return e.data},initialize:function(){this.fetch({success:function(e){},error:function(e){}})}})}),n(\"views/widgets/forms/newFormTemplate\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-template\",events:{click:\"maybeOpenModal\"},maybeOpenModal:function(e){if(\"ad\"!=this.model.get(\"type\"))return!0;e.preventDefault(),new jBox(\"Modal\",{width:450,title:this.model.get(\"modal-title\"),content:this.model.get(\"modal-content\"),closeButton:\"box\",blockScroll:!0}).open()}})}),n(\"views/widgets/forms/newFormGrid\",[\"models/formTemplateCollection\",\"views/widgets/forms/newFormTemplate\"],function(e,t){return Marionette.CollectionView.extend({tagName:\"div\",className:\"template-list\",collection:new e,childView:t,initialize:function(){this.listenTo(i.channel(\"widget-forms\"),\"update:filter\",this.updateFilter)},updateFilter:function(e){this.setFilter(function(t,n,i){return 0<=t.get(\"title\").toLowerCase().indexOf(e.toLowerCase())})}})}),n(\"views/widgets/forms/forms\",[\"views/widgets/forms/formsFilter\",\"views/widgets/forms/formsTable\",\"views/widgets/forms/newFormGrid\"],function(e,t,n){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms\",regions:{filter:\".filter\",content:\".content\"},ui:{add:\".add\",cancel:\".cancel\"},initialize:function(){i.channel(\"widget-forms\").reply(\"show:newFormsGrid\",this.showNewFormGrid,this),i.channel(\"widget-forms\").reply(\"show:formsTable\",this.showFormsTable,this)},onRender:function(){this.getUI(\"cancel\").hide(),this.showChildView(\"filter\",new e),\"#new-form\"==window.location.hash?(this.getUI(\"add\").hide(),this.getUI(\"cancel\").show(),this.showChildView(\"content\",new n)):this.showChildView(\"content\",new t)},events:{\"click @ui.add\":\"showNewFormGrid\",\"click @ui.cancel\":\"showFormsTable\"},showNewFormGrid:function(){window.location.hash=\"new-form\",this.showChildView(\"content\",new n),i.channel(\"widget-forms\").trigger(\"change:content\"),this.getUI(\"add\").hide(),this.getUI(\"cancel\").show(),this.getChildView(\"filter\").updatePlaceholder(\"Search Templates\")},showFormsTable:function(){console.log(this),window.location.hash=\"forms\",this.showChildView(\"content\",new t),i.channel(\"widget-forms\").trigger(\"change:content\"),this.getUI(\"cancel\").hide(),this.getUI(\"add\").show(),this.getChildView(\"filter\").updatePlaceholder(\"Search Forms\")}})}),n(\"views/sections/widgets.js\",[\"views/widgets/forms/forms\"],function(e){return Marionette.View.extend({template:\"#tmpl-nf-widgets\",regions:{forms:\".widget-forms\"},onRender:function(){this.showChildView(\"forms\",new e)}})}),n(\"views/services/service\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-service\",className:function(){return\"nf-extend nf-box \"+this.model.get(\"classes\")},ui:{install:\".js--install\",learnMore:\".js--learn-more\",enabled:\".nf-toggle.setting\",toggleEnable:\".nf-toggle + label\"},events:{\"click @ui.install\":function(){i.channel(\"dashboard\").request(\"install:service\",this.model)},\"click @ui.learnMore\":function(){this.showLearnMore()},\"click @ui.toggleEnable\":function(){if(null==this.model.get(\"enabled\")&&this.model.get(\"link\"))return window.location=this.model.get(\"link\"),this.render();this.model.set(\"enabled\",!this.model.get(\"enabled\")),this.model.save(\"enabled\"),this.render()}},initialize:function(e){this.updateOAuth(),this.listenTo(this.model,\"change\",this.render),i.channel(\"dashboard\").reply(\"more:service:\"+this.model.get(\"slug\"),this.showLearnMore,this),this.listenTo(i.channel(\"dashboard\"),\"fetch:oauth\",this.updateOAuth),this.listenTo(i.channel(\"dashboard\"),\"save:service-\"+this.model.get(\"slug\"),this.render)},showLearnMore:function(){var e=new jBox(\"Modal\",{width:750,title:this.model.get(\"learnMoreTitle\")||this.model.get(\"name\"),content:this.model.get(\"learnMore\"),closeButton:\"box\",blockScroll:!0});e.open(),i.channel(\"dashboard\").reply(\"service:\"+this.model.get(\"slug\")+\":modal\",function(){return e})},updateOAuth:function(){var e=i.channel(\"dashboard\").request(\"get:oauth\");this.connected=e.get(\"connected\"),this.render()},templateContext:function(){return{is_connected:this.connected}}})}),n(\"views/services/services\",[\"views/services/service\",\"models/serviceCollection\"],function(e,t){return Marionette.CollectionView.extend({collection:new t,className:\"wrap apps-container\",childView:e,initialize:function(){this.updateCollection(),this.listenTo(i.channel(\"dashboard\"),\"fetch:services\",this.updateCollection)},updateCollection:function(){this.collection=i.channel(\"dashboard\").request(\"get:services\"),this.render()}})}),n(\"views/sections/services.js\",[\"views/services/services\"],function(e){return Marionette.View.extend({template:\"#tmpl-nf-services\",regions:{services:\".services\"},onRender:function(){this.showChildView(\"services\",new e)}})}),n(\"views/sections/apps.js\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-apps\"})}),n(\"views/sections/memberships.js\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-memberships\"})}),n(\"views/oauth.js\",[\"models/oauthModel\"],function(e){return Marionette.View.extend({model:new e,template:\"#tmpl-nf-notices-oauth\",className:\"nf-notices--oauth\",ui:{disconnect:\".js--disconnect\"},initialize:function(e){this.listenTo(i.channel(\"dashboard\"),\"fetch:oauth\",this.updateModel)},updateModel:function(){this.model=i.channel(\"dashboard\").request(\"get:oauth\"),this.render()},events:{\"click @ui.disconnect\":function(){i.channel(\"dashboard\").request(\"disconnect:oauth\")}}})}),n(\"models/promotionModel\",[],function(){return Backbone.Model.extend({defaults:{id:\"\",content:\"\"},initialize:function(){}})}),n(\"views/promotion.js\",[\"models/promotionModel\"],function(e){return Marionette.View.extend({model:null,template:\"#tmpl-nf-promotion\",className:\"nf-promotion\",initialize:function(){var t=nfPromotions[Math.floor(Math.random()*nfPromotions.length)];this.model=new e(t)}})}),n(\"views/dashboardView\",[\"views/sections/widgets.js\",\"views/sections/services.js\",\"views/sections/apps.js\",\"views/sections/memberships.js\",\"views/oauth.js\",\"views/promotion.js\"],function(e,t,n,o,s,r){return Marionette.View.extend({template:\"#tmpl-nf-dashboard\",currentView:\"widgets\",regions:{notices:\".notices\",promotions:\".promotions\",content:\".content\"},events:{\"click .widgets a\":function(t){this.showChildView(\"content\",new e),jQuery(\".\"+this.currentView).find(\"a\").removeClass(\"active\"),t.target.classList.add(\"active\"),this.currentView=\"widgets\"},\"click .services a\":function(e){this.showChildView(\"content\",new t),jQuery(\".\"+this.currentView).find(\"a\").removeClass(\"active\"),e.target.classList.add(\"active\"),this.currentView=\"services\"},\"click .apps a\":function(e){this.showChildView(\"content\",new n),jQuery(\".\"+this.currentView).find(\"a\").removeClass(\"active\"),e.target.classList.add(\"active\"),this.currentView=\"apps\"},\"click .memberships a\":function(e){this.showChildView(\"content\",new o),jQuery(\".\"+this.currentView).find(\"a\").removeClass(\"active\"),e.target.classList.add(\"active\"),this.currentView=\"memberships\"}},initialize:function(){switch(window.location.hash){case\"#apps\":this.currentView=\"apps\";break;case\"#services\":this.currentView=\"services\";break;case\"#memberships\":this.currentView=\"memberships\";break;case\"#widgets\":default:this.currentView=\"widgets\"}i.channel(\"dashboard\").reply(\"show:widgets\",function(){this.showChildView(\"content\",new e),jQuery(\"nav.sections a.active\").removeClass(\"active\"),jQuery(\"nav.sections .widgets a\").addClass(\"active\"),this.currentView=\"widgets\"},this),i.channel(\"dashboard\").reply(\"show:services\",function(){this.showChildView(\"content\",new t),jQuery(\"nav.sections a.active\").removeClass(\"active\"),jQuery(\"nav.sections .services a\").addClass(\"active\"),this.currentView=\"services\"},this),i.channel(\"dashboard\").reply(\"show:apps\",function(){this.showChildView(\"content\",new n),jQuery(\"nav.sections a.active\").removeClass(\"active\"),jQuery(\"nav.sections .apps a\").addClass(\"active\"),this.currentView=\"apps\"},this)},onRender:function(){switch(useServices&&this.showChildView(\"notices\",new s),useServices&&this.showChildView(\"promotions\",new r),window.location.hash){case\"#apps\":var i=new n;break;case\"#memberships\":var i=new o;break;case\"#services\":var i=new t;break;case\"#widgets\":default:var i=new e}if(this.showChildView(\"content\",i),\"1\"==nfAdmin.showOptin){var a=new jBox(\"Modal\",{closeOnEsc:!1,closeOnClick:!1,width:400}),l=document.createElement(\"div\");l.id=\"optin-modal-title\";var c=document.createElement(\"h2\");c.innerHTML=\"Help make Ninja Forms better!\",l.appendChild(c);var d=document.createElement(\"div\");d.classList.add(\"message\"),d.style.padding=\"0px 20px 20px 20px\",d.innerHTML=nfi18n.optinContent;var u=document.createElement(\"p\");u.style.paddingBottom=\"10px\";var h=document.createElement(\"input\");h.id=\"optin-send-email\",h.setAttribute(\"type\",\"checkbox\"),h.style.margin=\"7px\";var m=document.createElement(\"label\");m.setAttribute(\"for\",\"optin-send-email\"),m.innerHTML=nfi18n.optinYesplease,u.appendChild(h),u.appendChild(m),d.appendChild(u),u=document.createElement(\"p\"),u.id=\"optin-block\",u.style.padding=\"0px 5px 20px 5px\",u.style.display=\"none\";var f=document.createElement(\"input\");f.id=\"optin-email-address\",f.setAttribute(\"type\",\"text\"),f.setAttribute(\"value\",nfAdmin.currentUserEmail),f.style.width=\"100%\",f.style.fontSize=\"16px\",u.appendChild(f),d.appendChild(u);var p=document.createElement(\"span\");p.id=\"optin-spinner\",p.classList.add(\"spinner\"),p.style.display=\"none\",d.appendChild(p);var w=document.createElement(\"div\");w.id=\"optin-buttons\",w.classList.add(\"buttons\");var g=document.createElement(\"div\");g.id=\"optout\",g.classList.add(\"nf-button\",\"secondary\"),g.innerHTML=nfi18n.optinSecondary,w.appendChild(g);var v=document.createElement(\"div\");v.id=\"optin\",v.classList.add(\"nf-button\",\"primary\",\"pull-right\"),v.innerHTML=nfi18n.optinPrimary,w.appendChild(v),d.appendChild(w);var b=document.createElement(\"h2\");b.innerHTML=nfi18n.optinAwesome;var y=document.createElement(\"div\");y.id=\"optin-thankyou\",y.classList.add(\"message\"),y.style.padding=\"20px\",y.innerHTML=nfi18n.optinThanks,a.setContent(document.createElement(\"div\").appendChild(d).innerHTML),a.setTitle(document.createElement(\"div\").appendChild(l).innerHTML),a.open(),jQuery(\"#optin-send-email\").click(function(e){jQuery(this).is(\":checked\")?jQuery(\"#optin-block\").show():jQuery(\"#optin-block\").hide()}),jQuery(\"#optin\").click(function(e){var t;jQuery(\"#optin-send-email\").attr(\"checked\")?(t=1,userEmail=jQuery(\"#optin-email-address\").val()):(t=0,userEmail=\"\"),jQuery(\"#optin\").unbind(\"click\"),jQuery(\"#optout\").unbind(\"click\");var n=jQuery(\"#optin\").width();jQuery(\"#optin\").html('<span class=\"dashicons dashicons-update dashicons-update-spin\"></span>'),jQuery(\"#optin\").width(n),jQuery.post(ajaxurl,{action:\"nf_optin\",ninja_forms_opt_in:1,send_email:t,user_email:userEmail},function(e){a.setTitle(document.createElement(\"div\").appendChild(b).innerHTML),a.setContent(document.createElement(\"div\").appendChild(y).innerHTML),setTimeout(function(){a.close()},2e3)})}),jQuery(\"#optout\").click(function(e){jQuery(\"#optin\").unbind(\"click\"),jQuery(\"#optout\").unbind(\"click\");var t=jQuery(\"#optout\").width();jQuery(\"#optout\").html('<span class=\"dashicons dashicons-update dashicons-update-spin\"></span>'),jQuery(\"#optout\").width(t),jQuery.post(ajaxurl,{action:\"nf_optin\",ninja_forms_opt_in:0},function(e){a.close()})})}else if(\"1\"==nfAdmin.doingCleanup)var C=this,j={width:450,closeOnClick:!1,closeOnEsc:!1,content:nfi18n.cleanupContent,useProgressBar:!0,loadingText:nfi18n.cleanupLoading,btnSecondary:{text:nfi18n.cleanupSecondary,callback:function(){x.toggleModal(!1)}},btnPrimary:{text:nfi18n.cleanupPrimary,callback:function(){jQuery(window).bind(\"beforeunload\",function(){return\"Are you sure? Leaving before the process completes could cause damage to your data.\"}),x.maybeShowActions(!1),x.maybeShowProgress(!0),C.cleanupProcess(C,-1,x)}}},x=new NinjaModal(j);if(void 0!==nfAdmin.formTelemetry&&1==nfAdmin.formTelemetry){var M={action:\"nf_form_telemetry\",security:nfAdmin.ajaxNonce};jQuery.post(ajaxurl,M)}},templateContext:function(){var e=this;return{renderNav:function(){var t=document.createElement(\"div\");return _.each(nfDashItems,function(n){var i=document.createElement(\"li\"),o=document.createElement(\"a\");o.href=\"#\"+n.slug,e.currentView==n.slug&&o.classList.add(\"active\"),o.innerHTML=n.niceName,i.classList.add(n.slug),i.appendChild(o),t.appendChild(i)}),t.innerHTML}}},cleanupProcess:function(e,t,n){var i={action:\"nf_batch_process\",batch_type:\"data_cleanup\",security:nfAdmin.batchNonce};jQuery.post(ajaxurl,i,function(i){if(i=JSON.parse(i),i.batch_complete)return n.setProgress(100),jQuery(window).unbind(\"beforeunload\"),n.toggleModal(!1),!1;-1==t&&(t=void 0!==i.step_total?i.step_total:i.step_remaining);var o=t-i.step_remaining,s=Math.round(o/t*100);n.incrementProgress(s),e.cleanupProcess(e,t,n)})}})});var i=Backbone.Radio;useServices||(nfDashItems=nfDashItems.filter(function(e){return\"services\"!==e.slug})),jQuery(document).ready(function(e){t([\"controllers/formsController\",\"controllers/oauthController\",\"controllers/servicesController\",\"views/dashboardView\"],function(t,n,i,o){(new(Marionette.Application.extend({region:\"#ninja-forms-dashboard\",controllers:{},initialize:function(e){var t=this;Marionette.Renderer.render=function(e,n){var e=t.template(e);return e(n)}},onStart:function(){this.showView(new o),this.controllers.forms=new t,useServices&&(this.controllers.oauth=new n),useServices&&(this.controllers.services=new i)},template:function(t){return _.template(e(t).html(),{evaluate:/<#([\\s\\S]+?)#>/g,interpolate:/\\{\\{\\{([\\s\\S]+?)\\}\\}\\}/g,escape:/\\{\\{([^\\}]+?)\\}\\}(?!\\})/g,variable:\"data\"})}}))).start()})}),jQuery('a[href=\"admin.php?page=ninja-forms#new-form\"]').on(\"click\",function(e){e.preventDefault(),window.location.hash=\"new-form\",i.channel(\"dashboard\").request(\"show:widgets\"),i.channel(\"widget-forms\").request(\"show:newFormsGrid\")}),jQuery('a[href=\"admin.php?page=ninja-forms#apps\"]').on(\"click\",function(e){e.preventDefault(),window.location.hash=\"apps\",i.channel(\"dashboard\").request(\"show:apps\")}),jQuery('a[href=\"admin.php?page=ninja-forms\"]').on(\"click\",function(e){e.preventDefault(),window.location.hash=\"forms\",i.channel(\"dashboard\").request(\"show:widgets\"),i.channel(\"widget-forms\").request(\"show:formsTable\")}),jQuery(window).on(\"hashchange\",function(){var e=window.location.hash.substr(1);i.channel(\"dashboard\").request(\"show:\"+e)}),n(\"main\",function(){})}();"],"file":"dashboard.min.js"}
|
1 |
+
{"version":3,"names":[],"mappings":"","sources":["views/widgets/forms/newFormTemplate.js"],"sourcesContent":["!function(){var e,t,n;!function(i){function s(e,t){return y.call(e,t)}function o(e,t){var n,i,s,o,r,a,l,d,c,u,h,m=t&&t.split(\"/\"),p=v.map,f=p&&p[\"*\"]||{};if(e&&\".\"===e.charAt(0))if(t){for(e=e.split(\"/\"),r=e.length-1,v.nodeIdCompat&&j.test(e[r])&&(e[r]=e[r].replace(j,\"\")),e=m.slice(0,m.length-1).concat(e),c=0;c<e.length;c+=1)if(\".\"===(h=e[c]))e.splice(c,1),c-=1;else if(\"..\"===h){if(1===c&&(\"..\"===e[2]||\"..\"===e[0]))break;c>0&&(e.splice(c-1,2),c-=2)}e=e.join(\"/\")}else 0===e.indexOf(\"./\")&&(e=e.substring(2));if((m||f)&&p){for(n=e.split(\"/\"),c=n.length;c>0;c-=1){if(i=n.slice(0,c).join(\"/\"),m)for(u=m.length;u>0;u-=1)if((s=p[m.slice(0,u).join(\"/\")])&&(s=s[i])){o=s,a=c;break}if(o)break;!l&&f&&f[i]&&(l=f[i],d=c)}!o&&l&&(o=l,a=d),o&&(n.splice(0,a,o),e=n.join(\"/\"))}return e}function r(e,t){return function(){var n=C.call(arguments,0);return\"string\"!=typeof n[0]&&1===n.length&&n.push(null),m.apply(i,n.concat([e,t]))}}function a(e){return function(t){return o(t,e)}}function l(e){return function(t){w[e]=t}}function d(e){if(s(g,e)){var t=g[e];delete g[e],b[e]=!0,h.apply(i,t)}if(!s(w,e)&&!s(b,e))throw new Error(\"No \"+e);return w[e]}function c(e){var t,n=e?e.indexOf(\"!\"):-1;return n>-1&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function u(e){return function(){return v&&v.config&&v.config[e]||{}}}var h,m,p,f,w={},g={},v={},b={},y=Object.prototype.hasOwnProperty,C=[].slice,j=/\\.js$/;p=function(e,t){var n,i=c(e),s=i[0];return e=i[1],s&&(s=o(s,t),n=d(s)),s?e=n&&n.normalize?n.normalize(e,a(t)):o(e,t):(e=o(e,t),i=c(e),s=i[0],e=i[1],s&&(n=d(s))),{f:s?s+\"!\"+e:e,n:e,pr:s,p:n}},f={require:function(e){return r(e)},exports:function(e){var t=w[e];return void 0!==t?t:w[e]={}},module:function(e){return{id:e,uri:\"\",exports:w[e],config:u(e)}}},h=function(e,t,n,o){var a,c,u,h,m,v,y=[],C=typeof n;if(o=o||e,\"undefined\"===C||\"function\"===C){for(t=!t.length&&n.length?[\"require\",\"exports\",\"module\"]:t,m=0;m<t.length;m+=1)if(h=p(t[m],o),\"require\"===(c=h.f))y[m]=f.require(e);else if(\"exports\"===c)y[m]=f.exports(e),v=!0;else if(\"module\"===c)a=y[m]=f.module(e);else if(s(w,c)||s(g,c)||s(b,c))y[m]=d(c);else{if(!h.p)throw new Error(e+\" missing \"+c);h.p.load(h.n,r(o,!0),l(c),{}),y[m]=w[c]}u=n?n.apply(w[e],y):void 0,e&&(a&&a.exports!==i&&a.exports!==w[e]?w[e]=a.exports:u===i&&v||(w[e]=u))}else e&&(w[e]=n)},e=t=m=function(e,t,n,s,o){if(\"string\"==typeof e)return f[e]?f[e](t):d(p(e,t).f);if(!e.splice){if(v=e,v.deps&&m(v.deps,v.callback),!t)return;t.splice?(e=t,t=n,n=null):e=i}return t=t||function(){},\"function\"==typeof n&&(n=s,s=o),s?h(i,e,t,n):setTimeout(function(){h(i,e,t,n)},4),m},m.config=function(e){return m(e)},e._defined=w,n=function(e,t,n){if(\"string\"!=typeof e)throw new Error(\"See almond README: incorrect module build, no module name\");t.splice||(n=t,t=[]),s(w,e)||s(g,e)||(g[e]=[e,t,n])},n.amd={jQuery:!0}}(),n(\"../../assets/js/lib/almond\",function(){}),n(\"models/formModel\",[],function(){return Backbone.Model.extend({defaults:{objectType:\"form\",id:0,title:\"unknown\",created_at:\"unknown\"},url:function(){return ajaxurl+\"?action=nf_forms&form_id=\"+this.get(\"id\")},initialize:function(){this.set(\"id\",Number(this.get(\"id\"))),this.get(\"id\")&&this.initShortcode(this.get(\"id\")),this.get(\"title\")&&this.set(\"title\",this.get(\"title\").replace(/<\\/?[^>]+(>|$)/g,\"\"))},initShortcode:function(e){var t=\"[ninja_form id=\"+e+\"]\";this.set(\"shortcode\",t)},destroy:function(){var e=this;jQuery.ajax({type:\"POST\",url:ajaxurl+\"?action=nf_forms&method_override=delete&form_id=\"+this.get(\"id\"),success:function(t){var t=JSON.parse(t);e.collection.remove(e)}})}})}),n(\"models/formCollection\",[\"models/formModel\"],function(e){return Backbone.Collection.extend({model:e,comparator:\"title\",tmpNum:1,url:function(){return ajaxurl+\"?action=nf_forms\"},initialize:function(){this.newIDs=[],this.baseUrl=window.location.href.split(\"?\")[0],this.listenTo(i.channel(\"dashboard\"),\"forms:delete\",this.modalConfirm),this.listenTo(i.channel(\"dashboard\"),\"forms:duplicate\",this.duplicate),this.modal=new jBox(\"Modal\",{width:400,addClass:\"dashboard-modal\",overlay:!0,closeOnClick:\"body\"})},parse:function(e,t){return e.data},modalConfirm:function(e){var t,n,i,s,o,r,a,l=e.model.get(\"id\"),d=e.model.get(\"title\");n=document.createElement(\"div\"),n.style.paddingRight=\"20px\",n.style.paddingLeft=\"20px\",n.style.paddingBottom=\"20px\",i=document.createElement(\"p\"),s=document.createElement(\"em\"),o=document.createElement(\"div\"),r=document.createElement(\"button\"),a=document.createElement(\"div\"),n.classList.add(\"message\"),s.innerHTML=d,i.innerHTML+=nfi18n.deleteWarningA+\" (<strong>\"+d+\"</strong>). \"+nfi18n.deleteWarningB,i.appendChild(document.createElement(\"br\")),i.appendChild(document.createElement(\"br\"));var c=document.createElement(\"a\");c.href=this.baseUrl+\"?page=nf-import-export&exportFormId=\"+l,c.innerHTML='<i class=\"fa fa-download\" style=\"padding:5px;\"></i>'+nfi18n.deleteXForm,c.target=\"_blank\",i.appendChild(c),i.appendChild(document.createElement(\"br\"));var u=document.createElement(\"a\");u.href=this.baseUrl+\"?page=nf-processing&action=download_all_subs&form_id=\"+l+\"&redirect=\"+encodeURIComponent(this.baseUrl.replace(\"admin.php\",\"edit.php\")+\"?post_status=all&post_type=nf_sub&form_id=\"+l),u.target=\"_blank\",u.innerHTML='<i class=\"fa fa-download\" style=\"padding:5px;\"></i>'+nfi18n.deleteXSubs,i.appendChild(u),i.appendChild(document.createElement(\"br\")),n.appendChild(i);var h=document.createElement(\"label\");h.for=\"confirmDeleteFormInput\",h.innerHTML=nfi18n.deleteConfirmA+' <span style=\"color:red;\">DELETE</span> '+nfi18n.deleteConfirmB;var m=document.createElement(\"input\");m.type=\"text\",m.id=\"confirmDeleteFormInput\",m.style.marginTop=\"10px\",m.style.width=\"100%\",m.style.height=\"2.5em\",m.style.fontSize=\"1em\",n.appendChild(h),n.appendChild(document.createElement(\"br\")),n.appendChild(m),n.appendChild(document.createElement(\"br\")),n.appendChild(document.createElement(\"br\")),r.innerHTML=nfi18n.delete,r.classList.add(\"confirm\",\"nf-button\",\"primary\",\"pull-right\"),a.innerHTML=nfi18n.cancel,a.classList.add(\"cancel\",\"nf-button\",\"secondary\"),o.appendChild(a),o.appendChild(r),o.classList.add(\"buttons\"),n.appendChild(o),t=document.createElement(\"div\"),t.appendChild(n),this.modal.setContent(t.innerHTML),this.modal.setTitle(nfi18n.deleteTitle),this.modal.open();var p=this;this.modal.container[0].getElementsByClassName(\"cancel\")[0].addEventListener(\"click\",function(){p.modalClose()}),this.modal.container[0].getElementsByClassName(\"confirm\")[0].addEventListener(\"click\",function(t){t.preventDefault(),\"DELETE\"===document.getElementById(\"confirmDeleteFormInput\").value?p.confirmDelete(e):p.modalClose()})},modalClose:function(){this.modal.close()},confirmDelete:function(e){jQuery(e.el).removeClass(\"show-actions\"),jQuery(e.el).addClass(\"deleting\"),jQuery(e.el).animate({opacity:0,\"line-height\":0,display:\"none\"},500),console.log(e),e.model.destroy(),this.modalClose()},duplicate:function(e){var t='<div class=\"message\">Duplicating <em>'+e.model.get(\"title\")+'</em>...<div class=\"nf-loading-spinner\"></div></div>';this.modal.setContent(t),this.modal.setTitle(\"Please Wait\"),this.modal.open();var n=this;jQuery.ajax({type:\"POST\",url:ajaxurl+\"?action=nf_forms&clone_id=\"+e.model.get(\"id\"),success:function(t){var t=JSON.parse(t),i=t.data.new_form_id,s=e.model.clone();s.set({id:i,title:s.get(\"title\")+\" - copy\",created_at:new Date}),s.initShortcode(i),e.model.collection.add(s),n.modalClose()}})}})}),n(\"controllers/formsController\",[\"models/formModel\",\"models/formCollection\"],function(e,t){return Marionette.Object.extend({initialize:function(){this.forms=new t,i.channel(\"dashboard\").reply(\"get:forms\",this.getForms,this),this.forms.fetch({success:function(e){i.channel(\"dashboard\").trigger(\"fetch:forms\",e)}})},getForms:function(){return this.forms}})}),n(\"models/oauthModel\",[],function(){return Backbone.Model.extend({defaults:{connected:null,connect_url:\"\"},url:function(){return ajaxurl+\"?action=nf_oauth\"},initialize:function(){},parse:function(e,t){return e.data}})}),n(\"controllers/oauthController\",[\"models/oauthModel\"],function(e){return Marionette.Object.extend({initialize:function(){this.oauth=new e,i.channel(\"dashboard\").reply(\"get:oauth\",this.getOAuth,this),i.channel(\"dashboard\").reply(\"disconnect:oauth\",this.disconnect,this),i.channel(\"dashboard\").reply(\"oauth:learn-more\",this.learnMoreModal,this),this.initOAuth()},getOAuth:function(){return this.oauth},initOAuth:function(){this.oauth.fetch({success:function(e){i.channel(\"dashboard\").trigger(\"fetch:oauth\")}})},disconnect:function(){var e=this;new jBox(\"Confirm\",{width:750,content:nfi18n.oauthDisconnectContent,confirmButton:nfi18n.oauthDisconnectConfirm,cancelButton:nfi18n.oauthDisconnectCancel,closeOnConfirm:!0,confirm:function(){jQuery.ajax({type:\"POST\",url:ajaxurl+\"?action=nf_oauth_disconnect\",success:function(t){console.log(t),e.initOAuth()}})}}).open()},learnMoreModal:function(){new jBox(\"Modal\",{width:500,content:nfi18n.oauthLearnMoreContent}).open()}})}),n(\"models/serviceModel\",[],function(){return Backbone.Model.extend({defaults:{objectType:\"service\",name:\"\",slug:\"\",installPath:\"\",description:\"\",enabled:null,infoLink:null,serviceLink:null,is_installing:!1,classes:\"\"},url:function(){return ajaxurl+\"?action=nf_service_\"+this.get(\"slug\")},initialize:function(){this.get(\"slug\")==serviceSuccess&&this.get(\"successMessage\")&&new jBox(\"Modal\",{width:300,addClass:\"dashboard-modal\",overlay:!0,closeOnClick:!0,content:this.get(\"successMessage\"),title:this.get(\"successMessageTitle\"),closeButton:\"box\"}).open();var e=this;i.channel(\"dashboard\").reply(\"install:service:\"+this.get(\"slug\"),function(){if(e.get(\"serviceLink\")&&e.get(\"serviceLink\").href){var t=e.get(\"serviceLink\").href;new jBox(\"Modal\",{width:300,addClass:\"dashboard-modal\",overlay:!0,closeOnClick:\"body\",content:nfi18n.serviceRedirect}).open();var n=i.channel(\"dashboard\").request(\"get:oauth\");if(n.get(\"connected\"))window.location=t;else{if(e.get(\"connect_url\"))return window.location=e.get(\"connect_url\")+\"&redirect=\"+t;window.location=n.get(\"connect_url\")+\"&redirect=\"+t}}})},save:function(){var e=this;jQuery.ajax({type:\"POST\",url:this.url(),data:this.toJSON()}).done(function(t){var n=JSON.parse(t);void 0!==n.error&&(alert(nfi18n.serviceUpdateError+\" \"+n.error),e.set(\"enabled\",!e.get(\"enabled\"))),i.channel(\"dashboard\").trigger(\"save:service-\"+e.get(\"slug\"))})}})}),n(\"models/serviceCollection\",[\"models/serviceModel\"],function(e){return Backbone.Collection.extend({model:e,comparator:\"name\",url:function(){return ajaxurl+\"?action=nf_services\"},initialize:function(){},parse:function(e,t){return e.data}})}),n(\"controllers/servicesController\",[\"models/serviceCollection\"],function(e){return Marionette.Object.extend({initialize:function(){this.services=new e,i.channel(\"dashboard\").reply(\"install:service\",this.installService,this),i.channel(\"dashboard\").reply(\"get:services\",this.getServices,this),this.fetchServices()},getServices:function(){return this.services},fetchServices:function(e){this.services.fetch({success:function(t){e&&e(t),i.channel(\"dashboard\").trigger(\"fetch:services\")}})},installService:function(e){var t=this;if(!(e instanceof Backbone.Model))var e=this.services.find(function(t){return e==t.get(\"slug\")});e.set(\"is_installing\",!0);var n=e.get(\"slug\"),s=e.get(\"installPath\");jQuery.post(ajaxurl,{action:\"nf_services_install\",plugin:n,install_path:s},function(e){t.fetchServices(function(){i.channel(\"dashboard\").request(\"install:service:\"+n)})})}})}),n(\"views/widgets/forms/formsFilter\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-filter\",ui:{input:\"input\"},events:{\"keyup @ui.input\":\"updateFilter\"},initialize:function(){this.listenTo(i.channel(\"widget-forms\"),\"change:content\",this.clearFilter)},updateFilter:function(){var e=this.getUI(\"input\").val();i.channel(\"widget-forms\").trigger(\"update:filter\",e)},clearFilter:function(){this.getUI(\"input\").val(\"\")},updatePlaceholder:function(e){this.getUI(\"input\").attr(\"placeholder\",e)}})}),n(\"views/widgets/forms/formsTableRow\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-table-row\",tagName:\"tr\",replaceElement:!0,ui:{delete:\".delete\",duplicate:\".duplicate\",edit:\".nf-item-edit\"},events:{\"click @ui.delete\":function(){i.channel(\"dashboard\").trigger(\"forms:delete\",this)},\"click @ui.duplicate\":function(){i.channel(\"dashboard\").trigger(\"forms:duplicate\",this)},\"click @ui.edit\":function(e){this.$el.toggleClass(\"show-actions\").siblings().removeClass(\"show-actions\")}},templateContext:function(){var e=this.model;return{created_at:moment(e.get(\"created_at\")).format(\"MM/DD/YY h:mm A\")}}})}),n(\"views/widgets/forms/formsTableEmpty\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-table-empty\",tagName:\"tr\"})}),n(\"views/widgets/forms/formsTableBody\",[\"views/widgets/forms/formsTableRow\",\"views/widgets/forms/formsTableEmpty\"],function(e,t){return Marionette.CollectionView.extend({childView:e,emptyView:t,className:\"forms-collection\",tagName:\"tbody\",initialize:function(){this.listenTo(i.channel(\"widget-forms\"),\"update:filter\",this.updateFilter)},updateFilter:function(e){this.setFilter(function(t,n,i){return 0<=t.get(\"title\").toLowerCase().indexOf(e.toLowerCase())})}})}),n(\"views/widgets/forms/formsTableLoading\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-table-loading\",tagName:\"tr\"})}),n(\"views/widgets/forms/formsTable\",[\"views/widgets/forms/formsTableBody\",\"views/widgets/forms/formsTableLoading\",\"models/formCollection\"],function(e,t,n){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-table\",className:\"nf-table-display\",tagName:\"table\",initialize:function(){var t=this;this.listenTo(i.channel(\"dashboard\"),\"fetch:forms\",function(n){t.showChildView(\"body\",new e({collection:n}))})},regions:{body:{el:\"tbody\",replaceElement:!0}},ui:{sortable:\".sortable\",body:\"tbody\",action2:\".action2\",more:\".more\",less:\".less\"},onRender:function(){this.getUI(\"less\").hide();var n=i.channel(\"dashboard\").request(\"get:forms\");void 0===n?this.showChildView(\"body\",new t):this.showChildView(\"body\",new e({collection:n})),this.maybeHideMoreButton()},events:{\"click @ui.sortable\":\"sortFormsTable\",\"click @ui.more\":\"showMore\",\"click @ui.less\":\"showLess\"},sortFormsTable:function(e){this.getUI(\"sortable\").removeClass(\"sorted-asc\"),this.getUI(\"sortable\").removeClass(\"sorted-desc\");var t=jQuery(e.target).data(\"sort\"),n=jQuery(e.target).data(\"reverse\")||0;n?(jQuery(e.target).addClass(\"sorted-desc\"),jQuery(e.target).removeClass(\"sorted-asc\")):(jQuery(e.target).addClass(\"sorted-asc\"),jQuery(e.target).removeClass(\"sorted-desc\"));var i=this.getChildView(\"body\").collection;i.comparator=function(e,i){return name1=e.get(t).toLowerCase(),name2=i.get(t).toLowerCase(),name1<name2?ret=-1:name1>name2?ret=1:ret=0,n&&(ret=-ret),ret},i.sort(),n?(i.models.reverse(),jQuery(e.target).data(\"reverse\",0)):jQuery(e.target).data(\"reverse\",1)},showMore:function(){this.getUI(\"more\").hide(),this.getUI(\"less\").show(),this.getUI(\"body\").addClass(\"more\")},showLess:function(){this.getUI(\"less\").hide(),this.getUI(\"more\").show(),this.getUI(\"body\").removeClass(\"more\")},maybeHideMoreButton:function(){void 0!==this.collection&&10<this.collection.length||this.getUI(\"action2\").hide()}})}),n(\"models/formTemplateModel\",[],function(){return Backbone.Model.extend({defaults:{objectType:\"template\",id:\"none\",title:\"unknown\",type:\"\"},initialize:function(){this.set(\"desc\",this.get(\"template-desc\")),this.set(\"modal-content\",this.get(\"modal-content\")),this.set(\"modal-title\",this.get(\"modal-title\"))}})}),n(\"models/formTemplateCollection\",[\"models/formTemplateModel\"],function(e){return Backbone.Collection.extend({model:e,tmpNum:1,url:function(){return ajaxurl+\"?action=nf_new_form_templates\"},parse:function(e,t){return e.data},initialize:function(){this.fetch({success:function(e){},error:function(e){}})}})}),n(\"views/widgets/forms/newFormTemplate\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms-template\",events:{click:\"maybeOpenModal\"},maybeOpenModal:function(e){if(e.preventDefault(),\"ad\"==this.model.get(\"type\")){new jBox(\"Modal\",{width:450,title:this.model.get(\"modal-title\"),content:this.model.get(\"modal-content\"),closeButton:\"box\",blockScroll:!0}).open()}else{var t={batch_type:\"import_form_template\",loadingText:\"Importing...\",extraData:{template:this.model.get(\"id\")},onCompleteCallback:function(e){if(void 0===e.form_id)return!1;window.location.href=nfAdmin.builderURL+e.form_id}};new NinjaBatchProcessor(t)}}})}),n(\"views/widgets/forms/newFormGrid\",[\"models/formTemplateCollection\",\"views/widgets/forms/newFormTemplate\"],function(e,t){return Marionette.CollectionView.extend({tagName:\"div\",className:\"template-list\",collection:new e,childView:t,initialize:function(){this.listenTo(i.channel(\"widget-forms\"),\"update:filter\",this.updateFilter)},updateFilter:function(e){this.setFilter(function(t,n,i){return 0<=t.get(\"title\").toLowerCase().indexOf(e.toLowerCase())})}})}),n(\"views/widgets/forms/forms\",[\"views/widgets/forms/formsFilter\",\"views/widgets/forms/formsTable\",\"views/widgets/forms/newFormGrid\"],function(e,t,n){return Marionette.View.extend({template:\"#tmpl-nf-widget-forms\",regions:{filter:\".filter\",content:\".content\"},ui:{add:\".add\",cancel:\".cancel\"},initialize:function(){},onRender:function(){this.getUI(\"cancel\").hide(),this.showChildView(\"filter\",new e),\"#new-form\"==window.location.hash?(this.getUI(\"add\").hide(),this.getUI(\"cancel\").show(),this.showChildView(\"content\",new n)):this.showChildView(\"content\",new t)},events:{\"click @ui.add\":\"showNewFormGrid\",\"click @ui.cancel\":\"showFormsTable\"},showNewFormGrid:function(){window.location.hash=\"new-form\",this.showChildView(\"content\",new n),i.channel(\"widget-forms\").trigger(\"change:content\"),this.getUI(\"add\").hide(),this.getUI(\"cancel\").show(),this.getChildView(\"filter\").updatePlaceholder(\"Search Templates\")},showFormsTable:function(){window.location.hash=\"forms\",this.showChildView(\"content\",new t),i.channel(\"widget-forms\").trigger(\"change:content\"),this.getUI(\"cancel\").hide(),this.getUI(\"add\").show(),this.getChildView(\"filter\").updatePlaceholder(\"Search Forms\")}})}),n(\"views/sections/widgets.js\",[\"views/widgets/forms/forms\"],function(e){return Marionette.View.extend({template:\"#tmpl-nf-widgets\",regions:{forms:\".widget-forms\"},onRender:function(){this.showChildView(\"forms\",new e)}})}),n(\"views/services/service\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-service\",className:function(){return\"nf-extend nf-box \"+this.model.get(\"classes\")},ui:{install:\".js--install\",learnMore:\".js--learn-more\",enabled:\".nf-toggle.setting\",toggleEnable:\".nf-toggle + label\"},events:{\"click @ui.install\":function(){i.channel(\"dashboard\").request(\"install:service\",this.model)},\"click @ui.learnMore\":function(){this.showLearnMore()},\"click @ui.toggleEnable\":function(){if(null==this.model.get(\"enabled\")&&this.model.get(\"link\"))return window.location=this.model.get(\"link\"),this.render();this.model.set(\"enabled\",!this.model.get(\"enabled\")),this.model.save(\"enabled\"),this.render()}},initialize:function(e){this.updateOAuth(),this.listenTo(this.model,\"change\",this.render),i.channel(\"dashboard\").reply(\"more:service:\"+this.model.get(\"slug\"),this.showLearnMore,this),this.listenTo(i.channel(\"dashboard\"),\"fetch:oauth\",this.updateOAuth),this.listenTo(i.channel(\"dashboard\"),\"save:service-\"+this.model.get(\"slug\"),this.render)},showLearnMore:function(){var e=new jBox(\"Modal\",{width:750,title:this.model.get(\"learnMoreTitle\")||this.model.get(\"name\"),content:this.model.get(\"learnMore\"),closeButton:\"box\",blockScroll:!0});e.open(),i.channel(\"dashboard\").reply(\"service:\"+this.model.get(\"slug\")+\":modal\",function(){return e})},updateOAuth:function(){var e=i.channel(\"dashboard\").request(\"get:oauth\");this.connected=e.get(\"connected\"),this.render()},templateContext:function(){return{is_connected:this.connected}}})}),n(\"views/services/services\",[\"views/services/service\",\"models/serviceCollection\"],function(e,t){return Marionette.CollectionView.extend({collection:new t,className:\"wrap apps-container\",childView:e,initialize:function(){this.updateCollection(),this.listenTo(i.channel(\"dashboard\"),\"fetch:services\",this.updateCollection)},updateCollection:function(){this.collection=i.channel(\"dashboard\").request(\"get:services\"),this.render()}})}),n(\"views/sections/services.js\",[\"views/services/services\"],function(e){return Marionette.View.extend({template:\"#tmpl-nf-services\",regions:{services:\".services\"},onRender:function(){this.showChildView(\"services\",new e)}})}),n(\"views/sections/apps.js\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-apps\"})}),n(\"views/sections/memberships.js\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-memberships\"})}),n(\"views/oauth.js\",[\"models/oauthModel\"],function(e){return Marionette.View.extend({model:new e,template:\"#tmpl-nf-notices-oauth\",className:\"nf-notices--oauth\",ui:{disconnect:\".js--disconnect\"},initialize:function(e){this.listenTo(i.channel(\"dashboard\"),\"fetch:oauth\",this.updateModel)},updateModel:function(){this.model=i.channel(\"dashboard\").request(\"get:oauth\"),this.render()},events:{\"click @ui.disconnect\":function(){i.channel(\"dashboard\").request(\"disconnect:oauth\")}}})}),n(\"models/promotionModel\",[],function(){return Backbone.Model.extend({defaults:{id:\"\",content:\"\"},initialize:function(){}})}),n(\"views/promotion.js\",[\"models/promotionModel\"],function(e){return Marionette.View.extend({model:null,template:\"#tmpl-nf-promotion\",className:\"nf-promotion\",initialize:function(){var t=nfPromotions[Math.floor(Math.random()*nfPromotions.length)];this.model=new e(t)}})}),n(\"views/sections/requiredUpdates.js\",[],function(){return Marionette.View.extend({template:\"#tmpl-nf-requiredUpdates\",updates:[],currentUpdate:0,totalUpdates:-1,updatesRemaining:-1,ui:{requiredUpdates:\".nf-required-update\"},onRender:function(){this.getRequiredUpdates()},setButtonClickEvent:function(){var e=this;jQuery(\"#nf-required-updates-btn\").off(\"click\").on(\"click\",function(t){t.preventDefault(),e.doRequiredUpdates(),jQuery(this).hide()})},getRequiredUpdates:function(){var e=this;jQuery.get(ajaxurl,{action:\"nf_required_update\"}).then(function(t){var n=JSON.parse(t);0===n.errors.length&&(e.totalUpdates=n.data.updates.length,e.updates=n.data.updates,0<e.updates.length?(e.requiredUpdates=e.updates.length,e.constructUpdateTable(),e.setButtonClickEvent()):window.location=window.location.origin+window.location.pathname+window.location.search)})},constructUpdateTable:function(){var e=this,t=document.getElementById(\"nf-upgrades-table\"),n=t.getElementsByTagName(\"thead\")[0],i=document.createElement(\"tr\"),s=document.createElement(\"th\");s.innerHTML=\"Update\",s.classList.add(\"nf-update-name-cell\");var o=document.createElement(\"th\");o.innerHTML=\"Progress\",o.classList.add(\"nf-update-progress-cell\"),i.appendChild(s),i.appendChild(o),n.appendChild(i);var r=t.getElementsByTagName(\"tbody\")[0];jQuery.each(this.updates,function(t,n){var i=document.createElement(\"tr\"),s=document.createElement(\"td\");s.innerHTML=n.nicename;var o=document.createElement(\"td\"),a=document.createElement(\"div\");a.id=\"update-progress-\"+t;var l=e.createNewProgressBar(t);a.appendChild(l),o.appendChild(a),i.appendChild(s),i.appendChild(o),r.appendChild(i)}),document.getElementById(\"nf-required-updates-btn\").style.display=\"block\"},doRequiredUpdates:function(){window.location.hash=\"#requiredUpdates\";var e=this;jQuery(\"#nf-required-updates-btn\").addClass(\"disabled\").attr(\"disabled\",\"disabled\"),jQuery.post(ajaxurl,{action:\"nf_required_update\",security:nfAdmin.updateNonce}).then(function(t){var n=JSON.parse(t);n.updatesRemaining>0?(e.updatesRemaining!==n.updatesRemaining&&n.currentStep===n.stepsTotal?(e.finishUpdate(e.currentUpdate),e.updatesRemaining=n.updatesRemaining):(e.showProgressBars(n),e.updatesRemaining=n.updatesRemaining),e.doRequiredUpdates()):(e.finishUpdate(e.currentUpdate),nfAdmin.requiredUpdates=0,jQuery(\"#nf-required-updates-btn\").removeClass(\"disabled\").removeAttr(\"disabled\").val(\"Go To Dashboard\").off(\"click\").on(\"click\",function(e){e.preventDefault(),window.location=window.location.origin+window.location.pathname+window.location.search}).show(),console.log(\"UPDATES DONE\"))})},showProgressBars:function(e){var t=this.totalUpdates-e.updatesRemaining,n=e.currentStep,i=e.stepsTotal,s=document.getElementById(\"nf_progressBar_\"+t);null==s&&(this.currentUpdate+=1,1===this.currentUpdate&&-1===this.totalUpdates&&(this.totalUpdates=t),s=this.createNewProgressBar(t)),this.incrementProgress(t,n,i)},createNewProgressBar:function(e){var t=document.createElement(\"div\");t.id=\"nf_progressBar_\"+e,t.classList.add(\"jBox-content\"),t.style.display=\"none\";var n=document.createElement(\"div\");n.classList.add(\"nf-progress-bar\");var i=document.createElement(\"div\");return i.id=\"nf-progress-bar-slider-\"+e,i.classList.add(\"nf-progress-bar-slider\"),n.appendChild(i),t.appendChild(n),t},incrementProgress:function(e,t,n){document.getElementById(\"nf_progressBar_\"+e).style.display=\"block\";var i=document.getElementById(\"nf-progress-bar-slider-\"+e),s=Number(t)/Number(n)*100;s>i.offsetWidth/i.parentElement.offsetWidth*100&&this.setProgress(e,s)},setProgress:function(e,t){document.getElementById(\"nf-progress-bar-slider-\"+e).style.width=t+\"%\",100<=t&&this.finishUpdate(e)},finishUpdate:function(e){var t=document.getElementById(\"nf_progressBar_\"+e),n=t.parentNode;n.removeChild(t);var i=document.createElement(\"span\");i.classList.add(\"dashicons\"),i.classList.add(\"dashicons-yes\"),n.appendChild(i),this.currentUpdate=this.currentUpdate+1}})}),n(\"views/dashboardView\",[\"views/sections/widgets.js\",\"views/sections/services.js\",\"views/sections/apps.js\",\"views/sections/memberships.js\",\"views/oauth.js\",\"views/promotion.js\",\"views/sections/requiredUpdates.js\"],function(e,t,n,s,o,r,a){return Marionette.View.extend({template:\"#tmpl-nf-dashboard\",currentView:\"widgets\",regions:{notices:\".notices\",promotions:\".promotions\",content:\".content\"},events:{\"click .widgets a\":function(t){\"1\"!=nfAdmin.requiredUpdates&&(this.showChildView(\"content\",new e),jQuery(\".\"+this.currentView).find(\"a\").removeClass(\"active\"),t.target.classList.add(\"active\"),this.currentView=\"widgets\")},\"click .services a\":function(e){\"1\"!=nfAdmin.requiredUpdates&&(this.showChildView(\"content\",new t),jQuery(\".\"+this.currentView).find(\"a\").removeClass(\"active\"),e.target.classList.add(\"active\"),this.currentView=\"services\")},\"click .apps a\":function(e){\"1\"!=nfAdmin.requiredUpdates&&(this.showChildView(\"content\",new n),jQuery(\".\"+this.currentView).find(\"a\").removeClass(\"active\"),e.target.classList.add(\"active\"),this.currentView=\"apps\")},\"click .memberships a\":function(e){\"1\"!=nfAdmin.requiredUpdates&&(this.showChildView(\"content\",new s),jQuery(\".\"+this.currentView).find(\"a\").removeClass(\"active\"),e.target.classList.add(\"active\"),this.currentView=\"memberships\")}},initialize:function(){switch(\"1\"===nfAdmin.requiredUpdates?window.location.hash=\"#requiredUpdates\":\"#requiredUpdates\"===window.location.hash&&(window.location.hash=\"\"),window.location.hash){case\"#apps\":this.currentView=\"apps\";break;case\"#services\":this.currentView=\"services\";break;case\"#memberships\":this.currentView=\"memberships\";break;case\"#requiredUpdates\":this.currentView=\"requiredUpdates\";break;case\"#widgets\":default:this.currentView=\"widgets\"}i.channel(\"dashboard\").reply(\"show:widgets\",function(){\"1\"!=nfAdmin.requiredUpdates&&(this.showChildView(\"content\",new e),jQuery(\"nav.sections a.active\").removeClass(\"active\"),jQuery(\"nav.sections .widgets a\").addClass(\"active\"),this.currentView=\"widgets\")},this),i.channel(\"dashboard\").reply(\"show:services\",function(){\"1\"!=nfAdmin.requiredUpdates&&(this.showChildView(\"content\",new t),jQuery(\"nav.sections a.active\").removeClass(\"active\"),jQuery(\"nav.sections .services a\").addClass(\"active\"),this.currentView=\"services\")},this),i.channel(\"dashboard\").reply(\"show:apps\",function(){\"1\"!=nfAdmin.requiredUpdates&&(this.showChildView(\"content\",new n),jQuery(\"nav.sections a.active\").removeClass(\"active\"),jQuery(\"nav.sections .apps a\").addClass(\"active\"),this.currentView=\"apps\")},this)},onRender:function(){switch(useServices&&this.showChildView(\"notices\",new o),useServices&&\"1\"!==nfAdmin.requiredUpdates&&this.showChildView(\"promotions\",new r),\"0\"===nfAdmin.requiredUpdates&&\"#requiredUpdates\"===window.location.hash&&(window.location.hash=\"\"),window.location.hash){case\"#apps\":var i=new n;break;case\"#memberships\":var i=new s;break;case\"#services\":var i=new t;break;case\"#requiredUpdates\":var i=new a;break;case\"#widgets\":default:var i=new e}if(this.showChildView(\"content\",i),\"1\"==nfAdmin.showOptin){var l=new jBox(\"Modal\",{closeOnEsc:!1,closeOnClick:!1,width:400}),d=document.createElement(\"div\");d.id=\"optin-modal-title\";var c=document.createElement(\"h2\");c.innerHTML=\"Help make Ninja Forms better!\",d.appendChild(c);var u=document.createElement(\"div\");u.classList.add(\"message\"),u.style.padding=\"0px 20px 20px 20px\",u.innerHTML=nfi18n.optinContent;var h=document.createElement(\"p\");h.style.paddingBottom=\"10px\";var m=document.createElement(\"input\");m.id=\"optin-send-email\",m.setAttribute(\"type\",\"checkbox\"),m.style.margin=\"7px\";var p=document.createElement(\"label\");p.setAttribute(\"for\",\"optin-send-email\"),p.innerHTML=nfi18n.optinYesplease,h.appendChild(m),h.appendChild(p),u.appendChild(h),h=document.createElement(\"p\"),h.id=\"optin-block\",h.style.padding=\"0px 5px 20px 5px\",h.style.display=\"none\";var f=document.createElement(\"input\");f.id=\"optin-email-address\",f.setAttribute(\"type\",\"text\"),f.setAttribute(\"value\",nfAdmin.currentUserEmail),f.style.width=\"100%\",f.style.fontSize=\"16px\",h.appendChild(f),u.appendChild(h);var w=document.createElement(\"span\");w.id=\"optin-spinner\",w.classList.add(\"spinner\"),w.style.display=\"none\",u.appendChild(w);var g=document.createElement(\"div\");g.id=\"optin-buttons\",g.classList.add(\"buttons\");var v=document.createElement(\"div\");v.id=\"optout\",v.classList.add(\"nf-button\",\"secondary\"),v.innerHTML=nfi18n.optinSecondary,g.appendChild(v);var b=document.createElement(\"div\");b.id=\"optin\",b.classList.add(\"nf-button\",\"primary\",\"pull-right\"),b.innerHTML=nfi18n.optinPrimary,g.appendChild(b),u.appendChild(g);var y=document.createElement(\"h2\");y.innerHTML=nfi18n.optinAwesome;var C=document.createElement(\"div\");C.id=\"optin-thankyou\",C.classList.add(\"message\"),C.style.padding=\"20px\",C.innerHTML=nfi18n.optinThanks,l.setContent(document.createElement(\"div\").appendChild(u).innerHTML),l.setTitle(document.createElement(\"div\").appendChild(d).innerHTML),l.open(),jQuery(\"#optin-send-email\").click(function(e){jQuery(this).is(\":checked\")?jQuery(\"#optin-block\").show():jQuery(\"#optin-block\").hide()}),jQuery(\"#optin\").click(function(e){var t;jQuery(\"#optin-send-email\").attr(\"checked\")?(t=1,userEmail=jQuery(\"#optin-email-address\").val()):(t=0,userEmail=\"\"),jQuery(\"#optin\").unbind(\"click\"),jQuery(\"#optout\").unbind(\"click\");var n=jQuery(\"#optin\").width();jQuery(\"#optin\").html('<span class=\"dashicons dashicons-update dashicons-update-spin\"></span>'),jQuery(\"#optin\").width(n),jQuery.post(ajaxurl,{action:\"nf_optin\",ninja_forms_opt_in:1,send_email:t,user_email:userEmail},function(e){l.setTitle(document.createElement(\"div\").appendChild(y).innerHTML),l.setContent(document.createElement(\"div\").appendChild(C).innerHTML),setTimeout(function(){l.close()},2e3)})}),jQuery(\"#optout\").click(function(e){jQuery(\"#optin\").unbind(\"click\"),jQuery(\"#optout\").unbind(\"click\");var t=jQuery(\"#optout\").width();jQuery(\"#optout\").html('<span class=\"dashicons dashicons-update dashicons-update-spin\"></span>'),jQuery(\"#optout\").width(t),jQuery.post(ajaxurl,{action:\"nf_optin\",ninja_forms_opt_in:0},function(e){l.close()})})}if(void 0!==nfAdmin.formTelemetry&&1==nfAdmin.formTelemetry){var j={action:\"nf_form_telemetry\",security:nfAdmin.ajaxNonce};jQuery.post(ajaxurl,j)}},templateContext:function(){var e=this;return{renderNav:function(){var t=document.createElement(\"div\");return _.each(nfDashItems,function(n){var i=document.createElement(\"li\"),s=document.createElement(\"a\");s.href=\"#\"+n.slug,\ne.currentView==n.slug&&s.classList.add(\"active\"),s.innerHTML=n.niceName,i.classList.add(n.slug),i.appendChild(s),t.appendChild(i)}),t.innerHTML}}}})});var i=Backbone.Radio;useServices||(nfDashItems=nfDashItems.filter(function(e){return\"services\"!==e.slug})),jQuery(document).ready(function(e){t([\"controllers/formsController\",\"controllers/oauthController\",\"controllers/servicesController\",\"views/dashboardView\"],function(t,n,i,s){(new(Marionette.Application.extend({region:\"#ninja-forms-dashboard\",controllers:{},initialize:function(e){var t=this;Marionette.Renderer.render=function(e,n){var e=t.template(e);return e(n)}},onStart:function(){this.showView(new s),this.controllers.forms=new t,useServices&&(this.controllers.oauth=new n),useServices&&(this.controllers.services=new i)},template:function(t){return _.template(e(t).html(),{evaluate:/<#([\\s\\S]+?)#>/g,interpolate:/\\{\\{\\{([\\s\\S]+?)\\}\\}\\}/g,escape:/\\{\\{([^\\}]+?)\\}\\}(?!\\})/g,variable:\"data\"})}}))).start()})}),jQuery('a[href=\"admin.php?page=ninja-forms#new-form\"]').on(\"click\",function(e){e.preventDefault(),\"1\"!==nfAdmin.requiredUpdates&&(window.location.hash=\"new-form\",i.channel(\"dashboard\").request(\"show:widgets\"),i.channel(\"widget-forms\").request(\"show:newFormsGrid\"))}),jQuery('a[href=\"admin.php?page=ninja-forms#apps\"]').on(\"click\",function(e){e.preventDefault(),\"1\"!==nfAdmin.requiredUpdates&&(window.location.hash=\"apps\",i.channel(\"dashboard\").request(\"show:apps\"))}),jQuery('a[href=\"admin.php?page=ninja-forms\"]').on(\"click\",function(e){e.preventDefault(),\"1\"!==nfAdmin.requiredUpdates&&(window.location.hash=\"forms\",i.channel(\"dashboard\").request(\"show:widgets\"),i.channel(\"widget-forms\").request(\"show:formsTable\"))}),jQuery(window).on(\"hashchange\",function(){var e=window.location.hash.substr(1);i.channel(\"dashboard\").request(\"show:\"+e)}),n(\"main\",function(){})}();"],"file":"dashboard.min.js"}
|
client/dashboard/main.js
CHANGED
@@ -80,23 +80,32 @@ jQuery( document ).ready( function( $ ) {
|
|
80 |
|
81 |
jQuery( 'a[href="admin.php?page=ninja-forms#new-form"]' ).on( 'click', function( event ){
|
82 |
event.preventDefault();
|
83 |
-
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
86 |
} );
|
87 |
|
88 |
jQuery( 'a[href="admin.php?page=ninja-forms#apps"]' ).on( 'click', function( event ){
|
89 |
event.preventDefault();
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
92 |
|
93 |
} );
|
94 |
|
95 |
jQuery( 'a[href="admin.php?page=ninja-forms"]' ).on( 'click', function( event ){
|
96 |
event.preventDefault();
|
97 |
-
|
98 |
-
|
99 |
-
|
|
|
|
|
|
|
100 |
} );
|
101 |
|
102 |
/**
|
80 |
|
81 |
jQuery( 'a[href="admin.php?page=ninja-forms#new-form"]' ).on( 'click', function( event ){
|
82 |
event.preventDefault();
|
83 |
+
// We won't allow access to add forms if there are required updates
|
84 |
+
if( "1" !== nfAdmin.requiredUpdates ) {
|
85 |
+
window.location.hash = 'new-form';
|
86 |
+
nfRadio.channel( 'dashboard' ).request( 'show:widgets' );
|
87 |
+
nfRadio.channel( 'widget-forms' ).request( 'show:newFormsGrid' );
|
88 |
+
}
|
89 |
} );
|
90 |
|
91 |
jQuery( 'a[href="admin.php?page=ninja-forms#apps"]' ).on( 'click', function( event ){
|
92 |
event.preventDefault();
|
93 |
+
// We won't allow access to the apps tab if there are required updates
|
94 |
+
if( "1" !== nfAdmin.requiredUpdates ) {
|
95 |
+
window.location.hash = 'apps';
|
96 |
+
nfRadio.channel( 'dashboard' ).request( 'show:apps' );
|
97 |
+
}
|
98 |
|
99 |
} );
|
100 |
|
101 |
jQuery( 'a[href="admin.php?page=ninja-forms"]' ).on( 'click', function( event ){
|
102 |
event.preventDefault();
|
103 |
+
// We won't allow access to the dashboard if there are required updates
|
104 |
+
if( "1" !== nfAdmin.requiredUpdates ) {
|
105 |
+
window.location.hash = 'forms';
|
106 |
+
nfRadio.channel( 'dashboard' ).request( 'show:widgets' );
|
107 |
+
nfRadio.channel( 'widget-forms' ).request( 'show:formsTable' );
|
108 |
+
}
|
109 |
} );
|
110 |
|
111 |
/**
|
client/dashboard/views/dashboardView.js
CHANGED
@@ -6,7 +6,7 @@
|
|
6 |
* @copyright (c) 2017 WP Ninjas
|
7 |
* @since 3.2
|
8 |
*/
|
9 |
-
define( [ 'views/sections/widgets.js', 'views/sections/services.js', 'views/sections/apps.js', 'views/sections/memberships.js', 'views/oauth.js', 'views/promotion.js' ], function( WidgetView, ServicesView, AppsView, MembershipsView, OAuthView, PromotionView ) {
|
10 |
var view = Marionette.View.extend( {
|
11 |
template: "#tmpl-nf-dashboard",
|
12 |
|
@@ -20,33 +20,49 @@ define( [ 'views/sections/widgets.js', 'views/sections/services.js', 'views/sect
|
|
20 |
|
21 |
events: {
|
22 |
'click .widgets a': function(e){
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
|
|
|
|
27 |
},
|
28 |
'click .services a': function(e){
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
|
|
|
|
33 |
},
|
34 |
'click .apps a': function(e){
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
|
|
39 |
},
|
40 |
'click .memberships a': function(e){
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
|
|
45 |
},
|
46 |
},
|
47 |
|
48 |
initialize: function() {
|
49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
switch( window.location.hash ) {
|
51 |
case '#apps':
|
52 |
this.currentView = 'apps';
|
@@ -57,6 +73,9 @@ define( [ 'views/sections/widgets.js', 'views/sections/services.js', 'views/sect
|
|
57 |
case '#memberships':
|
58 |
this.currentView = 'memberships';
|
59 |
break;
|
|
|
|
|
|
|
60 |
case '#widgets':
|
61 |
default:
|
62 |
this.currentView = 'widgets';
|
@@ -67,29 +86,43 @@ define( [ 'views/sections/widgets.js', 'views/sections/services.js', 'views/sect
|
|
67 |
* TODO: Clean this up.
|
68 |
*/
|
69 |
nfRadio.channel( 'dashboard' ).reply( 'show:widgets', function(){
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
|
|
|
|
74 |
}, this );
|
75 |
nfRadio.channel( 'dashboard' ).reply( 'show:services', function(){
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
|
|
|
|
80 |
}, this );
|
81 |
nfRadio.channel( 'dashboard' ).reply( 'show:apps', function(){
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
|
|
|
|
86 |
}, this );
|
87 |
},
|
88 |
|
89 |
onRender: function() {
|
90 |
|
91 |
if( useServices ) this.showChildView( 'notices', new OAuthView() );
|
92 |
-
if( useServices
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
switch( window.location.hash ) {
|
95 |
case '#apps':
|
@@ -101,6 +134,9 @@ define( [ 'views/sections/widgets.js', 'views/sections/services.js', 'views/sect
|
|
101 |
case '#services':
|
102 |
var childView = new ServicesView();
|
103 |
break;
|
|
|
|
|
|
|
104 |
case '#widgets':
|
105 |
default:
|
106 |
var childView = new WidgetView();
|
@@ -242,42 +278,7 @@ define( [ 'views/sections/widgets.js', 'views/sections/services.js', 'views/sect
|
|
242 |
} );
|
243 |
} );
|
244 |
} // If we've been told to run cleanup...
|
245 |
-
|
246 |
-
// Get the context for later.
|
247 |
-
var that = this;
|
248 |
-
// Define our modal options.
|
249 |
-
var modalData = {
|
250 |
-
width: 450,
|
251 |
-
closeOnClick: false,
|
252 |
-
closeOnEsc: false,
|
253 |
-
content: nfi18n.cleanupContent,
|
254 |
-
useProgressBar: true,
|
255 |
-
loadingText: nfi18n.cleanupLoading,
|
256 |
-
btnSecondary: {
|
257 |
-
text: nfi18n.cleanupSecondary,
|
258 |
-
callback: function() {
|
259 |
-
cleanupModal.toggleModal( false );
|
260 |
-
}
|
261 |
-
},
|
262 |
-
btnPrimary: {
|
263 |
-
text: nfi18n.cleanupPrimary,
|
264 |
-
callback: function() {
|
265 |
-
// Prevent the user from leaving without firing an alert.
|
266 |
-
jQuery( window ).bind( 'beforeunload', function() {
|
267 |
-
return 'Are you sure? Leaving before the process completes could cause damage to your data.';
|
268 |
-
} );
|
269 |
-
// Hide the buttons.
|
270 |
-
cleanupModal.maybeShowActions( false );
|
271 |
-
// Show the progress bar.
|
272 |
-
cleanupModal.maybeShowProgress( true );
|
273 |
-
// Begin our cleanup process.
|
274 |
-
that.cleanupProcess( that, -1, cleanupModal );
|
275 |
-
},
|
276 |
-
},
|
277 |
-
};
|
278 |
-
// Setup our modal.
|
279 |
-
var cleanupModal = new NinjaModal( modalData );
|
280 |
-
}
|
281 |
// If form telemetry is defined...
|
282 |
// AND if we should run it...
|
283 |
if ( 'undefined' !== typeof nfAdmin.formTelemetry && 1 == nfAdmin.formTelemetry ) {
|
@@ -310,56 +311,6 @@ define( [ 'views/sections/widgets.js', 'views/sections/services.js', 'views/sect
|
|
310 |
},
|
311 |
}
|
312 |
},
|
313 |
-
|
314 |
-
/**
|
315 |
-
* Function to manage our data cleanup batch process response.
|
316 |
-
*
|
317 |
-
* @since 3.3.1
|
318 |
-
*
|
319 |
-
* @param context (this) The context at the time of function definition.
|
320 |
-
* @param steps (int) The total number of steps in this process.
|
321 |
-
* @param modal (jBox) A reference to the modal where this process is running.
|
322 |
-
*/
|
323 |
-
cleanupProcess: function( context, steps, modal ) {
|
324 |
-
var data = {
|
325 |
-
action: 'nf_batch_process',
|
326 |
-
batch_type: 'data_cleanup',
|
327 |
-
security: nfAdmin.batchNonce
|
328 |
-
};
|
329 |
-
jQuery.post( ajaxurl, data, function( response ) {
|
330 |
-
response = JSON.parse( response );
|
331 |
-
// If we're done...
|
332 |
-
if ( response.batch_complete ) {
|
333 |
-
// Push our progress bar to 100%.
|
334 |
-
modal.setProgress( 100 );
|
335 |
-
// Allow the user to leave the page now.
|
336 |
-
jQuery( window ).unbind( 'beforeunload' );
|
337 |
-
modal.toggleModal( false );
|
338 |
-
// Exit.
|
339 |
-
return false;
|
340 |
-
}
|
341 |
-
// If we do not yet have a determined number of steps...
|
342 |
-
if ( -1 == steps ) {
|
343 |
-
// If step_toal is defined...
|
344 |
-
if ( 'undefined' != typeof response.step_total ) {
|
345 |
-
// Use the step_total.
|
346 |
-
steps = response.step_total;
|
347 |
-
} // Otherwise... (step_total is not defined)
|
348 |
-
else {
|
349 |
-
// Use step_remaining.
|
350 |
-
steps = response.step_remaining;
|
351 |
-
}
|
352 |
-
}
|
353 |
-
// Calculate our current step.
|
354 |
-
var step = steps - response.step_remaining;
|
355 |
-
// Calculate our maximum progress for this step.
|
356 |
-
var maxProgress = Math.round( step / steps * 100 );
|
357 |
-
// Increment the progress.
|
358 |
-
modal.incrementProgress ( maxProgress );
|
359 |
-
// Recall our function...
|
360 |
-
context.cleanupProcess( context, steps, modal );
|
361 |
-
} );
|
362 |
-
}
|
363 |
} );
|
364 |
return view;
|
365 |
} );
|
6 |
* @copyright (c) 2017 WP Ninjas
|
7 |
* @since 3.2
|
8 |
*/
|
9 |
+
define( [ 'views/sections/widgets.js', 'views/sections/services.js', 'views/sections/apps.js', 'views/sections/memberships.js', 'views/oauth.js', 'views/promotion.js', 'views/sections/requiredUpdates.js' ], function( WidgetView, ServicesView, AppsView, MembershipsView, OAuthView, PromotionView, RequiredUpdatesView ) {
|
10 |
var view = Marionette.View.extend( {
|
11 |
template: "#tmpl-nf-dashboard",
|
12 |
|
20 |
|
21 |
events: {
|
22 |
'click .widgets a': function(e){
|
23 |
+
if( "1" != nfAdmin.requiredUpdates ) {
|
24 |
+
this.showChildView( 'content', new WidgetView() );
|
25 |
+
jQuery( '.' + this.currentView).find( 'a' ).removeClass( 'active' );
|
26 |
+
e.target.classList.add( 'active' );
|
27 |
+
this.currentView = 'widgets';
|
28 |
+
}
|
29 |
},
|
30 |
'click .services a': function(e){
|
31 |
+
if( "1" != nfAdmin.requiredUpdates ) {
|
32 |
+
this.showChildView( 'content', new ServicesView() );
|
33 |
+
jQuery( '.' + this.currentView).find( 'a' ).removeClass( 'active' );
|
34 |
+
e.target.classList.add( 'active' );
|
35 |
+
this.currentView = 'services';
|
36 |
+
}
|
37 |
},
|
38 |
'click .apps a': function(e){
|
39 |
+
if( "1" != nfAdmin.requiredUpdates ) {
|
40 |
+
this.showChildView( 'content', new AppsView() );
|
41 |
+
jQuery( '.' + this.currentView).find( 'a' ).removeClass( 'active' );
|
42 |
+
e.target.classList.add( 'active' );
|
43 |
+
this.currentView = 'apps';
|
44 |
+
}
|
45 |
},
|
46 |
'click .memberships a': function(e){
|
47 |
+
if( "1" != nfAdmin.requiredUpdates ) {
|
48 |
+
this.showChildView( 'content', new MembershipsView() );
|
49 |
+
jQuery( '.' + this.currentView).find( 'a' ).removeClass( 'active' );
|
50 |
+
e.target.classList.add( 'active' );
|
51 |
+
this.currentView = 'memberships';
|
52 |
+
}
|
53 |
},
|
54 |
},
|
55 |
|
56 |
initialize: function() {
|
57 |
|
58 |
+
if( "1" === nfAdmin.requiredUpdates ) {
|
59 |
+
// if we have required updates, redirect them
|
60 |
+
window.location.hash = '#requiredUpdates';
|
61 |
+
} else if ( '#requiredUpdates' === window.location.hash ) {
|
62 |
+
// if no updates, but someone hits update url, give the the dashboard
|
63 |
+
window.location.hash = '';
|
64 |
+
}
|
65 |
+
|
66 |
switch( window.location.hash ) {
|
67 |
case '#apps':
|
68 |
this.currentView = 'apps';
|
73 |
case '#memberships':
|
74 |
this.currentView = 'memberships';
|
75 |
break;
|
76 |
+
case '#requiredUpdates':
|
77 |
+
this.currentView = 'requiredUpdates';
|
78 |
+
break;
|
79 |
case '#widgets':
|
80 |
default:
|
81 |
this.currentView = 'widgets';
|
86 |
* TODO: Clean this up.
|
87 |
*/
|
88 |
nfRadio.channel( 'dashboard' ).reply( 'show:widgets', function(){
|
89 |
+
if( "1" != nfAdmin.requiredUpdates ) {
|
90 |
+
this.showChildView('content', new WidgetView() );
|
91 |
+
jQuery( 'nav.sections a.active' ).removeClass( 'active' );
|
92 |
+
jQuery( 'nav.sections .widgets a' ).addClass( 'active' );
|
93 |
+
this.currentView = 'widgets';
|
94 |
+
}
|
95 |
}, this );
|
96 |
nfRadio.channel( 'dashboard' ).reply( 'show:services', function(){
|
97 |
+
if( "1" != nfAdmin.requiredUpdates ) {
|
98 |
+
this.showChildView('content', new ServicesView() );
|
99 |
+
jQuery( 'nav.sections a.active' ).removeClass( 'active' );
|
100 |
+
jQuery( 'nav.sections .services a' ).addClass( 'active' );
|
101 |
+
this.currentView = 'services';
|
102 |
+
}
|
103 |
}, this );
|
104 |
nfRadio.channel( 'dashboard' ).reply( 'show:apps', function(){
|
105 |
+
if( "1" != nfAdmin.requiredUpdates ) {
|
106 |
+
this.showChildView('content', new AppsView() );
|
107 |
+
jQuery( 'nav.sections a.active' ).removeClass( 'active' );
|
108 |
+
jQuery( 'nav.sections .apps a' ).addClass( 'active' );
|
109 |
+
this.currentView = 'apps';
|
110 |
+
}
|
111 |
}, this );
|
112 |
},
|
113 |
|
114 |
onRender: function() {
|
115 |
|
116 |
if( useServices ) this.showChildView( 'notices', new OAuthView() );
|
117 |
+
if( useServices && '1' !== nfAdmin.requiredUpdates ) {
|
118 |
+
this.showChildView( 'promotions', new PromotionView() );
|
119 |
+
}
|
120 |
+
|
121 |
+
// if no updates and someone hits the update url, give them the dashboard
|
122 |
+
if( '0' === nfAdmin.requiredUpdates
|
123 |
+
&& '#requiredUpdates' === window.location.hash ) {
|
124 |
+
window.location.hash = '';
|
125 |
+
}
|
126 |
|
127 |
switch( window.location.hash ) {
|
128 |
case '#apps':
|
134 |
case '#services':
|
135 |
var childView = new ServicesView();
|
136 |
break;
|
137 |
+
case '#requiredUpdates':
|
138 |
+
var childView = new RequiredUpdatesView();
|
139 |
+
break;
|
140 |
case '#widgets':
|
141 |
default:
|
142 |
var childView = new WidgetView();
|
278 |
} );
|
279 |
} );
|
280 |
} // If we've been told to run cleanup...
|
281 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
282 |
// If form telemetry is defined...
|
283 |
// AND if we should run it...
|
284 |
if ( 'undefined' !== typeof nfAdmin.formTelemetry && 1 == nfAdmin.formTelemetry ) {
|
311 |
},
|
312 |
}
|
313 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
314 |
} );
|
315 |
return view;
|
316 |
} );
|
client/dashboard/views/sections/requiredUpdates.js
ADDED
@@ -0,0 +1,345 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* @package Ninja Forms
|
3 |
+
* @subpackage Dashboard
|
4 |
+
* @copyright (c) 2017 WP Ninjas
|
5 |
+
* @since 3.2
|
6 |
+
*/
|
7 |
+
define( [], function() {
|
8 |
+
var view = Marionette.View.extend( {
|
9 |
+
template: '#tmpl-nf-requiredUpdates',
|
10 |
+
|
11 |
+
updates: [], //an object containing updates to be performed
|
12 |
+
|
13 |
+
currentUpdate: 0, // current update out of totalUpdate
|
14 |
+
|
15 |
+
totalUpdates: -1, // we start with -1 and overwrite it
|
16 |
+
|
17 |
+
updatesRemaining: -1,// how many update are left
|
18 |
+
|
19 |
+
ui: {
|
20 |
+
requiredUpdates: '.nf-required-update',
|
21 |
+
|
22 |
+
},
|
23 |
+
|
24 |
+
/**
|
25 |
+
* When we render this section, check for updates
|
26 |
+
*/
|
27 |
+
onRender: function() {
|
28 |
+
this.getRequiredUpdates();
|
29 |
+
},
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Set up the initial on click for the button, as it changes after
|
33 |
+
* the updates are done
|
34 |
+
*/
|
35 |
+
setButtonClickEvent: function() {
|
36 |
+
var that = this;
|
37 |
+
|
38 |
+
// tell the button to do updates on click
|
39 |
+
jQuery( '#nf-required-updates-btn' )
|
40 |
+
.off( 'click' )
|
41 |
+
.on( 'click', function( e ) {
|
42 |
+
e.preventDefault();
|
43 |
+
that.doRequiredUpdates();
|
44 |
+
jQuery( this ).hide();
|
45 |
+
} );
|
46 |
+
},
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Get any required updates that might need to happen
|
50 |
+
*/
|
51 |
+
getRequiredUpdates: function() {
|
52 |
+
|
53 |
+
var that = this;
|
54 |
+
jQuery.get( ajaxurl, { action: 'nf_required_update' } )
|
55 |
+
.then( function( response ) {
|
56 |
+
var res = JSON.parse( response );
|
57 |
+
|
58 |
+
if( 0 === res.errors.length) {
|
59 |
+
// get the number of updates
|
60 |
+
that.totalUpdates = res.data.updates.length;
|
61 |
+
|
62 |
+
// get the updates into an array
|
63 |
+
that.updates = res.data.updates;
|
64 |
+
|
65 |
+
if( 0 < that.updates.length ) {
|
66 |
+
that.requiredUpdates = that.updates.length;
|
67 |
+
// now that we have updates, let's make our table
|
68 |
+
that.constructUpdateTable();
|
69 |
+
|
70 |
+
// set up the click event for the button to do updates
|
71 |
+
that.setButtonClickEvent();
|
72 |
+
} else {
|
73 |
+
window.location = window.location.origin +
|
74 |
+
window.location.pathname + window.location.search;
|
75 |
+
}
|
76 |
+
|
77 |
+
}
|
78 |
+
} );
|
79 |
+
},
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Construct a table that shows required updates
|
83 |
+
*/
|
84 |
+
constructUpdateTable: function() {
|
85 |
+
var that = this;
|
86 |
+
// get the table and header
|
87 |
+
var updateTable = document.getElementById( 'nf-upgrades-table' );
|
88 |
+
var tableHeader = updateTable.getElementsByTagName( 'thead' )[0];
|
89 |
+
|
90 |
+
// create the header row
|
91 |
+
var headerRow = document.createElement( 'tr' );
|
92 |
+
|
93 |
+
// create the header cell for update name column
|
94 |
+
var updateNameHeaderCell = document.createElement( 'th' );
|
95 |
+
updateNameHeaderCell.innerHTML = "Update";
|
96 |
+
updateNameHeaderCell.classList.add( "nf-update-name-cell" );
|
97 |
+
|
98 |
+
// create header cell for progress bar column
|
99 |
+
var updateProgressHeaderCell = document.createElement( 'th' );
|
100 |
+
updateProgressHeaderCell.innerHTML = "Progress";
|
101 |
+
updateProgressHeaderCell.classList.add( "nf-update-progress-cell" );
|
102 |
+
|
103 |
+
// append header cells to header row
|
104 |
+
headerRow.appendChild( updateNameHeaderCell );
|
105 |
+
headerRow.appendChild( updateProgressHeaderCell );
|
106 |
+
|
107 |
+
// append header row to table header
|
108 |
+
tableHeader.appendChild( headerRow );
|
109 |
+
|
110 |
+
// get the table body
|
111 |
+
var tableBody = updateTable.getElementsByTagName( 'tbody' )[0];
|
112 |
+
|
113 |
+
// create a table row for each required update
|
114 |
+
jQuery.each( this.updates, function( i, update ) {
|
115 |
+
var tableRow = document.createElement( 'tr' );
|
116 |
+
|
117 |
+
var updateNameCell = document.createElement( 'td' );
|
118 |
+
updateNameCell.innerHTML = update.nicename;
|
119 |
+
|
120 |
+
var updateProgressCell = document.createElement( 'td' );
|
121 |
+
var updateProgressBar = document.createElement( 'div' );
|
122 |
+
|
123 |
+
updateProgressBar.id = "update-progress-" + i;
|
124 |
+
|
125 |
+
var newProgressBar = that.createNewProgressBar( i );
|
126 |
+
|
127 |
+
updateProgressBar.appendChild( newProgressBar );
|
128 |
+
|
129 |
+
updateProgressCell.appendChild( updateProgressBar );
|
130 |
+
|
131 |
+
tableRow.appendChild( updateNameCell );
|
132 |
+
tableRow.appendChild( updateProgressCell );
|
133 |
+
|
134 |
+
tableBody.appendChild( tableRow );
|
135 |
+
} );
|
136 |
+
|
137 |
+
var updateBtn = document.getElementById( 'nf-required-updates-btn' );
|
138 |
+
updateBtn.style.display = 'block';
|
139 |
+
|
140 |
+
},
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Function that starts running required updates if we have any
|
144 |
+
*/
|
145 |
+
|
146 |
+
doRequiredUpdates: function() {
|
147 |
+
// set the window.location hash just in case
|
148 |
+
window.location.hash = '#requiredUpdates';
|
149 |
+
|
150 |
+
var context = this;
|
151 |
+
|
152 |
+
// disable the button once we've clicked
|
153 |
+
jQuery( '#nf-required-updates-btn' ).addClass( 'disabled' ).attr( 'disabled', 'disabled' );
|
154 |
+
|
155 |
+
//make initial call to initiate required updates
|
156 |
+
jQuery.post( ajaxurl, { action: 'nf_required_update', security: nfAdmin.updateNonce } )
|
157 |
+
.then( function( response ) {
|
158 |
+
var res = JSON.parse( response );
|
159 |
+
|
160 |
+
// if we still have updates remaining, call the ajax again
|
161 |
+
if( res.updatesRemaining > 0 ) {
|
162 |
+
|
163 |
+
/**
|
164 |
+
* We had to add this if/else b/c the classes were returning
|
165 |
+
* results where the currentStep and stepsTotal values
|
166 |
+
* were the same, but the updatesRemaining value had changed,
|
167 |
+
* thus causing any progress bars after the first to
|
168 |
+
* automatically show 100% even though the updates continue
|
169 |
+
*/
|
170 |
+
if( context.updatesRemaining !== res.updatesRemaining
|
171 |
+
&& res.currentStep === res.stepsTotal ) {
|
172 |
+
|
173 |
+
// finish the current update
|
174 |
+
context.finishUpdate( context.currentUpdate );
|
175 |
+
|
176 |
+
// update the remaining updates
|
177 |
+
context.updatesRemaining = res.updatesRemaining;
|
178 |
+
} else {
|
179 |
+
// this will show progress bars that are processing
|
180 |
+
context.showProgressBars( res );
|
181 |
+
|
182 |
+
// update the remaining updates
|
183 |
+
context.updatesRemaining = res.updatesRemaining;
|
184 |
+
}
|
185 |
+
|
186 |
+
// keep moving through required updates
|
187 |
+
context.doRequiredUpdates();
|
188 |
+
} else {
|
189 |
+
|
190 |
+
// finish the current update
|
191 |
+
context.finishUpdate( context.currentUpdate );
|
192 |
+
|
193 |
+
// set the globle required updates variable to 0
|
194 |
+
nfAdmin.requiredUpdates = 0;
|
195 |
+
|
196 |
+
// remove the disabled items and set the click to the dashboard
|
197 |
+
jQuery( '#nf-required-updates-btn' )
|
198 |
+
.removeClass( 'disabled' )
|
199 |
+
.removeAttr( 'disabled' )
|
200 |
+
.val( 'Go To Dashboard' )
|
201 |
+
.off( 'click' )
|
202 |
+
.on( 'click', function( e ) {
|
203 |
+
e.preventDefault();
|
204 |
+
window.location = window.location.origin +
|
205 |
+
window.location.pathname + window.location.search;
|
206 |
+
} )
|
207 |
+
.show();
|
208 |
+
|
209 |
+
console.log( "UPDATES DONE" );
|
210 |
+
}
|
211 |
+
});
|
212 |
+
},
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Function create and display progress bars.
|
216 |
+
* We create one for each update
|
217 |
+
*
|
218 |
+
* @param data
|
219 |
+
*/
|
220 |
+
showProgressBars: function( data ) {
|
221 |
+
var update = this.totalUpdates - data.updatesRemaining;
|
222 |
+
var progress = data.currentStep;
|
223 |
+
var totalSteps = data.stepsTotal;
|
224 |
+
|
225 |
+
// get the progress bar we are dealing with
|
226 |
+
var currentProgressBar = document.getElementById( 'nf_progressBar_' + update );
|
227 |
+
|
228 |
+
if( null == currentProgressBar ) {
|
229 |
+
// if the element requested is null, then we know this is a new update
|
230 |
+
this.currentUpdate += 1;
|
231 |
+
if( 1 === this.currentUpdate && -1 === this.totalUpdates ) {
|
232 |
+
// the initial 'update' value with be how many remaining(total updates)
|
233 |
+
this.totalUpdates = update;
|
234 |
+
}
|
235 |
+
// create a new progress bar if it doesn't exist
|
236 |
+
currentProgressBar = this.createNewProgressBar( update );
|
237 |
+
}
|
238 |
+
|
239 |
+
// update the progress bar
|
240 |
+
this.incrementProgress( update, progress, totalSteps)
|
241 |
+
},
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Create a new progress bar for the new update
|
245 |
+
*
|
246 |
+
* @param update
|
247 |
+
*
|
248 |
+
* @returns newProgressBarContainer
|
249 |
+
*/
|
250 |
+
createNewProgressBar: function( update ) {
|
251 |
+
//create new container
|
252 |
+
var newProgressBarContainer = document.createElement( 'div' );
|
253 |
+
newProgressBarContainer.id = 'nf_progressBar_' + update;
|
254 |
+
newProgressBarContainer.classList.add( 'jBox-content' );
|
255 |
+
newProgressBarContainer.style.display = 'none';
|
256 |
+
|
257 |
+
// create new progress bar
|
258 |
+
var newProgressBar = document.createElement( 'div' );
|
259 |
+
newProgressBar.classList.add( 'nf-progress-bar' );
|
260 |
+
|
261 |
+
// create the slider
|
262 |
+
var newProgressSlider = document.createElement( 'div' );
|
263 |
+
newProgressSlider.id = 'nf-progress-bar-slider-' + update;
|
264 |
+
newProgressSlider.classList.add( 'nf-progress-bar-slider' );
|
265 |
+
|
266 |
+
// append the slider to the progress bar
|
267 |
+
newProgressBar.appendChild( newProgressSlider );
|
268 |
+
|
269 |
+
// append the progress bar to the container
|
270 |
+
newProgressBarContainer.appendChild( newProgressBar );
|
271 |
+
|
272 |
+
return newProgressBarContainer;
|
273 |
+
},
|
274 |
+
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Increment the progress based on total steps and current progress
|
278 |
+
*
|
279 |
+
* @param update
|
280 |
+
* @param progress
|
281 |
+
* @param totalSteps
|
282 |
+
*/
|
283 |
+
incrementProgress: function( update, currentStep, totalSteps ) {
|
284 |
+
var progressBarContainer = document.getElementById( 'nf_progressBar_' + update );
|
285 |
+
progressBarContainer.style.display = 'block';
|
286 |
+
|
287 |
+
// get the slider element
|
288 |
+
var progressBar = document.getElementById( 'nf-progress-bar-slider-' + update );
|
289 |
+
|
290 |
+
// get the current progress(%) based on total steps and currentStep
|
291 |
+
var newValue = ( Number( currentStep ) / Number( totalSteps ) ) * 100;
|
292 |
+
|
293 |
+
// Get our current progress.
|
294 |
+
var currentProgress = progressBar.offsetWidth / progressBar.parentElement.offsetWidth * 100;
|
295 |
+
|
296 |
+
// If the new value is greater than the currentProgress, update it
|
297 |
+
if ( newValue > currentProgress ) {
|
298 |
+
this.setProgress( update, newValue );
|
299 |
+
}
|
300 |
+
},
|
301 |
+
|
302 |
+
/**
|
303 |
+
* Sets the current progress for the current progress bar
|
304 |
+
*
|
305 |
+
* @param update
|
306 |
+
* @param percent
|
307 |
+
*/
|
308 |
+
setProgress: function( update, percent ) {
|
309 |
+
// Update the width of the element as a percentage.
|
310 |
+
var progressBar = document.getElementById( 'nf-progress-bar-slider-' + update );
|
311 |
+
progressBar.style.width = percent + '%';
|
312 |
+
|
313 |
+
if( 100 <= percent ) {
|
314 |
+
this.finishUpdate( update );
|
315 |
+
}
|
316 |
+
},
|
317 |
+
|
318 |
+
/**
|
319 |
+
* If an update is done, then let's set it to done in the updates table
|
320 |
+
*/
|
321 |
+
finishUpdate: function( update ) {
|
322 |
+
// get the progress bar container of the one that is done
|
323 |
+
var progressBarContainer = document.getElementById( 'nf_progressBar_' + update );
|
324 |
+
|
325 |
+
// get it's parent table cell
|
326 |
+
var progressCell = progressBarContainer.parentNode;
|
327 |
+
|
328 |
+
// remove the progress bar element
|
329 |
+
progressCell.removeChild( progressBarContainer );
|
330 |
+
|
331 |
+
// add the span with 'Done' check mark
|
332 |
+
var finishedSpan = document.createElement( 'span' );
|
333 |
+
finishedSpan.classList.add( 'dashicons' );
|
334 |
+
finishedSpan.classList.add( 'dashicons-yes' );
|
335 |
+
|
336 |
+
// append it to the progress cell
|
337 |
+
progressCell.appendChild( finishedSpan );
|
338 |
+
|
339 |
+
// update the current update
|
340 |
+
this.currentUpdate = this.currentUpdate + 1;
|
341 |
+
|
342 |
+
}
|
343 |
+
} );
|
344 |
+
return view;
|
345 |
+
} );
|
client/dashboard/views/widgets/forms/forms.js
CHANGED
@@ -25,8 +25,8 @@ define( [
|
|
25 |
},
|
26 |
|
27 |
initialize: function(){
|
28 |
-
nfRadio.channel( 'widget-forms' ).reply( 'show:newFormsGrid', this.showNewFormGrid, this );
|
29 |
-
nfRadio.channel( 'widget-forms' ).reply( 'show:formsTable', this.showFormsTable, this );
|
30 |
},
|
31 |
|
32 |
onRender: function() {
|
@@ -57,7 +57,6 @@ define( [
|
|
57 |
},
|
58 |
|
59 |
showFormsTable: function(){
|
60 |
-
console.log( this );
|
61 |
window.location.hash = 'forms';
|
62 |
this.showChildView( 'content', new FormsTableView() );
|
63 |
nfRadio.channel( 'widget-forms' ).trigger( 'change:content' );
|
25 |
},
|
26 |
|
27 |
initialize: function(){
|
28 |
+
// nfRadio.channel( 'widget-forms' ).reply( 'show:newFormsGrid', this.showNewFormGrid, this );
|
29 |
+
// nfRadio.channel( 'widget-forms' ).reply( 'show:formsTable', this.showFormsTable, this );
|
30 |
},
|
31 |
|
32 |
onRender: function() {
|
57 |
},
|
58 |
|
59 |
showFormsTable: function(){
|
|
|
60 |
window.location.hash = 'forms';
|
61 |
this.showChildView( 'content', new FormsTableView() );
|
62 |
nfRadio.channel( 'widget-forms' ).trigger( 'change:content' );
|
client/dashboard/views/widgets/forms/newFormTemplate.js
CHANGED
@@ -21,23 +21,41 @@ define( [], function() {
|
|
21 |
* @return {void}
|
22 |
*/
|
23 |
maybeOpenModal: function( e ) {
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
|
|
|
|
39 |
|
40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
}
|
42 |
|
43 |
} );
|
21 |
* @return {void}
|
22 |
*/
|
23 |
maybeOpenModal: function( e ) {
|
24 |
+
e.preventDefault();
|
25 |
+
// If this is an ad, open the ad modal.
|
26 |
+
if ( 'ad' == this.model.get( 'type' ) ) {
|
27 |
+
// Open our jBox modal
|
28 |
+
var modal = new jBox( 'Modal', {
|
29 |
+
width: 450,
|
30 |
+
title: this.model.get( 'modal-title' ),
|
31 |
+
content: this.model.get( 'modal-content' ),
|
32 |
+
closeButton: 'box',
|
33 |
+
blockScroll: true
|
34 |
+
} );
|
35 |
|
36 |
+
modal.open();
|
37 |
+
} else { // This is a template, so import it using the batch processor.
|
38 |
+
// Settings object for our batch processor
|
39 |
+
var settings = {
|
40 |
+
// Batch processor slug. Must match what we have set in our PHP settings array.
|
41 |
+
batch_type: 'import_form_template',
|
42 |
+
loadingText: 'Importing...',
|
43 |
+
extraData: { template: this.model.get( 'id' ) },
|
44 |
+
onCompleteCallback: function( response ) {
|
45 |
+
// Bail if we don't return a form ID.
|
46 |
+
if ( 'undefined' == typeof response.form_id ) return false;
|
47 |
|
48 |
+
window.location.href = nfAdmin.builderURL + response.form_id;
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Instantiate our batch processor.
|
54 |
+
*
|
55 |
+
* This will open the modal and present the user with content.
|
56 |
+
*/
|
57 |
+
new NinjaBatchProcessor( settings );
|
58 |
+
}
|
59 |
}
|
60 |
|
61 |
} );
|
deprecated/ninja-forms.php
CHANGED
@@ -265,7 +265,7 @@ class Ninja_Forms {
|
|
265 |
|
266 |
// Plugin version
|
267 |
if ( ! defined( 'NF_PLUGIN_VERSION' ) )
|
268 |
-
define( 'NF_PLUGIN_VERSION', '3.
|
269 |
|
270 |
// Plugin Folder Path
|
271 |
if ( ! defined( 'NF_PLUGIN_DIR' ) )
|
265 |
|
266 |
// Plugin version
|
267 |
if ( ! defined( 'NF_PLUGIN_VERSION' ) )
|
268 |
+
define( 'NF_PLUGIN_VERSION', '3.4.0' );
|
269 |
|
270 |
// Plugin Folder Path
|
271 |
if ( ! defined( 'NF_PLUGIN_DIR' ) )
|
includes/AJAX/Controllers/Form.php
CHANGED
@@ -12,6 +12,7 @@ class NF_AJAX_Controllers_Form extends NF_Abstracts_Controller
|
|
12 |
add_action( 'wp_ajax_nopriv_nf_ajax_get_new_nonce', array( $this, 'get_new_nonce' ) );
|
13 |
add_action( 'wp_ajax_nf_save_form', array( $this, 'save' ) );
|
14 |
add_action( 'wp_ajax_nf_delete_form', array( $this, 'delete' ) );
|
|
|
15 |
}
|
16 |
|
17 |
public function plugins_loaded()
|
@@ -141,6 +142,21 @@ class NF_AJAX_Controllers_Form extends NF_Abstracts_Controller
|
|
141 |
$this->_respond();
|
142 |
}
|
143 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
/**
|
145 |
* Let's generate a unique nonce for each form render so that we don't get
|
146 |
* caught with an expiring nonce accidentally and fail to allow a submission
|
12 |
add_action( 'wp_ajax_nopriv_nf_ajax_get_new_nonce', array( $this, 'get_new_nonce' ) );
|
13 |
add_action( 'wp_ajax_nf_save_form', array( $this, 'save' ) );
|
14 |
add_action( 'wp_ajax_nf_delete_form', array( $this, 'delete' ) );
|
15 |
+
add_action( 'wp_ajax_nf_remove_maintenance_mode', array( $this, 'remove_maintenance_mode' ) );
|
16 |
}
|
17 |
|
18 |
public function plugins_loaded()
|
142 |
$this->_respond();
|
143 |
}
|
144 |
|
145 |
+
/**
|
146 |
+
* This function will take all form out of maintenance mode( in case some
|
147 |
+
* are still in maintenance mode after some required updates )
|
148 |
+
*
|
149 |
+
* @since 3.4.0
|
150 |
+
*/
|
151 |
+
public function remove_maintenance_mode() {
|
152 |
+
|
153 |
+
check_ajax_referer( 'ninja_forms_settings_nonce', 'security' );
|
154 |
+
|
155 |
+
WPN_Helper::set_forms_maintenance_mode();
|
156 |
+
|
157 |
+
$this->_respond();
|
158 |
+
}
|
159 |
+
|
160 |
/**
|
161 |
* Let's generate a unique nonce for each form render so that we don't get
|
162 |
* caught with an expiring nonce accidentally and fail to allow a submission
|
includes/AJAX/Controllers/Submission.php
CHANGED
@@ -57,6 +57,19 @@ class NF_AJAX_Controllers_Submission extends NF_Abstracts_Controller
|
|
57 |
$this->_respond();
|
58 |
}
|
59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
if( $this->is_preview() ) {
|
61 |
|
62 |
$this->_form_cache = get_user_option( 'nf_form_preview_' . $this->_form_id );
|
57 |
$this->_respond();
|
58 |
}
|
59 |
|
60 |
+
// Check to see if our form is maintenance mode.
|
61 |
+
$is_maintenance = WPN_Helper::form_in_maintenance( $this->_form_id );
|
62 |
+
|
63 |
+
/*
|
64 |
+
* If our form is in maintenance mode then, stop processing and throw an error with a link
|
65 |
+
* back to the form.
|
66 |
+
*/
|
67 |
+
if ( $is_maintenance ) {
|
68 |
+
$this->_errors[ 'form' ][] = apply_filters( 'nf_maintenance_message', __( 'This form is currently undergoing maintenance. Please ', 'ninja-forms' )
|
69 |
+
. '<a href="' . $_SERVER[ 'HTTP_REFERER' ] . '">' . __( 'click here ', 'ninja-forms' ) . '</a>' . __( 'to reload the form and try again.', 'ninja-forms' ) ) ;
|
70 |
+
$this->_respond();
|
71 |
+
}
|
72 |
+
|
73 |
if( $this->is_preview() ) {
|
74 |
|
75 |
$this->_form_cache = get_user_option( 'nf_form_preview_' . $this->_form_id );
|
includes/AJAX/REST/BatchProcess.php
CHANGED
@@ -22,27 +22,19 @@ class NF_AJAX_REST_BatchProcess extends NF_AJAX_REST_Controller
|
|
22 |
if ( ! isset( $request_data[ 'security' ] ) || ! wp_verify_nonce( $request_data[ 'security' ], 'ninja_forms_batch_nonce' ) ) {
|
23 |
// Kick the request out now.
|
24 |
$data[ 'error' ] = __( 'Request forbidden.', 'ninja-forms' );
|
|
|
25 |
}
|
|
|
26 |
// If we have a batch type...
|
27 |
if ( isset( $request_data[ 'batch_type' ]) ){
|
28 |
$batch_type = $request_data[ 'batch_type' ];
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
$batch = new NF_Admin_Processes_DataCleanup(
|
37 |
-
$request_data );
|
38 |
-
break;
|
39 |
-
case 'expired_submission_cleanup':
|
40 |
-
$batch = new NF_Admin_Processes_ExpiredSubmissionCleanup(
|
41 |
-
$request_data );
|
42 |
-
break;
|
43 |
-
default:
|
44 |
-
$data[ 'error' ] = __( 'Invalid request.', 'ninja-forms' );
|
45 |
-
break;
|
46 |
}
|
47 |
} // Otherwise... (We don't have a batch type.)
|
48 |
else {
|
22 |
if ( ! isset( $request_data[ 'security' ] ) || ! wp_verify_nonce( $request_data[ 'security' ], 'ninja_forms_batch_nonce' ) ) {
|
23 |
// Kick the request out now.
|
24 |
$data[ 'error' ] = __( 'Request forbidden.', 'ninja-forms' );
|
25 |
+
return $data;
|
26 |
}
|
27 |
+
|
28 |
// If we have a batch type...
|
29 |
if ( isset( $request_data[ 'batch_type' ]) ){
|
30 |
$batch_type = $request_data[ 'batch_type' ];
|
31 |
+
$batch_processes = Ninja_Forms()->config( 'BatchProcesses' );
|
32 |
+
|
33 |
+
if ( isset ( $batch_processes[ $batch_type ][ 'class_name' ] ) ) {
|
34 |
+
$batch_class = $batch_processes[ $batch_type ][ 'class_name' ];
|
35 |
+
$batch = new $batch_class( $request_data );
|
36 |
+
} else {
|
37 |
+
$data[ 'error' ] = __( 'Invalid request.', 'ninja-forms' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
}
|
39 |
} // Otherwise... (We don't have a batch type.)
|
40 |
else {
|
includes/AJAX/REST/NewFormTemplates.php
CHANGED
@@ -13,10 +13,10 @@ class NF_AJAX_REST_NewFormTemplates extends NF_AJAX_REST_Controller
|
|
13 |
$templates = Ninja_Forms()->config( 'NewFormTemplates' );
|
14 |
usort( $templates, array( $this, 'cmp' ) );
|
15 |
array_unshift( $templates, array(
|
16 |
-
'id'
|
17 |
-
'title'
|
18 |
'template-desc' => __( 'The blank form allows you to create any type of form using our drag & drop builder.', 'ninja-forms' ),
|
19 |
-
'type'
|
20 |
) );
|
21 |
return array_values( $templates ); // Remove keys so that the JSON is an array.
|
22 |
}
|
13 |
$templates = Ninja_Forms()->config( 'NewFormTemplates' );
|
14 |
usort( $templates, array( $this, 'cmp' ) );
|
15 |
array_unshift( $templates, array(
|
16 |
+
'id' => 'new',
|
17 |
+
'title' => __( 'Blank Form', 'ninja-forms' ),
|
18 |
'template-desc' => __( 'The blank form allows you to create any type of form using our drag & drop builder.', 'ninja-forms' ),
|
19 |
+
'type' => 'default'
|
20 |
) );
|
21 |
return array_values( $templates ); // Remove keys so that the JSON is an array.
|
22 |
}
|
includes/AJAX/REST/RequiredUpdate.php
ADDED
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
class NF_AJAX_REST_RequiredUpdate extends NF_AJAX_REST_Controller
|
4 |
+
{
|
5 |
+
private $updates = array();
|
6 |
+
private $running = array();
|
7 |
+
|
8 |
+
protected $action = 'nf_required_update';
|
9 |
+
public function __construct()
|
10 |
+
{
|
11 |
+
parent::__construct();
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* POST
|
16 |
+
* @param array $request_data [ int $clone_id ]
|
17 |
+
* @return array $data [ int $new_form_id ]
|
18 |
+
*/
|
19 |
+
public function post( $request_data )
|
20 |
+
{
|
21 |
+
$data = array();
|
22 |
+
|
23 |
+
// If we don't have a nonce...
|
24 |
+
// OR if the nonce is invalid...
|
25 |
+
if ( ! isset( $request_data[ 'security' ] ) || ! wp_verify_nonce( $request_data[ 'security' ], 'ninja_forms_required_update_nonce' ) ) {
|
26 |
+
// Kick the request out now.
|
27 |
+
$data[ 'error' ] = __( 'Request forbidden.', 'ninja-forms' );
|
28 |
+
return $data;
|
29 |
+
}
|
30 |
+
$doing_updates = get_option( 'ninja_forms_doing_required_updates' );
|
31 |
+
// If we're not already doing updates...
|
32 |
+
if ( ! $doing_updates ) {
|
33 |
+
// Get our list of already run updates.
|
34 |
+
$processed = get_option( 'ninja_forms_required_updates', array() );
|
35 |
+
// Get our list of updates to run.
|
36 |
+
$this->updates = Ninja_Forms()->config( 'RequiredUpdates' );
|
37 |
+
// Sort our updates.
|
38 |
+
$this->running = $this->sort_updates( $this->updates, $processed );
|
39 |
+
} // Otherwise... (We are already processing updates.)
|
40 |
+
else {
|
41 |
+
$this->running = $doing_updates;
|
42 |
+
}
|
43 |
+
// Call the class of our current update.
|
44 |
+
$class = $this->running[ 0 ][ 'class_name' ];
|
45 |
+
$update_class = new $class( $request_data, $this->running );
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* GET
|
50 |
+
* @param $request_data (Array)
|
51 |
+
* @return $data (Array)
|
52 |
+
*
|
53 |
+
* @since 3.4.0
|
54 |
+
*/
|
55 |
+
public function get( $request_data ) {
|
56 |
+
|
57 |
+
$data = array();
|
58 |
+
$data[ 'updates' ] = array();
|
59 |
+
|
60 |
+
// Get our list of already run updates.
|
61 |
+
$processed = get_option( 'ninja_forms_required_updates', array() );
|
62 |
+
// Get our list of updates yet to be run.
|
63 |
+
$this->updates = Ninja_Forms()->config( 'RequiredUpdates' );
|
64 |
+
// Sort our updates.
|
65 |
+
$sorted = $this->sort_updates( $this->updates, $processed );
|
66 |
+
$data[ 'updates' ] = $sorted;
|
67 |
+
return $data;
|
68 |
+
}
|
69 |
+
|
70 |
+
protected function get_request_data()
|
71 |
+
{
|
72 |
+
$request_data = array();
|
73 |
+
|
74 |
+
if( isset( $_REQUEST[ 'data' ] ) && $_REQUEST[ 'data' ] ){
|
75 |
+
$request_data[ 'data' ] = $_REQUEST[ 'data' ];
|
76 |
+
}
|
77 |
+
|
78 |
+
if( isset( $_REQUEST[ 'security' ] ) && $_REQUEST[ 'security' ] ){
|
79 |
+
$request_data[ 'security' ] = $_REQUEST[ 'security' ];
|
80 |
+
}
|
81 |
+
|
82 |
+
if( isset( $_REQUEST[ 'action' ] ) && $_REQUEST[ 'action' ] ){
|
83 |
+
$request_data[ 'action' ] = $_REQUEST[ 'action' ];
|
84 |
+
}
|
85 |
+
|
86 |
+
return $request_data;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Function to get the list of updates that need to run.
|
91 |
+
*
|
92 |
+
* @param $processed (Array) The list of updates that have already run on this install.
|
93 |
+
* @return Array
|
94 |
+
*/
|
95 |
+
private function get_current_updates( $processed ) {
|
96 |
+
$updates = array();
|
97 |
+
// For each update in the list...
|
98 |
+
foreach ( $this->updates as $slug => $update ) {
|
99 |
+
// If we've not already processed it...
|
100 |
+
if ( ! isset( $processed[ $slug ] ) ) {
|
101 |
+
// Add it to our list.
|
102 |
+
$updates[ $slug ] = $update;
|
103 |
+
}
|
104 |
+
}
|
105 |
+
return $updates;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Function to sort the updates to be run.
|
110 |
+
*
|
111 |
+
* @param $current (Array) The list of updates to be run.
|
112 |
+
* @param $previous (Array) The list of updates that have already been run.
|
113 |
+
* @return Array
|
114 |
+
*/
|
115 |
+
private function sort_updates( $current, $previous ) {
|
116 |
+
$sorted = array();
|
117 |
+
$queue = array();
|
118 |
+
// While we have not finished sorting updates...
|
119 |
+
while ( count( $sorted ) < count( $current ) ) {
|
120 |
+
// For each update we wish to run...
|
121 |
+
foreach ( $current as $slug => $update ) {
|
122 |
+
// Migrate the slug to a property.
|
123 |
+
$update[ 'slug' ] = $slug;
|
124 |
+
// If we've not already added this to the sorted list...
|
125 |
+
if ( ! in_array( $update, $sorted ) ) {
|
126 |
+
// If it has requirements...
|
127 |
+
if ( ! empty( $update[ 'requires' ] ) ) {
|
128 |
+
$enqueued = 0;
|
129 |
+
// For each requirement...
|
130 |
+
foreach ( $update[ 'requires' ] as $requirement ) {
|
131 |
+
// If the requirement doesn't exist...
|
132 |
+
if ( ! isset( $this->updates[ $requirement ] ) ) {
|
133 |
+
// unset the update b/c we are missing requirements
|
134 |
+
unset( $current[ $slug ] );
|
135 |
+
unset( $this->updates[ $slug ] );
|
136 |
+
}
|
137 |
+
// If the requirement has already been added to the stack...
|
138 |
+
if ( in_array( $requirement, $queue ) ) {
|
139 |
+
$enqueued++;
|
140 |
+
} // OR If the requirement has already been processed...
|
141 |
+
elseif ( isset( $previous[ $requirement ] ) ) {
|
142 |
+
$enqueued++;
|
143 |
+
}
|
144 |
+
}
|
145 |
+
// If all requirement are met...
|
146 |
+
if ( $enqueued == count( $update[ 'requires' ] ) ) {
|
147 |
+
// Add it to the list.
|
148 |
+
array_push( $sorted, $update );
|
149 |
+
// Record that we enqueued it.
|
150 |
+
array_push( $queue, $slug );
|
151 |
+
}
|
152 |
+
} // Otherwise... (It has no requirements.)
|
153 |
+
else {
|
154 |
+
// Add it to the list.
|
155 |
+
array_push( $sorted, $update );
|
156 |
+
// Record that we enqueued it.
|
157 |
+
array_push( $queue, $slug );
|
158 |
+
}
|
159 |
+
}
|
160 |
+
}
|
161 |
+
}
|
162 |
+
return $sorted;
|
163 |
+
}
|
164 |
+
|
165 |
+
}
|
includes/Abstracts/BatchProcess.php
CHANGED
@@ -5,6 +5,15 @@
|
|
5 |
*/
|
6 |
abstract class NF_Abstracts_BatchProcess
|
7 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
|
9 |
/**
|
10 |
* Constructor
|
@@ -14,11 +23,49 @@ abstract class NF_Abstracts_BatchProcess
|
|
14 |
//Bail if we aren't in the admin.
|
15 |
if ( ! is_admin() )
|
16 |
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
}
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
/**
|
21 |
* Function to loop over the batch.
|
|
|
|
|
|
|
22 |
*/
|
23 |
public function process()
|
24 |
{
|
@@ -27,9 +74,11 @@ abstract class NF_Abstracts_BatchProcess
|
|
27 |
*/
|
28 |
}
|
29 |
|
30 |
-
|
31 |
/**
|
32 |
* Function to run any setup steps necessary to begin processing.
|
|
|
|
|
|
|
33 |
*/
|
34 |
public function startup()
|
35 |
{
|
@@ -38,9 +87,37 @@ abstract class NF_Abstracts_BatchProcess
|
|
38 |
*/
|
39 |
}
|
40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
/**
|
43 |
* Function to cleanup any lingering temporary elements of a batch process after completion.
|
|
|
|
|
|
|
44 |
*/
|
45 |
public function cleanup()
|
46 |
{
|
@@ -49,4 +126,53 @@ abstract class NF_Abstracts_BatchProcess
|
|
49 |
*/
|
50 |
}
|
51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
}
|
5 |
*/
|
6 |
abstract class NF_Abstracts_BatchProcess
|
7 |
{
|
8 |
+
protected $_db;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Array that holds data we're sending back to the JS front-end.
|
12 |
+
* @var array
|
13 |
+
*/
|
14 |
+
protected $response = array(
|
15 |
+
'batch_complete' => false
|
16 |
+
);
|
17 |
|
18 |
/**
|
19 |
* Constructor
|
23 |
//Bail if we aren't in the admin.
|
24 |
if ( ! is_admin() )
|
25 |
return false;
|
26 |
+
|
27 |
+
global $wpdb;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Set $_db to $wpdb.
|
31 |
+
* This helps us by not requiring us to declare global $wpdb in every class method.
|
32 |
+
*/
|
33 |
+
$this->_db = $wpdb;
|
34 |
+
|
35 |
+
// Run init.
|
36 |
+
$this->init();
|
37 |
}
|
38 |
|
39 |
+
/**
|
40 |
+
* Decides whether we need to run startup or restart and then calls processing.
|
41 |
+
*
|
42 |
+
* @since 3.4.0
|
43 |
+
* @return void
|
44 |
+
*/
|
45 |
+
public function init()
|
46 |
+
{
|
47 |
+
if ( ! get_option( 'nf_doing_' . $this->_slug ) ) {
|
48 |
+
// Run the startup process.
|
49 |
+
$this->startup();
|
50 |
+
} else {
|
51 |
+
// Otherwise... (We've already run startup.)
|
52 |
+
$this->restart();
|
53 |
+
}
|
54 |
+
|
55 |
+
// Determine how many steps this will take.
|
56 |
+
$this->response[ 'step_total' ] = $this->get_steps();
|
57 |
+
|
58 |
+
add_option( 'nf_doing_' . $this->_slug, true );
|
59 |
+
|
60 |
+
// Run processing
|
61 |
+
$this->process();
|
62 |
+
}
|
63 |
|
64 |
/**
|
65 |
* Function to loop over the batch.
|
66 |
+
*
|
67 |
+
* @since 3.4.0
|
68 |
+
* @return void
|
69 |
*/
|
70 |
public function process()
|
71 |
{
|
74 |
*/
|
75 |
}
|
76 |
|
|
|
77 |
/**
|
78 |
* Function to run any setup steps necessary to begin processing.
|
79 |
+
*
|
80 |
+
* @since 3.4.0
|
81 |
+
* @return void
|
82 |
*/
|
83 |
public function startup()
|
84 |
{
|
87 |
*/
|
88 |
}
|
89 |
|
90 |
+
/**
|
91 |
+
* Function to run any setup steps necessary to begin processing for steps after the first.
|
92 |
+
*
|
93 |
+
* @since 3.4.0
|
94 |
+
* @return void
|
95 |
+
*/
|
96 |
+
public function restart()
|
97 |
+
{
|
98 |
+
/**
|
99 |
+
* This function intentionally left empty.
|
100 |
+
*/
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Returns how many steps we have in this process.
|
105 |
+
*
|
106 |
+
* If this method isn't overwritten by a child, it defaults to 1.
|
107 |
+
*
|
108 |
+
* @since 3.4.0
|
109 |
+
* @return int
|
110 |
+
*/
|
111 |
+
public function get_steps()
|
112 |
+
{
|
113 |
+
return 1;
|
114 |
+
}
|
115 |
|
116 |
/**
|
117 |
* Function to cleanup any lingering temporary elements of a batch process after completion.
|
118 |
+
*
|
119 |
+
* @since 3.4.0
|
120 |
+
* @return void
|
121 |
*/
|
122 |
public function cleanup()
|
123 |
{
|
126 |
*/
|
127 |
}
|
128 |
|
129 |
+
/**
|
130 |
+
* Method called when we are finished with this process.
|
131 |
+
*
|
132 |
+
* Deletes our "doing" option.
|
133 |
+
* Set's our response 'batch_complete' to true.
|
134 |
+
* Runs cleanup().
|
135 |
+
* Responds to the JS front-end.
|
136 |
+
*
|
137 |
+
* @since 3.4.0
|
138 |
+
* @return void
|
139 |
+
*/
|
140 |
+
public function batch_complete()
|
141 |
+
{
|
142 |
+
// Delete our options.
|
143 |
+
delete_option( 'nf_doing_' . $this->_slug );
|
144 |
+
// Tell our JS that we're done.
|
145 |
+
$this->response[ 'batch_complete' ] = true;
|
146 |
+
|
147 |
+
$this->cleanup();
|
148 |
+
$this->respond();
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Method that immediately moves on to the next step.
|
153 |
+
*
|
154 |
+
* Used in child methods to stop processing the current step an dmove to the next.
|
155 |
+
*
|
156 |
+
* @since 3.4.0
|
157 |
+
* @return void
|
158 |
+
*/
|
159 |
+
public function next_step()
|
160 |
+
{
|
161 |
+
// ..see how many steps we have left, update our option, and send the remaining step to the JS.
|
162 |
+
$this->response[ 'step_remaining' ] = $this->get_steps();
|
163 |
+
$this->respond();
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Method that encodes $this->response and sends the data to the front-end.
|
168 |
+
*
|
169 |
+
* @since 3.4.0
|
170 |
+
* @return void
|
171 |
+
*/
|
172 |
+
public function respond()
|
173 |
+
{
|
174 |
+
echo wp_json_encode( $this->response );
|
175 |
+
wp_die();
|
176 |
+
}
|
177 |
+
|
178 |
}
|
includes/Abstracts/Migration.php
CHANGED
@@ -10,63 +10,121 @@ abstract class NF_Abstracts_Migration
|
|
10 |
|
11 |
public $flag = '';
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function __construct( $table_name, $flag )
|
14 |
{
|
15 |
$this->table_name = $table_name;
|
16 |
}
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
public function table_name()
|
19 |
{
|
20 |
global $wpdb;
|
21 |
return $wpdb->prefix . $this->table_name;
|
22 |
}
|
23 |
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
{
|
26 |
global $wpdb;
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
return 'DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci';
|
35 |
-
}
|
36 |
}
|
37 |
|
|
|
38 |
/**
|
39 |
-
*
|
40 |
*
|
41 |
-
* @
|
42 |
*
|
43 |
-
* @return
|
|
|
|
|
|
|
44 |
*/
|
45 |
-
public function
|
46 |
{
|
|
|
47 |
global $wpdb;
|
48 |
// If our mysql version is 5.5.3 or higher...
|
49 |
if ( version_compare( $wpdb->db_version(), '5.5.3', '>=' ) ) {
|
50 |
// We can use mb4.
|
51 |
-
|
52 |
} // Otherwise...
|
53 |
else {
|
54 |
// We use standard utf8.
|
55 |
-
|
56 |
-
}
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
58 |
}
|
59 |
-
|
60 |
/**
|
61 |
-
* Function to run our
|
|
|
|
|
|
|
|
|
62 |
*/
|
63 |
-
public function
|
64 |
{
|
65 |
-
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
}
|
68 |
}
|
69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
public function _run()
|
71 |
{
|
72 |
// Check the flag
|
@@ -79,17 +137,38 @@ abstract class NF_Abstracts_Migration
|
|
79 |
update_option( $this->flag, TRUE );
|
80 |
}
|
81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
protected abstract function run();
|
83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
public function _drop()
|
85 |
{
|
86 |
global $wpdb;
|
|
|
87 |
if( ! $this->table_name ) return;
|
|
|
88 |
if( 0 == $wpdb->query( $wpdb->prepare( "SHOW TABLES LIKE '%s'", $this->table_name() ) ) ) return;
|
|
|
89 |
$wpdb->query( "DROP TABLE " . $this->table_name() );
|
90 |
return $this->drop();
|
91 |
}
|
92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
protected function drop()
|
94 |
{
|
95 |
// This section intentionally left blank.
|
10 |
|
11 |
public $flag = '';
|
12 |
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Constructor method for the NF_Abstracts_Migration class.
|
16 |
+
*
|
17 |
+
* @param $table_name (String) The database table name managed by the extension.
|
18 |
+
* @param $flag (String) The wp option set to determine if this migration has already been run.
|
19 |
+
*
|
20 |
+
* @since 3.0.0
|
21 |
+
*/
|
22 |
public function __construct( $table_name, $flag )
|
23 |
{
|
24 |
$this->table_name = $table_name;
|
25 |
}
|
26 |
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Function to retrieve the full table name of the extension.
|
30 |
+
*
|
31 |
+
* @return (String) The full table name, including database prefix.
|
32 |
+
*
|
33 |
+
* @since 3.0.28
|
34 |
+
*/
|
35 |
public function table_name()
|
36 |
{
|
37 |
global $wpdb;
|
38 |
return $wpdb->prefix . $this->table_name;
|
39 |
}
|
40 |
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Function to check for the existence of a column in the extension's table.
|
44 |
+
*
|
45 |
+
* @param $column (String) The name of the column to search for.
|
46 |
+
*
|
47 |
+
* @return (Boolean) Whether or not the column exists.
|
48 |
+
*
|
49 |
+
* @since 3.4.0
|
50 |
+
*/
|
51 |
+
public function column_exists( $column )
|
52 |
{
|
53 |
global $wpdb;
|
54 |
+
$response = false;
|
55 |
+
// Fetch any records of the target column.
|
56 |
+
$sql = $wpdb->prepare( "SHOW COLUMNS FROM `{$this->table_name()}` WHERE `Field` = '%s';", $column );
|
57 |
+
$result = $wpdb->query( $sql );
|
58 |
+
// If we got anything back, say so.
|
59 |
+
if ( ! empty( $result ) ) $response = true;
|
60 |
+
return $result;
|
|
|
|
|
61 |
}
|
62 |
|
63 |
+
|
64 |
/**
|
65 |
+
* Funciton to get the charset and collate for migrations.
|
66 |
*
|
67 |
+
* @param $use_default (Boolean) Whether or not to include the DEFAULT keyword in the return pattern.
|
68 |
*
|
69 |
+
* @return (String) A SQL formatted charset and collate for use by table definition.
|
70 |
+
*
|
71 |
+
* @since 3.0.28
|
72 |
+
* @updated 3.1.14
|
73 |
*/
|
74 |
+
public function charset_collate( $use_default = false )
|
75 |
{
|
76 |
+
$response = '';
|
77 |
global $wpdb;
|
78 |
// If our mysql version is 5.5.3 or higher...
|
79 |
if ( version_compare( $wpdb->db_version(), '5.5.3', '>=' ) ) {
|
80 |
// We can use mb4.
|
81 |
+
$response = 'CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci';
|
82 |
} // Otherwise...
|
83 |
else {
|
84 |
// We use standard utf8.
|
85 |
+
$response = 'CHARACTER SET utf8 COLLATE utf8_general_ci';
|
86 |
+
}
|
87 |
+
// If we need to use default...
|
88 |
+
if ( $use_default ) {
|
89 |
+
// Append that to the response.
|
90 |
+
$response = 'DEFAULT ' . $response;
|
91 |
+
}
|
92 |
+
return $response;
|
93 |
}
|
94 |
+
|
95 |
/**
|
96 |
+
* Function to run our required update functions.
|
97 |
+
*
|
98 |
+
* @param $callback (String) The function to be run by this call.
|
99 |
+
*
|
100 |
+
* @since 3.4.0
|
101 |
*/
|
102 |
+
public function _do_upgrade( $callback )
|
103 |
{
|
104 |
+
// If the method exists...
|
105 |
+
if ( method_exists( $this, $callback ) ) {
|
106 |
+
$blacklist = array(
|
107 |
+
'__construct',
|
108 |
+
'_do_upgrade',
|
109 |
+
'_run',
|
110 |
+
'run',
|
111 |
+
'_drop',
|
112 |
+
'drop'
|
113 |
+
);
|
114 |
+
// If this callback method isn't blacklisted...
|
115 |
+
if ( ! in_array( $callback, $blacklist ) ) {
|
116 |
+
// Run it.
|
117 |
+
$this->{$callback}();
|
118 |
+
}
|
119 |
}
|
120 |
}
|
121 |
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Function to run our initial migration.
|
125 |
+
*
|
126 |
+
* @since 3.0.0
|
127 |
+
*/
|
128 |
public function _run()
|
129 |
{
|
130 |
// Check the flag
|
137 |
update_option( $this->flag, TRUE );
|
138 |
}
|
139 |
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Abstract protection of inherited funciton run.
|
143 |
+
*
|
144 |
+
* @since 3.0.0
|
145 |
+
*/
|
146 |
protected abstract function run();
|
147 |
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Function to drop the table managed by this migration.
|
151 |
+
*
|
152 |
+
* @since 3.0.28
|
153 |
+
*/
|
154 |
public function _drop()
|
155 |
{
|
156 |
global $wpdb;
|
157 |
+
// If we don't have a table name, exit early.
|
158 |
if( ! $this->table_name ) return;
|
159 |
+
// If the table doesn't exist, exit early.
|
160 |
if( 0 == $wpdb->query( $wpdb->prepare( "SHOW TABLES LIKE '%s'", $this->table_name() ) ) ) return;
|
161 |
+
// Drop the table.
|
162 |
$wpdb->query( "DROP TABLE " . $this->table_name() );
|
163 |
return $this->drop();
|
164 |
}
|
165 |
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Protection of inherited function drop.
|
169 |
+
*
|
170 |
+
* @since 3.0.28
|
171 |
+
*/
|
172 |
protected function drop()
|
173 |
{
|
174 |
// This section intentionally left blank.
|
includes/Abstracts/Model.php
CHANGED
@@ -120,6 +120,13 @@ class NF_Abstracts_Model
|
|
120 |
*/
|
121 |
protected $_cache = TRUE;
|
122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
//-----------------------------------------------------
|
124 |
// Public Methods
|
125 |
//-----------------------------------------------------
|
@@ -251,6 +258,8 @@ class NF_Abstracts_Model
|
|
251 |
$this->_settings[ 'label' ] = $field[ 'label' ];
|
252 |
$this->_settings[ 'key' ] = $field[ 'key' ];
|
253 |
$this->_settings[ 'type' ] = $field[ 'type' ];
|
|
|
|
|
254 |
}
|
255 |
}
|
256 |
|
@@ -482,6 +491,22 @@ class NF_Abstracts_Model
|
|
482 |
*/
|
483 |
public function save()
|
484 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
485 |
$data = array ( 'updated_at' => current_time( 'mysql' ));
|
486 |
|
487 |
// If the ID is not set, assign an ID
|
@@ -644,11 +669,11 @@ class NF_Abstracts_Model
|
|
644 |
if( $meta_row ){
|
645 |
|
646 |
$update_values = array(
|
647 |
-
|
648 |
);
|
649 |
|
650 |
// for forms we need to update the meta_key and meta_value columns
|
651 |
-
if( 'form' == $this->_type ) {
|
652 |
$update_values[ 'meta_key' ] = $key;
|
653 |
$update_values[ 'meta_value' ] = $value;
|
654 |
}
|
@@ -671,7 +696,7 @@ class NF_Abstracts_Model
|
|
671 |
);
|
672 |
|
673 |
// for forms we need to update the meta_key and meta_value columns
|
674 |
-
if( 'form' == $this->_type ) {
|
675 |
$insert_values[ 'meta_key' ] = $key;
|
676 |
$insert_values[ 'meta_value' ] = $value;
|
677 |
}
|
120 |
*/
|
121 |
protected $_cache = TRUE;
|
122 |
|
123 |
+
/**
|
124 |
+
* A Flag for testing whether or not we've completed stage 1 of our db.
|
125 |
+
*
|
126 |
+
* @var boolean
|
127 |
+
*/
|
128 |
+
private $db_stage_1_complete = TRUE;
|
129 |
+
|
130 |
//-----------------------------------------------------
|
131 |
// Public Methods
|
132 |
//-----------------------------------------------------
|
258 |
$this->_settings[ 'label' ] = $field[ 'label' ];
|
259 |
$this->_settings[ 'key' ] = $field[ 'key' ];
|
260 |
$this->_settings[ 'type' ] = $field[ 'type' ];
|
261 |
+
$this->_settings[ 'field_label' ] = $field[ 'label' ];
|
262 |
+
$this->_settings[ 'field_key' ] = $field[ 'key' ];
|
263 |
}
|
264 |
}
|
265 |
|
491 |
*/
|
492 |
public function save()
|
493 |
{
|
494 |
+
|
495 |
+
/**
|
496 |
+
* Check to see if we've completed stage 1 of our db update.
|
497 |
+
*/
|
498 |
+
|
499 |
+
$sql = "SHOW COLUMNS FROM {$this->_db->prefix}nf3_fields LIKE 'field_key'";
|
500 |
+
$results = $this->_db->get_results( $sql );
|
501 |
+
/**
|
502 |
+
* If we don't have the field_key column, we need to remove our new columns.
|
503 |
+
*
|
504 |
+
* Also, set our db stage 1 tracker to false.
|
505 |
+
*/
|
506 |
+
if ( empty ( $results ) ) {
|
507 |
+
$this->db_stage_1_complete = false;
|
508 |
+
}
|
509 |
+
|
510 |
$data = array ( 'updated_at' => current_time( 'mysql' ));
|
511 |
|
512 |
// If the ID is not set, assign an ID
|
669 |
if( $meta_row ){
|
670 |
|
671 |
$update_values = array(
|
672 |
+
'value' => $value,
|
673 |
);
|
674 |
|
675 |
// for forms we need to update the meta_key and meta_value columns
|
676 |
+
if( 'form' == $this->_type || $this->db_stage_1_complete ) {
|
677 |
$update_values[ 'meta_key' ] = $key;
|
678 |
$update_values[ 'meta_value' ] = $value;
|
679 |
}
|
696 |
);
|
697 |
|
698 |
// for forms we need to update the meta_key and meta_value columns
|
699 |
+
if( 'form' == $this->_type || $this->db_stage_1_complete ) {
|
700 |
$insert_values[ 'meta_key' ] = $key;
|
701 |
$insert_values[ 'meta_value' ] = $value;
|
702 |
}
|
includes/Abstracts/RequiredUpdate.php
ADDED
@@ -0,0 +1,224 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class NF_Abstracts_RequiredUpdate
|
5 |
+
*/
|
6 |
+
abstract class NF_Abstracts_RequiredUpdate
|
7 |
+
{
|
8 |
+
|
9 |
+
protected $_slug = '';
|
10 |
+
|
11 |
+
protected $_requires = array();
|
12 |
+
|
13 |
+
protected $_class_name = '';
|
14 |
+
|
15 |
+
protected $db;
|
16 |
+
|
17 |
+
public $response = array();
|
18 |
+
|
19 |
+
public $debug = false;
|
20 |
+
|
21 |
+
public $lock_process = false;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Constructor
|
25 |
+
*
|
26 |
+
* @since 3.4.0
|
27 |
+
*/
|
28 |
+
public function __construct( $data = array() )
|
29 |
+
{
|
30 |
+
// Save a reference to wpdb.
|
31 |
+
global $wpdb;
|
32 |
+
$this->db = $wpdb;
|
33 |
+
//Bail if we aren't in the admin.
|
34 |
+
if ( ! is_admin() ) return false;
|
35 |
+
// If we weren't provided with a slug or a class name...
|
36 |
+
if ( ! isset( $data[ 'slug' ] ) || ! isset( $data[ 'class_name' ] ) ) {
|
37 |
+
// Bail.
|
38 |
+
return false;
|
39 |
+
}
|
40 |
+
$this->_slug = $data[ 'slug' ];
|
41 |
+
$this->_class_name = $data[ 'class_name' ];
|
42 |
+
// Record debug settings if provided.
|
43 |
+
if ( isset( $data[ 'debug' ] ) ) $this->debug = $data[ 'debug' ];
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Function to loop over the batch.
|
49 |
+
*
|
50 |
+
* @since 3.4.0
|
51 |
+
*/
|
52 |
+
public function process()
|
53 |
+
{
|
54 |
+
/**
|
55 |
+
* This function intentionlly left empty.
|
56 |
+
*/
|
57 |
+
}
|
58 |
+
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Function to run any setup steps necessary to begin processing.
|
62 |
+
*
|
63 |
+
* @since 3.4.0
|
64 |
+
*/
|
65 |
+
public function startup()
|
66 |
+
{
|
67 |
+
/**
|
68 |
+
* This function intentionally left empty.
|
69 |
+
*/
|
70 |
+
}
|
71 |
+
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Function to cleanup any lingering temporary elements of required updates after completion.
|
75 |
+
*
|
76 |
+
* @since 3.4.0
|
77 |
+
*/
|
78 |
+
public function cleanup()
|
79 |
+
{
|
80 |
+
// Delete our required updates data.
|
81 |
+
delete_option( 'ninja_forms_doing_required_updates' );
|
82 |
+
// Flag that updates are done.
|
83 |
+
update_option( 'ninja_forms_needs_updates', 0 );
|
84 |
+
// Set our new db version.
|
85 |
+
update_option( 'ninja_forms_db_version', Ninja_Forms::DB_VERSION );
|
86 |
+
// Fetch our list of completed updates.
|
87 |
+
$updates = get_option( 'ninja_forms_required_updates', array() );
|
88 |
+
// If we got something back...
|
89 |
+
if ( ! empty( $updates ) ) {
|
90 |
+
// Send out a call to telemetry.
|
91 |
+
Ninja_Forms()->dispatcher()->send( 'required_updates_complete', $updates );
|
92 |
+
}
|
93 |
+
// Output that we're done.
|
94 |
+
$this->response[ 'updatesRemaining' ] = 0;
|
95 |
+
$this->respond();
|
96 |
+
}
|
97 |
+
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Function to dump our JSON response and kill processing.
|
101 |
+
*
|
102 |
+
* @since 3.4.0
|
103 |
+
*/
|
104 |
+
public function respond()
|
105 |
+
{
|
106 |
+
// Dump the response.
|
107 |
+
echo( json_encode( $this->response ) );
|
108 |
+
// Terminate processing.
|
109 |
+
die();
|
110 |
+
}
|
111 |
+
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Function to run our table migrations.
|
115 |
+
*
|
116 |
+
* @param $callback (String) The callback function in the migration file.
|
117 |
+
*
|
118 |
+
* @since 3.4.0
|
119 |
+
*/
|
120 |
+
protected function migrate( $callback )
|
121 |
+
{
|
122 |
+
$migrations = new NF_Database_Migrations();
|
123 |
+
$migrations->do_upgrade( $callback );
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Function to prepare our query values for insert.
|
128 |
+
*
|
129 |
+
* @param $value (Mixed) The value to be escaped for SQL.
|
130 |
+
* @return (String) The escaped (and possibly serialized) value of the string.
|
131 |
+
*
|
132 |
+
* @since 3.4.0
|
133 |
+
*/
|
134 |
+
public function prepare( $value )
|
135 |
+
{
|
136 |
+
// If our value is a number...
|
137 |
+
if ( is_float( $value ) ) {
|
138 |
+
// Exit early and return the value.
|
139 |
+
return $value;
|
140 |
+
}
|
141 |
+
// Serialize the value if necessary.
|
142 |
+
$escaped = maybe_serialize( $value );
|
143 |
+
// Escape it.
|
144 |
+
$escaped = $this->db->_real_escape( $escaped );
|
145 |
+
|
146 |
+
return $escaped;
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Function used to call queries that are gated by debug.
|
151 |
+
*
|
152 |
+
* @param $sql (String) The query to be run.
|
153 |
+
* @return (Object) The response to the wpdb query call.
|
154 |
+
*
|
155 |
+
* @since 3.4.0
|
156 |
+
*/
|
157 |
+
protected function query( $sql )
|
158 |
+
{
|
159 |
+
// If we're not debugging...
|
160 |
+
if ( ! $this->debug ) {
|
161 |
+
// Run the query.
|
162 |
+
return $this->db->query( $sql );
|
163 |
+
} // Otherwise...
|
164 |
+
// Append the query to the response object.
|
165 |
+
$this->response[ 'queries' ][] = $sql;
|
166 |
+
// Return false.
|
167 |
+
return false;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Function to record the completion of our update in the DB.
|
172 |
+
*
|
173 |
+
* @since 3.4.0
|
174 |
+
*/
|
175 |
+
protected function confirm_complete()
|
176 |
+
{
|
177 |
+
// If we're not debugging...
|
178 |
+
if ( ! $this->debug ) {
|
179 |
+
// Fetch our required updates array.
|
180 |
+
$updates = get_option( 'ninja_forms_required_updates', array() );
|
181 |
+
// Get a timestamp.
|
182 |
+
date_default_timezone_set( 'UTC' );
|
183 |
+
$now = date( "Y-m-d H:i:s" );
|
184 |
+
// Append the current update to the array.
|
185 |
+
$updates[ $this->_slug ] = $now;
|
186 |
+
// Save it.
|
187 |
+
update_option( 'ninja_forms_required_updates', $updates );
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Enable Maintenance mode
|
193 |
+
* Enables maintenance mode so the form will not render on the front end while updates are running.
|
194 |
+
*
|
195 |
+
* @since 3.4.0
|
196 |
+
*
|
197 |
+
* @param $prefix - the db prefix.
|
198 |
+
* @param $form_id - The id of the form.
|
199 |
+
*/
|
200 |
+
public function enable_maintenance_mode( $prefix, $form_id )
|
201 |
+
{
|
202 |
+
// Change maintenance column value to 1, run the query and then return.
|
203 |
+
$sql = $this->db->prepare( 'UPDATE `' . $prefix . 'nf3_upgrades` SET `maintenance` = 1 WHERE `id` = %d', $form_id );
|
204 |
+
$this->db->query( $sql );
|
205 |
+
return;
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Disable Maintenance Mode
|
210 |
+
* Disables maintenance mode, so the form will be displayed on the front end..
|
211 |
+
*
|
212 |
+
* @since 3.4.0
|
213 |
+
*
|
214 |
+
* @param $prefix - the db prefix.
|
215 |
+
* @param $form_id - The id of the form.
|
216 |
+
*/
|
217 |
+
public function disable_maintenance_mode( $prefix, $form_id )
|
218 |
+
{
|
219 |
+
// Change maintenance column value to 0, run the query and then return.
|
220 |
+
$sql = $this->db->prepare( 'UPDATE `' . $prefix . 'nf3_upgrades` SET `maintenance` = 0 WHERE `id` = %d', $form_id );
|
221 |
+
$this->db->query( $sql );
|
222 |
+
return;
|
223 |
+
}
|
224 |
+
}
|
includes/Admin/Menus/AddNew.php
CHANGED
@@ -13,6 +13,19 @@ final class NF_Admin_Menus_AddNew extends NF_Abstracts_Submenu
|
|
13 |
public function __construct()
|
14 |
{
|
15 |
parent::__construct();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
}
|
17 |
|
18 |
public function get_page_title()
|
13 |
public function __construct()
|
14 |
{
|
15 |
parent::__construct();
|
16 |
+
|
17 |
+
add_action( 'admin_init', array( $this, 'nf_upgrade_redirect' ) );
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* If we have required updates, unregister the menu item
|
22 |
+
*/
|
23 |
+
public function nf_upgrade_redirect() {
|
24 |
+
global $pagenow;
|
25 |
+
|
26 |
+
if( "1" == get_option( 'ninja_forms_needs_updates' ) ) {
|
27 |
+
remove_submenu_page( $this->parent_slug, $this->menu_slug );
|
28 |
+
}
|
29 |
}
|
30 |
|
31 |
public function get_page_title()
|
includes/Admin/Menus/Addons.php
CHANGED
@@ -14,6 +14,19 @@ final class NF_Admin_Menus_Addons extends NF_Abstracts_Submenu
|
|
14 |
if ( ! apply_filters( 'ninja_forms_disable_marketing', $disable_marketing ) ) {
|
15 |
parent::__construct();
|
16 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
}
|
18 |
|
19 |
public function get_page_title()
|
14 |
if ( ! apply_filters( 'ninja_forms_disable_marketing', $disable_marketing ) ) {
|
15 |
parent::__construct();
|
16 |
}
|
17 |
+
|
18 |
+
add_action( 'admin_init', array( $this, 'nf_upgrade_redirect' ) );
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* If we have required updates, unregister the menu item
|
23 |
+
*/
|
24 |
+
public function nf_upgrade_redirect() {
|
25 |
+
global $pagenow;
|
26 |
+
|
27 |
+
if( "1" == get_option( 'ninja_forms_needs_updates' ) ) {
|
28 |
+
remove_submenu_page( $this->parent_slug, $this->menu_slug );
|
29 |
+
}
|
30 |
}
|
31 |
|
32 |
public function get_page_title()
|
includes/Admin/Menus/Forms.php
CHANGED
@@ -25,6 +25,23 @@ final class NF_Admin_Menus_Forms extends NF_Abstracts_Menu
|
|
25 |
}
|
26 |
|
27 |
add_action( 'admin_body_class', array( $this, 'body_class' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
}
|
29 |
|
30 |
public function body_class( $classes )
|
@@ -134,10 +151,13 @@ final class NF_Admin_Menus_Forms extends NF_Abstracts_Menu
|
|
134 |
</script>
|
135 |
<?php
|
136 |
|
|
|
|
|
137 |
wp_enqueue_script( 'backbone-radio', Ninja_Forms::$url . 'assets/js/lib/backbone.radio.min.js', array( 'jquery', 'backbone' ) );
|
138 |
wp_enqueue_script( 'backbone-marionette-3', Ninja_Forms::$url . 'assets/js/lib/backbone.marionette3.min.js', array( 'jquery', 'backbone' ) );
|
139 |
wp_enqueue_script( 'nf-jbox', Ninja_Forms::$url . 'assets/js/lib/jBox.min.js', array( 'jquery' ) );
|
140 |
wp_enqueue_script( 'nf-ninjamodal', Ninja_Forms::$url . 'assets/js/lib/ninjaModal.js', array( 'jquery' ), $this->ver );
|
|
|
141 |
wp_enqueue_script( 'nf-moment', Ninja_Forms::$url . 'assets/js/lib/moment-with-locales.min.js', array( 'jquery', 'nf-dashboard' ) );
|
142 |
wp_enqueue_script( 'nf-dashboard', Ninja_Forms::$url . 'assets/js/min/dashboard.min.js', array( 'backbone-radio', 'backbone-marionette-3' ), $this->ver );
|
143 |
|
@@ -147,13 +167,13 @@ final class NF_Admin_Menus_Forms extends NF_Abstracts_Menu
|
|
147 |
wp_localize_script( 'nf-dashboard', 'nfAdmin', array(
|
148 |
'ajaxNonce' => wp_create_nonce( 'ninja_forms_dashboard_nonce' ),
|
149 |
'batchNonce' => wp_create_nonce( 'ninja_forms_batch_nonce' ),
|
|
|
150 |
'formTelemetry' => ( get_option( 'nf_form_tel_sent' ) ) ? 0 : 1,
|
151 |
'showOptin' => ( get_option( 'ninja_forms_do_not_allow_tracking' ) ||
|
152 |
get_option( 'ninja_forms_allow_tracking' ) ) ? 0 : 1,
|
|
|
153 |
'currentUserEmail' => $current_user->user_email,
|
154 |
-
'
|
155 |
-
isset( $_REQUEST[ 'action' ] ) &&
|
156 |
-
'cleanup' == $_REQUEST[ 'action' ] ) ? 1 : 0,
|
157 |
) );
|
158 |
|
159 |
wp_enqueue_style( 'nf-builder', Ninja_Forms::$url . 'assets/css/builder.css', array(), $this->ver );
|
@@ -161,6 +181,10 @@ final class NF_Admin_Menus_Forms extends NF_Abstracts_Menu
|
|
161 |
wp_enqueue_style( 'nf-jbox', Ninja_Forms::$url . 'assets/css/jBox.css' );
|
162 |
wp_enqueue_style( 'nf-font-awesome', Ninja_Forms::$url . 'assets/css/font-awesome.min.css' );
|
163 |
|
|
|
|
|
|
|
|
|
164 |
Ninja_Forms::template( 'admin-menu-dashboard.html.php' );
|
165 |
}
|
166 |
}
|
@@ -170,6 +194,11 @@ final class NF_Admin_Menus_Forms extends NF_Abstracts_Menu
|
|
170 |
add_submenu_page( 'ninja-forms', '', '', 'read', '', '' );
|
171 |
}
|
172 |
|
|
|
|
|
|
|
|
|
|
|
173 |
private function import_from_template()
|
174 |
{
|
175 |
$template = sanitize_title( $_GET['form_id'] );
|
25 |
}
|
26 |
|
27 |
add_action( 'admin_body_class', array( $this, 'body_class' ) );
|
28 |
+
add_action( 'admin_init', array( $this, 'nf_upgrade_redirect' ) );
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* If we have required updates, redirect to the main Ninja Forms page
|
33 |
+
*/
|
34 |
+
public function nf_upgrade_redirect() {
|
35 |
+
global $pagenow;
|
36 |
+
|
37 |
+
if( "1" == get_option( 'ninja_forms_needs_updates' ) &&
|
38 |
+
'admin.php' == $pagenow &&
|
39 |
+
'ninja-forms' == $_GET[ 'page' ] &&
|
40 |
+
isset( $_GET[ 'form_id' ] ) ) {
|
41 |
+
wp_safe_redirect( admin_url( 'admin.php?page=ninja-forms' ), 301 );
|
42 |
+
exit;
|
43 |
+
|
44 |
+
}
|
45 |
}
|
46 |
|
47 |
public function body_class( $classes )
|
151 |
</script>
|
152 |
<?php
|
153 |
|
154 |
+
$required_updates = get_option( 'ninja_forms_needs_updates', 0 );
|
155 |
+
|
156 |
wp_enqueue_script( 'backbone-radio', Ninja_Forms::$url . 'assets/js/lib/backbone.radio.min.js', array( 'jquery', 'backbone' ) );
|
157 |
wp_enqueue_script( 'backbone-marionette-3', Ninja_Forms::$url . 'assets/js/lib/backbone.marionette3.min.js', array( 'jquery', 'backbone' ) );
|
158 |
wp_enqueue_script( 'nf-jbox', Ninja_Forms::$url . 'assets/js/lib/jBox.min.js', array( 'jquery' ) );
|
159 |
wp_enqueue_script( 'nf-ninjamodal', Ninja_Forms::$url . 'assets/js/lib/ninjaModal.js', array( 'jquery' ), $this->ver );
|
160 |
+
wp_enqueue_script( 'nf-batch-processor', Ninja_Forms::$url . 'assets/js/lib/batch-processor.js', array( 'nf-ninjamodal' ), $this->ver );
|
161 |
wp_enqueue_script( 'nf-moment', Ninja_Forms::$url . 'assets/js/lib/moment-with-locales.min.js', array( 'jquery', 'nf-dashboard' ) );
|
162 |
wp_enqueue_script( 'nf-dashboard', Ninja_Forms::$url . 'assets/js/min/dashboard.min.js', array( 'backbone-radio', 'backbone-marionette-3' ), $this->ver );
|
163 |
|
167 |
wp_localize_script( 'nf-dashboard', 'nfAdmin', array(
|
168 |
'ajaxNonce' => wp_create_nonce( 'ninja_forms_dashboard_nonce' ),
|
169 |
'batchNonce' => wp_create_nonce( 'ninja_forms_batch_nonce' ),
|
170 |
+
'updateNonce' => wp_create_nonce( 'ninja_forms_required_update_nonce' ),
|
171 |
'formTelemetry' => ( get_option( 'nf_form_tel_sent' ) ) ? 0 : 1,
|
172 |
'showOptin' => ( get_option( 'ninja_forms_do_not_allow_tracking' ) ||
|
173 |
get_option( 'ninja_forms_allow_tracking' ) ) ? 0 : 1,
|
174 |
+
'requiredUpdates' => $required_updates,
|
175 |
'currentUserEmail' => $current_user->user_email,
|
176 |
+
'builderURL' => admin_url( 'admin.php?page=ninja-forms&form_id=' ),
|
|
|
|
|
177 |
) );
|
178 |
|
179 |
wp_enqueue_style( 'nf-builder', Ninja_Forms::$url . 'assets/css/builder.css', array(), $this->ver );
|
181 |
wp_enqueue_style( 'nf-jbox', Ninja_Forms::$url . 'assets/css/jBox.css' );
|
182 |
wp_enqueue_style( 'nf-font-awesome', Ninja_Forms::$url . 'assets/css/font-awesome.min.css' );
|
183 |
|
184 |
+
if( $required_updates ) {
|
185 |
+
wp_enqueue_style( 'nf-updates-styles', Ninja_Forms::$url . '/assets/css/required-updates.css' );
|
186 |
+
}
|
187 |
+
|
188 |
Ninja_Forms::template( 'admin-menu-dashboard.html.php' );
|
189 |
}
|
190 |
}
|
194 |
add_submenu_page( 'ninja-forms', '', '', 'read', '', '' );
|
195 |
}
|
196 |
|
197 |
+
/**
|
198 |
+
* TODO: Remove this function and its hook because we are handling template imports via the batch processor.
|
199 |
+
* @since 3.0
|
200 |
+
* @return void
|
201 |
+
*/
|
202 |
private function import_from_template()
|
203 |
{
|
204 |
$template = sanitize_title( $_GET['form_id'] );
|
includes/Admin/Menus/ImportExport.php
CHANGED
@@ -7,7 +7,7 @@ final class NF_Admin_Menus_ImportExport extends NF_Abstracts_Submenu
|
|
7 |
public $menu_slug = 'nf-import-export';
|
8 |
|
9 |
public function __construct()
|
10 |
-
{
|
11 |
add_action( 'init', array( $this, 'import_form_listener' ), 0 );
|
12 |
add_action( 'init', array( $this, 'export_form_listener' ), 0 );
|
13 |
|
@@ -17,6 +17,24 @@ final class NF_Admin_Menus_ImportExport extends NF_Abstracts_Submenu
|
|
17 |
add_filter( 'ninja_forms_before_import_fields', array( $this, 'import_fields_backwards_compatibility' ) );
|
18 |
|
19 |
parent::__construct();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
}
|
21 |
|
22 |
public function get_page_title()
|
@@ -143,6 +161,25 @@ final class NF_Admin_Menus_ImportExport extends NF_Abstracts_Submenu
|
|
143 |
|
144 |
wp_enqueue_script( 'ninja_forms_admin_import_export' );
|
145 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
Ninja_Forms::template( 'admin-menu-import-export.html.php', compact( 'tabs', 'active_tab' ) );
|
147 |
}
|
148 |
|
7 |
public $menu_slug = 'nf-import-export';
|
8 |
|
9 |
public function __construct()
|
10 |
+
{
|
11 |
add_action( 'init', array( $this, 'import_form_listener' ), 0 );
|
12 |
add_action( 'init', array( $this, 'export_form_listener' ), 0 );
|
13 |
|
17 |
add_filter( 'ninja_forms_before_import_fields', array( $this, 'import_fields_backwards_compatibility' ) );
|
18 |
|
19 |
parent::__construct();
|
20 |
+
|
21 |
+
add_action( 'admin_init', array( $this, 'nf_upgrade_redirect' ) );
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* If we have required updates, redirect to the main Ninja Forms page
|
26 |
+
*/
|
27 |
+
public function nf_upgrade_redirect() {
|
28 |
+
global $pagenow;
|
29 |
+
|
30 |
+
if( "1" == get_option( 'ninja_forms_needs_updates' ) ) {
|
31 |
+
remove_submenu_page( $this->parent_slug, $this->menu_slug );
|
32 |
+
if( 'admin.php' == $pagenow && 'nf-import-export' == $_GET[ 'page' ] ) {
|
33 |
+
|
34 |
+
wp_safe_redirect( admin_url( 'admin.php?page=ninja-forms' ), 301 );
|
35 |
+
exit;
|
36 |
+
}
|
37 |
+
}
|
38 |
}
|
39 |
|
40 |
public function get_page_title()
|
161 |
|
162 |
wp_enqueue_script( 'ninja_forms_admin_import_export' );
|
163 |
|
164 |
+
wp_localize_script( 'ninja_forms_admin_import_export', 'nfAdmin', array(
|
165 |
+
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
166 |
+
'batchNonce' => wp_create_nonce( 'ninja_forms_batch_nonce' ),
|
167 |
+
'i18n' => array(
|
168 |
+
'trashExpiredSubsMessage' => __( 'Are you sure you want to trash all expired submissions?', 'ninja-forms' ),
|
169 |
+
'trashExpiredSubsButtonPrimary' => __( 'Trash', 'ninja-forms' ),
|
170 |
+
'trashExpiredSubsButtonSecondary' => __( 'Cancel', 'ninja-forms' ),
|
171 |
+
),
|
172 |
+
'builderURL' => admin_url( 'admin.php?page=ninja-forms&form_id=' ),
|
173 |
+
));
|
174 |
+
|
175 |
+
wp_enqueue_script( 'jBox', Ninja_Forms::$url . 'assets/js/lib/jBox.min.js', array( 'jquery' ) );
|
176 |
+
wp_enqueue_style( 'jBox', Ninja_Forms::$url . 'assets/css/jBox.css' );
|
177 |
+
wp_enqueue_script( 'nf-ninja-modal', Ninja_Forms::$url . 'assets/js/lib/ninjaModal.js', array( 'jquery' ) );
|
178 |
+
wp_enqueue_script( 'nf-batch-processor', Ninja_Forms::$url . 'assets/js/lib/batch-processor.js', array( 'jquery' ) );
|
179 |
+
wp_enqueue_style( 'nf-font-awesome', Ninja_Forms::$url . 'assets/css/font-awesome.min.css' );
|
180 |
+
|
181 |
+
|
182 |
+
|
183 |
Ninja_Forms::template( 'admin-menu-import-export.html.php', compact( 'tabs', 'active_tab' ) );
|
184 |
}
|
185 |
|
includes/Admin/Menus/Settings.php
CHANGED
@@ -154,12 +154,44 @@ final class NF_Admin_Menus_Settings extends NF_Abstracts_Submenu
|
|
154 |
wp_enqueue_style( 'nf-combobox', Ninja_Forms::$url . 'assets/css/combobox.css' );
|
155 |
wp_enqueue_style( 'jBox', Ninja_Forms::$url . 'assets/css/jBox.css' );
|
156 |
wp_register_script( 'ninja_forms_admin_menu_settings', Ninja_Forms::$url . 'assets/js/admin-settings.js', array( 'jquery' ), FALSE, TRUE );
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
wp_localize_script( 'ninja_forms_admin_menu_settings', 'nf_settings', array(
|
158 |
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
159 |
'forms' => $form_options,
|
160 |
'nf_nuke_title' => __( 'Remove ALL Ninja Forms data and uninstall?', 'ninja-forms' ),
|
161 |
'nonce' => wp_create_nonce( "ninja_forms_settings_nonce" ),
|
162 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
'i18n' => array(
|
164 |
'downgradeMessage' => __( 'Are you sure you want to downgrade?', 'ninja-forms' ),
|
165 |
'downgradeWarningMessage' => __( 'You WILL lose any forms or submissions created on this version of Ninja Forms.', 'ninja-forms' ),
|
@@ -173,6 +205,7 @@ final class NF_Admin_Menus_Settings extends NF_Abstracts_Submenu
|
|
173 |
'allow_telemetry' => $allow_tel,
|
174 |
));
|
175 |
wp_enqueue_script( 'nf-ninja-modal', Ninja_Forms::$url . 'assets/js/lib/ninjaModal.js' );
|
|
|
176 |
wp_enqueue_style( 'nf-font-awesome', Ninja_Forms::$url . 'assets/css/font-awesome.min.css' );
|
177 |
|
178 |
|
154 |
wp_enqueue_style( 'nf-combobox', Ninja_Forms::$url . 'assets/css/combobox.css' );
|
155 |
wp_enqueue_style( 'jBox', Ninja_Forms::$url . 'assets/css/jBox.css' );
|
156 |
wp_register_script( 'ninja_forms_admin_menu_settings', Ninja_Forms::$url . 'assets/js/admin-settings.js', array( 'jquery' ), FALSE, TRUE );
|
157 |
+
|
158 |
+
/**
|
159 |
+
* This wp_localize_script call should eventually be removed.
|
160 |
+
*
|
161 |
+
* TODO: Remove this function call when we've replaced references to nf_settings in our JS with nfAdmin.
|
162 |
+
*/
|
163 |
wp_localize_script( 'ninja_forms_admin_menu_settings', 'nf_settings', array(
|
164 |
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
165 |
'forms' => $form_options,
|
166 |
'nf_nuke_title' => __( 'Remove ALL Ninja Forms data and uninstall?', 'ninja-forms' ),
|
167 |
'nonce' => wp_create_nonce( "ninja_forms_settings_nonce" ),
|
168 |
+
'batchNonce' => wp_create_nonce( 'ninja_forms_batch_nonce' ),
|
169 |
+
'i18n' => array(
|
170 |
+
'downgradeMessage' => __( 'Are you sure you want to downgrade?', 'ninja-forms' ),
|
171 |
+
'downgradeWarningMessage' => __( 'You WILL lose any forms or submissions created on this version of Ninja Forms.', 'ninja-forms' ),
|
172 |
+
'downgradeConfirmMessage' => __( 'Type ', 'ninja-forms' ) . '<span style="color: red";>' . 'DOWNGRADE' . "</span>" . __( ' to confirm.', 'ninja-forms' ),
|
173 |
+
'downgradeButtonPrimary' => __( 'Downgrade', 'ninja-forms'),
|
174 |
+
'downgradeButtonSecondary' => __( 'Cancel', 'ninja-forms' ),
|
175 |
+
'trashExpiredSubsMessage' => __( 'Are you sure you want to trash all expired submissions?', 'ninja-forms' ),
|
176 |
+
'trashExpiredSubsButtonPrimary' => __( 'Trash', 'ninja-forms' ),
|
177 |
+
'trashExpiredSubsButtonSecondary' => __( 'Cancel', 'ninja-forms' ),
|
178 |
+
),
|
179 |
+
'allow_telemetry' => $allow_tel,
|
180 |
+
));
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Duplicating the localization above with an nfAdmin variable for consistency.
|
184 |
+
*
|
185 |
+
* Eventually, we should remove all references to nf_settings, which isn't very descriptive or specific with nfAdmin instead.
|
186 |
+
*
|
187 |
+
* TODO: Replace references to nf_settings object in admin JS files with nfAdmin.
|
188 |
+
*/
|
189 |
+
wp_localize_script( 'ninja_forms_admin_menu_settings', 'nfAdmin', array(
|
190 |
+
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
191 |
+
'forms' => $form_options,
|
192 |
+
'nf_nuke_title' => __( 'Remove ALL Ninja Forms data and uninstall?', 'ninja-forms' ),
|
193 |
+
'nonce' => wp_create_nonce( "ninja_forms_settings_nonce" ),
|
194 |
+
'batchNonce' => wp_create_nonce( 'ninja_forms_batch_nonce' ),
|
195 |
'i18n' => array(
|
196 |
'downgradeMessage' => __( 'Are you sure you want to downgrade?', 'ninja-forms' ),
|
197 |
'downgradeWarningMessage' => __( 'You WILL lose any forms or submissions created on this version of Ninja Forms.', 'ninja-forms' ),
|
205 |
'allow_telemetry' => $allow_tel,
|
206 |
));
|
207 |
wp_enqueue_script( 'nf-ninja-modal', Ninja_Forms::$url . 'assets/js/lib/ninjaModal.js' );
|
208 |
+
wp_enqueue_script( 'nf-ninja-batch-processor', Ninja_Forms::$url . 'assets/js/lib/batch-processor.js' );
|
209 |
wp_enqueue_style( 'nf-font-awesome', Ninja_Forms::$url . 'assets/css/font-awesome.min.css' );
|
210 |
|
211 |
|
includes/Admin/Menus/Submissions.php
CHANGED
@@ -29,7 +29,7 @@ final class NF_Admin_Menus_Submissions extends NF_Abstracts_Submenu
|
|
29 |
* Constructor
|
30 |
*/
|
31 |
public function __construct()
|
32 |
-
{
|
33 |
parent::__construct();
|
34 |
|
35 |
add_filter( 'manage_nf_sub_posts_columns', array( $this, 'change_columns' ) );
|
@@ -56,6 +56,23 @@ final class NF_Admin_Menus_Submissions extends NF_Abstracts_Submenu
|
|
56 |
|
57 |
// This will only run on our post type.
|
58 |
add_action( 'views_edit-nf_sub', array( $this, 'change_views' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
|
61 |
/**
|
29 |
* Constructor
|
30 |
*/
|
31 |
public function __construct()
|
32 |
+
{
|
33 |
parent::__construct();
|
34 |
|
35 |
add_filter( 'manage_nf_sub_posts_columns', array( $this, 'change_columns' ) );
|
56 |
|
57 |
// This will only run on our post type.
|
58 |
add_action( 'views_edit-nf_sub', array( $this, 'change_views' ) );
|
59 |
+
|
60 |
+
// add_action( 'admin_init', array( $this, 'nf_upgrade_redirect' ) );
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* If we have required updates, redirect to the main Ninja Forms page
|
65 |
+
*/
|
66 |
+
public function nf_upgrade_redirect() {
|
67 |
+
global $pagenow;
|
68 |
+
|
69 |
+
if( "1" == get_option( 'ninja_forms_needs_updates' ) ) {
|
70 |
+
// remove_submenu_page( $this->parent_slug, $this->menu_slug );
|
71 |
+
// if( 'edit.php' == $pagenow && 'nf_sub' == $_GET[ 'post_type' ] ) {
|
72 |
+
// wp_safe_redirect( admin_url( 'admin.php?page=ninja-forms' ), 301 );
|
73 |
+
// exit;
|
74 |
+
// }
|
75 |
+
}
|
76 |
}
|
77 |
|
78 |
/**
|
includes/Admin/Menus/SystemStatus.php
CHANGED
@@ -165,6 +165,8 @@ final class NF_Admin_Menus_SystemStatus extends NF_Abstracts_Submenu
|
|
165 |
__( 'Home URL','ninja-forms' ) => home_url(),
|
166 |
__( 'Site URL','ninja-forms' ) => site_url(),
|
167 |
__( 'Ninja Forms Version','ninja-forms' ) => esc_html( Ninja_Forms::VERSION ),
|
|
|
|
|
168 |
__( 'WP Version','ninja-forms' ) => $wp_version . ' - ' . $wp_compatible,
|
169 |
__( 'WP Multisite Enabled','ninja-forms' ) => $multisite,
|
170 |
__( 'Web Server Info','ninja-forms' ) => esc_html( $_SERVER['SERVER_SOFTWARE'] ),
|
165 |
__( 'Home URL','ninja-forms' ) => home_url(),
|
166 |
__( 'Site URL','ninja-forms' ) => site_url(),
|
167 |
__( 'Ninja Forms Version','ninja-forms' ) => esc_html( Ninja_Forms::VERSION ),
|
168 |
+
__( 'Ninja Forms DB Version', 'ninja-forms' ) => get_option( 'ninja_forms_db_version' ),
|
169 |
+
__( 'Ninja Forms Gatekeeper', 'ninja-forms' ) => WPN_Helper::get_zuul(),
|
170 |
__( 'WP Version','ninja-forms' ) => $wp_version . ' - ' . $wp_compatible,
|
171 |
__( 'WP Multisite Enabled','ninja-forms' ) => $multisite,
|
172 |
__( 'Web Server Info','ninja-forms' ) => esc_html( $_SERVER['SERVER_SOFTWARE'] ),
|
includes/Admin/Processes/ChunkPublish.php
CHANGED
@@ -8,7 +8,7 @@ class NF_Admin_Processes_ChunkPublish extends NF_Abstracts_BatchProcess
|
|
8 |
// header( 'Content-Type: application/json' );
|
9 |
private $data;
|
10 |
private $form_id;
|
11 |
-
|
12 |
'last_request' => 'failure',
|
13 |
'batch_complete' => false,
|
14 |
);
|
8 |
// header( 'Content-Type: application/json' );
|
9 |
private $data;
|
10 |
private $form_id;
|
11 |
+
protected $response = array(
|
12 |
'last_request' => 'failure',
|
13 |
'batch_complete' => false,
|
14 |
);
|
includes/Admin/Processes/DataCleanup.php
DELETED
@@ -1,131 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class NF_Abstracts_Batch_Process
|
5 |
-
*/
|
6 |
-
class NF_Admin_Processes_DataCleanup extends NF_Abstracts_BatchProcess
|
7 |
-
{
|
8 |
-
private $response = array(
|
9 |
-
'batch_complete' => false
|
10 |
-
);
|
11 |
-
protected $delete = array();
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Constructor
|
15 |
-
*/
|
16 |
-
public function __construct( $data = array() )
|
17 |
-
{
|
18 |
-
//Bail if we aren't in the admin.
|
19 |
-
if ( ! is_admin() )
|
20 |
-
return false;
|
21 |
-
// Run process.
|
22 |
-
$this->process();
|
23 |
-
}
|
24 |
-
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Function to loop over the batch.
|
28 |
-
*/
|
29 |
-
public function process()
|
30 |
-
{
|
31 |
-
global $wpdb;
|
32 |
-
// If we've not already started the cleanup process...
|
33 |
-
if ( ! get_option( 'nf_doing_data_cleanup' ) ) {
|
34 |
-
// Run the startup process.
|
35 |
-
$this->startup();
|
36 |
-
} // Otherwise... (We've already run startup.)
|
37 |
-
else {
|
38 |
-
// Get our data.
|
39 |
-
$data = get_option( 'nf_data_cleanup_ids' );
|
40 |
-
$this->delete = explode( ',', $data );
|
41 |
-
}
|
42 |
-
// If our array isn't emtpy...
|
43 |
-
if ( ! empty( $this->delete ) ) {
|
44 |
-
// Fetch the last item on it.
|
45 |
-
$id = array_pop( $this->delete );
|
46 |
-
// Get a list of post IDs to delete.
|
47 |
-
$sql = "SELECT DISTINCT(`id`) FROM `" . $wpdb->prefix . "posts` WHERE `id` IN( SELECT DISTINCT(`post_id`) FROM `" . $wpdb->prefix . "postmeta` WHERE `meta_key` = '_form_id' AND `meta_value` = '" . $id . "' ) AND `post_type` = 'nf_sub' LIMIT 500";
|
48 |
-
$result = $wpdb->get_results( $sql, 'ARRAY_A' );
|
49 |
-
// If we got 500 or more results...
|
50 |
-
if ( 500 == count( $result ) ) {
|
51 |
-
// Put this id back in our array to run again.
|
52 |
-
array_push( $this->delete, $id );
|
53 |
-
}
|
54 |
-
// Convert our results to something we can use in a query.
|
55 |
-
array_walk( $result, array( $this, 'smush_results' ) );
|
56 |
-
$sub_sql = implode( ', ', $result );
|
57 |
-
// If we have something to query...
|
58 |
-
if ( '' != $sub_sql ) {
|
59 |
-
// Delete postmeta data.
|
60 |
-
$sql = "DELETE FROM `" . $wpdb->prefix . "postmeta` WHERE `post_id` IN(" . $sub_sql . ")";
|
61 |
-
$wpdb->query( $sql );
|
62 |
-
// Delete post data.
|
63 |
-
$sql = "DELETE FROM `" . $wpdb->prefix . "posts` WHERE `id` IN(" . $sub_sql . ")";
|
64 |
-
$wpdb->query( $sql );
|
65 |
-
}
|
66 |
-
}
|
67 |
-
// If our array isn't empty...
|
68 |
-
if ( ! empty( $this->delete ) ) {
|
69 |
-
// Determine how many steps we have left.
|
70 |
-
$this->response[ 'step_remaining' ] = count( $this->delete );
|
71 |
-
update_option( 'nf_data_cleanup_ids', implode( ',', $this->delete ) );
|
72 |
-
echo wp_json_encode( $this->response );
|
73 |
-
wp_die();
|
74 |
-
}
|
75 |
-
// Run our cleanup process.
|
76 |
-
$this->cleanup();
|
77 |
-
echo wp_json_encode( $this->response );
|
78 |
-
wp_die();
|
79 |
-
}
|
80 |
-
|
81 |
-
|
82 |
-
/**
|
83 |
-
* Function to run any setup steps necessary to begin processing.
|
84 |
-
*/
|
85 |
-
public function startup()
|
86 |
-
{
|
87 |
-
global $wpdb;
|
88 |
-
// Get a list of IDs from the forms table.
|
89 |
-
$sql = "SELECT DISTINCT(`id`) FROM `" . $wpdb->prefix . "nf3_forms`";
|
90 |
-
$forms = $wpdb->get_results( $sql, 'ARRAY_A' );
|
91 |
-
// Get a list of IDs from the Submissions data.
|
92 |
-
$sql = "SELECT DISTINCT(m.meta_value) AS id FROM `" . $wpdb->prefix . "postmeta` AS m LEFT JOIN `" . $wpdb->prefix . "posts` AS p on p.id = m.post_id WHERE m.meta_key = '_form_id' AND p.post_type = 'nf_sub'";
|
93 |
-
$sub_forms = $wpdb->get_results( $sql, 'ARRAY_A' );
|
94 |
-
// For each form ID in the submission records...
|
95 |
-
foreach( $sub_forms AS $form ) {
|
96 |
-
// If the form is not currently defined in our forms table...
|
97 |
-
if ( ! in_array( $form, $forms ) ) {
|
98 |
-
// Add it to our list of things to delete.
|
99 |
-
$this->delete[] = $form[ 'id' ];
|
100 |
-
}
|
101 |
-
}
|
102 |
-
// Get our number of steps for the progress bar.
|
103 |
-
$this->response[ 'step_total' ] = count( $this->delete );
|
104 |
-
// Flag startup done.
|
105 |
-
add_option( 'nf_doing_data_cleanup', 'true' );
|
106 |
-
}
|
107 |
-
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Function to cleanup any lingering temporary elements of a batch process after completion.
|
111 |
-
*/
|
112 |
-
public function cleanup()
|
113 |
-
{
|
114 |
-
global $wpdb;
|
115 |
-
// Delete our options.
|
116 |
-
delete_option( 'nf_data_cleanup_ids' );
|
117 |
-
delete_option( 'nf_doing_data_cleanup' );
|
118 |
-
// Add our "finished" option.
|
119 |
-
add_option( 'ninja_forms_data_is_clean', 'true' );
|
120 |
-
// Tell our JS that we're done.
|
121 |
-
$this->response[ 'step_remaining' ] = 0;
|
122 |
-
$this->response[ 'batch_complete' ] = true;
|
123 |
-
}
|
124 |
-
|
125 |
-
/**
|
126 |
-
* Function to compress data array and eliminate unnecessary keys.
|
127 |
-
*/
|
128 |
-
public function smush_results( &$value, $key ) {
|
129 |
-
$value = $value[ 'id' ];
|
130 |
-
}
|
131 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/Admin/Processes/ExpiredSubmissionCleanup.php
CHANGED
@@ -5,41 +5,53 @@
|
|
5 |
*/
|
6 |
class NF_Admin_Processes_ExpiredSubmissionCleanup extends NF_Abstracts_BatchProcess
|
7 |
{
|
8 |
-
|
9 |
protected $expired_subs = array();
|
10 |
|
11 |
-
private $response = array(
|
12 |
-
'batch_complete' => false
|
13 |
-
);
|
14 |
-
|
15 |
/**
|
16 |
-
*
|
17 |
*/
|
18 |
-
public function
|
19 |
{
|
20 |
-
//
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
-
|
25 |
-
|
|
|
|
|
|
|
26 |
}
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
/**
|
30 |
* Function to loop over the batch.
|
|
|
|
|
|
|
31 |
*/
|
32 |
public function process()
|
33 |
{
|
34 |
-
if ( ! get_option( 'nf_doing_expired_submission_cleanup' ) ) {
|
35 |
-
// Run the startup process.
|
36 |
-
$this->startup();
|
37 |
-
} // Otherwise... (We've already run startup.)
|
38 |
-
else {
|
39 |
-
// Get our remaining submissions from record.
|
40 |
-
$data = get_option( 'nf_expired_submissions' );
|
41 |
-
$this->expired_subs = $data;
|
42 |
-
}
|
43 |
|
44 |
// For the first 250 in the array.
|
45 |
for( $i = 0; $i < 250; $i++ ){
|
@@ -53,68 +65,32 @@ class NF_Admin_Processes_ExpiredSubmissionCleanup extends NF_Abstracts_BatchProc
|
|
53 |
|
54 |
// If our subs array isn't empty...
|
55 |
if( ! empty( $this->expired_subs ) ) {
|
56 |
-
//
|
57 |
-
$this->response[ 'step_remaining' ] = $this->get_steps();
|
58 |
update_option( 'nf_expired_submissions', $this->expired_subs );
|
59 |
-
|
60 |
-
|
61 |
}
|
62 |
|
63 |
-
//
|
64 |
-
$this->
|
65 |
-
echo wp_json_encode( $this->response );
|
66 |
-
wp_die();
|
67 |
}
|
68 |
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Function to run any setup steps necessary to begin processing.
|
72 |
-
*/
|
73 |
-
public function startup()
|
74 |
-
{
|
75 |
-
// Retrieves the option that contains all of our expiration data.
|
76 |
-
$expired_sub_option = get_option( 'nf_sub_expiration', array() );
|
77 |
-
|
78 |
-
// Loop over our options and ...
|
79 |
-
foreach( $expired_sub_option as $sub ) {
|
80 |
-
/*
|
81 |
-
* Separate our $option values into two positions
|
82 |
-
* $option[ 0 ] = ( int ) form_id
|
83 |
-
* $option[ 1 ] = ( int ) expiration time in days.
|
84 |
-
*/
|
85 |
-
$sub = explode( ',', $sub );
|
86 |
-
|
87 |
-
$expired_subs = $this->get_expired_subs( $sub[ 0 ], $sub[ 1 ] );
|
88 |
-
|
89 |
-
// Use the helper method to build an array of expired subs.
|
90 |
-
$this->expired_subs = array_merge( $this->expired_subs, $expired_subs );
|
91 |
-
}
|
92 |
-
|
93 |
-
// Determine how many steps this will take.
|
94 |
-
$this->response[ 'step_total' ] = $this->get_steps();
|
95 |
-
|
96 |
-
|
97 |
-
add_option( 'nf_doing_expired_submission_cleanup', 'true' );
|
98 |
-
}
|
99 |
-
|
100 |
-
|
101 |
/**
|
102 |
* Function to cleanup any lingering temporary elements of a batch process after completion.
|
|
|
|
|
|
|
103 |
*/
|
104 |
public function cleanup()
|
105 |
{
|
106 |
-
// Delete our options.
|
107 |
-
delete_option('nf_doing_expired_submission_cleanup' );
|
108 |
delete_option( 'nf_expired_submissions' );
|
109 |
-
|
110 |
-
// Tell our JS that we're done.
|
111 |
-
$this->response[ 'batch_complete' ] = true;
|
112 |
}
|
113 |
|
114 |
-
|
115 |
* Get Steps
|
116 |
* Determines the amount of steps needed for the step processors.
|
117 |
*
|
|
|
118 |
* @return int of the number of steps.
|
119 |
*/
|
120 |
public function get_steps()
|
5 |
*/
|
6 |
class NF_Admin_Processes_ExpiredSubmissionCleanup extends NF_Abstracts_BatchProcess
|
7 |
{
|
8 |
+
protected $_slug = 'expired_submission_cleanup';
|
9 |
protected $expired_subs = array();
|
10 |
|
|
|
|
|
|
|
|
|
11 |
/**
|
12 |
+
* Function to run any setup steps necessary to begin processing.
|
13 |
*/
|
14 |
+
public function startup()
|
15 |
{
|
16 |
+
// Retrieves the option that contains all of our expiration data.
|
17 |
+
$expired_sub_option = get_option( 'nf_sub_expiration', array() );
|
18 |
+
|
19 |
+
// Loop over our options and ...
|
20 |
+
foreach( $expired_sub_option as $sub ) {
|
21 |
+
/*
|
22 |
+
* Separate our $option values into two positions
|
23 |
+
* $option[ 0 ] = ( int ) form_id
|
24 |
+
* $option[ 1 ] = ( int ) expiration time in days.
|
25 |
+
*/
|
26 |
+
$sub = explode( ',', $sub );
|
27 |
|
28 |
+
$expired_subs = $this->get_expired_subs( $sub[ 0 ], $sub[ 1 ] );
|
29 |
+
|
30 |
+
// Use the helper method to build an array of expired subs.
|
31 |
+
$this->expired_subs = array_merge( $this->expired_subs, $expired_subs );
|
32 |
+
}
|
33 |
}
|
34 |
|
35 |
+
/**
|
36 |
+
* Function to run any setup steps necessary to begin processing for steps after the first.
|
37 |
+
*
|
38 |
+
* @since 3.4.0
|
39 |
+
* @return void
|
40 |
+
*/
|
41 |
+
public function restart()
|
42 |
+
{
|
43 |
+
// Get our remaining submissions from record.
|
44 |
+
$this->expired_subs = get_option( 'nf_expired_submissions', array() );
|
45 |
+
}
|
46 |
|
47 |
/**
|
48 |
* Function to loop over the batch.
|
49 |
+
*
|
50 |
+
* @since 3.4.0
|
51 |
+
* @return void
|
52 |
*/
|
53 |
public function process()
|
54 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
// For the first 250 in the array.
|
57 |
for( $i = 0; $i < 250; $i++ ){
|
65 |
|
66 |
// If our subs array isn't empty...
|
67 |
if( ! empty( $this->expired_subs ) ) {
|
68 |
+
// Update nf_expired_submissions so that we can use it in our next step.
|
|
|
69 |
update_option( 'nf_expired_submissions', $this->expired_subs );
|
70 |
+
// End processing and move to the next step.
|
71 |
+
$this->next_step();
|
72 |
}
|
73 |
|
74 |
+
// If we get here, then we're ready to end batch processing.
|
75 |
+
$this->batch_complete();
|
|
|
|
|
76 |
}
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
/**
|
79 |
* Function to cleanup any lingering temporary elements of a batch process after completion.
|
80 |
+
*
|
81 |
+
* @since 3.4.0
|
82 |
+
* @return void
|
83 |
*/
|
84 |
public function cleanup()
|
85 |
{
|
|
|
|
|
86 |
delete_option( 'nf_expired_submissions' );
|
|
|
|
|
|
|
87 |
}
|
88 |
|
89 |
+
/**
|
90 |
* Get Steps
|
91 |
* Determines the amount of steps needed for the step processors.
|
92 |
*
|
93 |
+
* @since 3.4.0
|
94 |
* @return int of the number of steps.
|
95 |
*/
|
96 |
public function get_steps()
|
includes/Admin/Processes/ImportForm.php
ADDED
@@ -0,0 +1,856 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class NF_Abstracts_Batch_Process
|
5 |
+
*/
|
6 |
+
class NF_Admin_Processes_ImportForm extends NF_Abstracts_BatchProcess
|
7 |
+
{
|
8 |
+
protected $_slug = 'import_form';
|
9 |
+
|
10 |
+
private $fields_per_step = 20;
|
11 |
+
|
12 |
+
protected $form;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Store an array of columns that we want to store in our table rather than meta.
|
16 |
+
*
|
17 |
+
* This array stores the column name and the name of the setting that it maps to.
|
18 |
+
*
|
19 |
+
* The format is:
|
20 |
+
*
|
21 |
+
* array( 'COLUMN_NAME' => 'SETTING_NAME' )
|
22 |
+
*/
|
23 |
+
protected $forms_db_columns = array(
|
24 |
+
'title' => 'title',
|
25 |
+
'created_at' => 'created_at',
|
26 |
+
'form_title' => 'title',
|
27 |
+
'default_label_pos' => 'default_label_pos',
|
28 |
+
'show_title' => 'show_title',
|
29 |
+
'clear_complete' => 'clear_complete',
|
30 |
+
'hide_complete' => 'hide_complete',
|
31 |
+
'logged_in' => 'logged_in',
|
32 |
+
'seq_num' => 'seq_num',
|
33 |
+
);
|
34 |
+
|
35 |
+
protected $fields_db_columns = array(
|
36 |
+
'parent_id' => 'parent_id',
|
37 |
+
'id' => 'id',
|
38 |
+
'key' => 'key',
|
39 |
+
'type' => 'type',
|
40 |
+
'label' => 'label',
|
41 |
+
'field_key' => 'key',
|
42 |
+
'field_label' => 'label',
|
43 |
+
'order' => 'order',
|
44 |
+
'required' => 'required',
|
45 |
+
'default_value' => 'default',
|
46 |
+
'label_pos' => 'label_pos',
|
47 |
+
'personally_identifiable' => 'personally_identifiable',
|
48 |
+
);
|
49 |
+
|
50 |
+
protected $actions_db_columns = array(
|
51 |
+
'title' => 'title',
|
52 |
+
'key' =>'key',
|
53 |
+
'type' =>'type',
|
54 |
+
'active' =>'active',
|
55 |
+
'parent_id' =>'parent_id',
|
56 |
+
'created_at' =>'created_at',
|
57 |
+
'updated_at' =>'updated_at',
|
58 |
+
'label' =>'label',
|
59 |
+
);
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Function to run any setup steps necessary to begin processing.
|
63 |
+
*
|
64 |
+
* @since 3.4.0
|
65 |
+
* @return void
|
66 |
+
*/
|
67 |
+
public function startup()
|
68 |
+
{
|
69 |
+
// If we aren't passed any form content, bail.
|
70 |
+
if ( empty ( $_POST[ 'extraData' ][ 'content' ] ) ) {
|
71 |
+
// TODO: When we add error handling to the batch processor, this should be revisited.
|
72 |
+
$this->batch_complete();
|
73 |
+
}
|
74 |
+
|
75 |
+
$data = explode( ';base64,', $_POST[ 'extraData' ][ 'content' ] );
|
76 |
+
$data = base64_decode( $data[ 1 ] );
|
77 |
+
|
78 |
+
/**
|
79 |
+
* $data could now hold two things, depending on whether this was a 2.9 or 3.0 export.
|
80 |
+
*
|
81 |
+
* If it's a 3.0 export, the data will be json encoded.
|
82 |
+
* If it's a 2.9 export, the data will be serialized.
|
83 |
+
*
|
84 |
+
* We're first going to try to json_decode. If we don't get an array, we'll unserialize.
|
85 |
+
*/
|
86 |
+
|
87 |
+
$decoded_data = json_decode( WPN_Helper::json_cleanup( html_entity_decode( $data ) ), true );
|
88 |
+
|
89 |
+
// If we don't have an array, try unserializing
|
90 |
+
if ( ! is_array( $decoded_data ) ) {
|
91 |
+
$decoded_data = WPN_Helper::maybe_unserialize( $data );
|
92 |
+
}
|
93 |
+
|
94 |
+
// Try to utf8 decode our results.
|
95 |
+
$data = WPN_Helper::utf8_decode( $decoded_data );
|
96 |
+
|
97 |
+
// If json_encode returns false, then this is an invalid utf8 decode.
|
98 |
+
if ( ! json_encode( $data ) ) {
|
99 |
+
$data = $decoded_data;
|
100 |
+
}
|
101 |
+
|
102 |
+
$data = $this->import_form_backwards_compatibility( $data );
|
103 |
+
|
104 |
+
// $data is now a form array.
|
105 |
+
$this->form = $data;
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Check to see if we've got new field columns.
|
109 |
+
*
|
110 |
+
* We do this here instead of the get_sql_queries() method so that we don't hit the db multiple times.
|
111 |
+
*/
|
112 |
+
$sql = "SHOW COLUMNS FROM {$this->_db->prefix}nf3_fields LIKE 'field_key'";
|
113 |
+
$results = $this->_db->get_results( $sql );
|
114 |
+
|
115 |
+
/**
|
116 |
+
* If we don't have the field_key column, we need to remove our new columns.
|
117 |
+
*
|
118 |
+
* Also, set our db stage 1 tracker to false.
|
119 |
+
*/
|
120 |
+
if ( empty ( $results ) ) {
|
121 |
+
unset( $this->actions_db_columns[ 'label' ] );
|
122 |
+
$db_stage_one_complete = false;
|
123 |
+
} else {
|
124 |
+
// Add a form value that stores whether or not we have our new DB columns.
|
125 |
+
$db_stage_one_complete = true;
|
126 |
+
}
|
127 |
+
|
128 |
+
$this->form[ 'db_stage_one_complete' ] = $db_stage_one_complete;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* On processing steps after the first, we need to grab our data from our saved option.
|
133 |
+
*
|
134 |
+
* @since 3.4.0
|
135 |
+
* @return void
|
136 |
+
*/
|
137 |
+
public function restart()
|
138 |
+
{
|
139 |
+
// Get our remaining fields from the database.
|
140 |
+
$this->form = get_option( 'nf_import_form', $this->form, array() );
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Function to loop over the batch.
|
145 |
+
*
|
146 |
+
* @since 3.4.0
|
147 |
+
* @return void
|
148 |
+
*/
|
149 |
+
public function process()
|
150 |
+
{
|
151 |
+
/**
|
152 |
+
* Check to see if our $this->form var contains an 'ID' index.
|
153 |
+
*
|
154 |
+
* If it doesn't, then we need to:
|
155 |
+
* Insert our Form.
|
156 |
+
* Insert our Form Meta.
|
157 |
+
* Insert our Actions.
|
158 |
+
* Insert our Action Meta.
|
159 |
+
* Unset [ 'settings' ] and [ 'actions' ] from $this->form.
|
160 |
+
* Update $this->form[ 'ID' ].
|
161 |
+
* Save our processing option.
|
162 |
+
* Move on to the next step.
|
163 |
+
*/
|
164 |
+
if ( ! isset ( $this->form[ 'ID' ] ) ) {
|
165 |
+
$this->insert_form();
|
166 |
+
} else { // We have a form ID set.
|
167 |
+
$this->insert_fields();
|
168 |
+
}
|
169 |
+
|
170 |
+
// If we don't have any more fields to insert, we're done.
|
171 |
+
if ( empty( $this->form[ 'fields' ] ) ) {
|
172 |
+
// Update our form cache for the new form.
|
173 |
+
WPN_Helper::build_nf_cache( $this->form[ 'ID' ] );
|
174 |
+
// We're done with this batch process.
|
175 |
+
$this->batch_complete();
|
176 |
+
} else { // We have fields left to process.
|
177 |
+
/**
|
178 |
+
* If we have fields left, we need to reset the index.
|
179 |
+
* Since fields is a non-associative array, we are looping over it by sequential numeric index.
|
180 |
+
* Resetting the index ensures we always have a 0 -> COUNT() keys.
|
181 |
+
*/
|
182 |
+
$this->form[ 'fields' ] = array_values( $this->form[ 'fields' ] );
|
183 |
+
// Save our progress.
|
184 |
+
update_option( 'nf_import_form', $this->form, 'no' );
|
185 |
+
// Move on to the next step in processing.
|
186 |
+
$this->next_step();
|
187 |
+
}
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Function to cleanup any lingering temporary elements of a batch process after completion.
|
192 |
+
*/
|
193 |
+
public function cleanup()
|
194 |
+
{
|
195 |
+
// Remove the option we used to track between
|
196 |
+
delete_option( 'nf_import_form' );
|
197 |
+
// Return our new Form ID
|
198 |
+
$this->response[ 'form_id' ] = $this->form[ 'ID' ];
|
199 |
+
}
|
200 |
+
|
201 |
+
/*
|
202 |
+
* Get Steps
|
203 |
+
* Determines the amount of steps needed for the step processors.
|
204 |
+
*
|
205 |
+
* @return int of the number of steps.
|
206 |
+
*/
|
207 |
+
public function get_steps()
|
208 |
+
{
|
209 |
+
/**
|
210 |
+
* We want to run a step for every $this->fields_per_step fields on this form.
|
211 |
+
*
|
212 |
+
* If we have no fields, then we want to return 0.
|
213 |
+
*/
|
214 |
+
if ( ! isset ( $this->form[ 'fields' ] ) || empty ( $this->form[ 'fields' ] ) ) {
|
215 |
+
return 0;
|
216 |
+
}
|
217 |
+
|
218 |
+
$steps = count( $this->form[ 'fields' ] ) / $this->fields_per_step;
|
219 |
+
$steps = ceil( $steps );
|
220 |
+
return $steps;
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Insert our form using $this->_db->insert by building an array of column => value pairs and %s, %d types.
|
225 |
+
*
|
226 |
+
* @since 3.4.0
|
227 |
+
* @return void
|
228 |
+
*/
|
229 |
+
public function insert_form()
|
230 |
+
{
|
231 |
+
$insert_columns = array();
|
232 |
+
$insert_columns_types = array();
|
233 |
+
foreach ( $this->forms_db_columns as $column_name => $setting_name ) {
|
234 |
+
$insert_columns[ $column_name ] = $this->form[ 'settings' ][ $setting_name ];
|
235 |
+
if ( is_numeric( $this->form[ 'settings' ][ $setting_name ] ) ) {
|
236 |
+
array_push( $insert_columns_types, '%d' );
|
237 |
+
} else {
|
238 |
+
array_push( $insert_columns_types, '%s' );
|
239 |
+
}
|
240 |
+
}
|
241 |
+
|
242 |
+
$this->_db->insert( "{$this->_db->prefix}nf3_forms", $insert_columns, $insert_columns_types );
|
243 |
+
|
244 |
+
// Update our form ID with the newly inserted row ID.
|
245 |
+
$this->form[ 'ID' ] = $this->_db->insert_id;
|
246 |
+
|
247 |
+
$this->insert_form_meta();
|
248 |
+
$this->insert_actions();
|
249 |
+
|
250 |
+
// Remove our settings and actions array items.
|
251 |
+
unset( $this->form[ 'settings' ], $this->form[ 'actions' ] );
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Insert Form Meta.
|
256 |
+
*
|
257 |
+
* Loop over our remaining form settings that we need to insert into meta.
|
258 |
+
* Add them to our "Values" string for insertion later.
|
259 |
+
*
|
260 |
+
* @since 3.4.0
|
261 |
+
* @return void
|
262 |
+
*/
|
263 |
+
public function insert_form_meta()
|
264 |
+
{
|
265 |
+
$insert_values = '';
|
266 |
+
|
267 |
+
foreach( $this->form[ 'settings' ] as $meta_key => $meta_value ) {
|
268 |
+
$meta_value = maybe_serialize( $meta_value );
|
269 |
+
$this->_db->escape_by_ref( $meta_value );
|
270 |
+
$insert_values .= "( {$this->form[ 'ID' ]}, '{$meta_key}', '{$meta_value}'";
|
271 |
+
if ( $this->form[ 'db_stage_one_complete'] ) {
|
272 |
+
$insert_values .= ", '{$meta_key}', '{$meta_value}'";
|
273 |
+
}
|
274 |
+
$insert_values .= "),";
|
275 |
+
}
|
276 |
+
|
277 |
+
// Remove the trailing comma.
|
278 |
+
$insert_values = rtrim( $insert_values, ',' );
|
279 |
+
$insert_columns = '`parent_id`, `key`, `value`';
|
280 |
+
if ( $this->form[ 'db_stage_one_complete'] ) {
|
281 |
+
$insert_columns .= ', `meta_key`, `meta_value`';
|
282 |
+
}
|
283 |
+
|
284 |
+
// Create SQL string.
|
285 |
+
$sql = "INSERT INTO {$this->_db->prefix}nf3_form_meta ( {$insert_columns} ) VALUES {$insert_values}";
|
286 |
+
// Run our SQL query.
|
287 |
+
$this->_db->query( $sql );
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Insert Actions and Action Meta.
|
292 |
+
*
|
293 |
+
* Loop over actions for this form and insert actions and action meta.
|
294 |
+
*
|
295 |
+
* @since 3.4.0
|
296 |
+
* @return void
|
297 |
+
*/
|
298 |
+
public function insert_actions()
|
299 |
+
{
|
300 |
+
foreach( $this->form[ 'actions' ] as $action_settings ) {
|
301 |
+
$action_settings[ 'parent_id' ] = $this->form[ 'ID' ];
|
302 |
+
// Array that tracks which settings need to be meta and which are columns.
|
303 |
+
$action_meta = $action_settings;
|
304 |
+
$insert_columns = array();
|
305 |
+
$insert_columns_types = array();
|
306 |
+
// Loop over all our action columns to get their values.
|
307 |
+
foreach ( $this->actions_db_columns as $column_name => $setting_name ) {
|
308 |
+
$insert_columns[ $column_name ] = $action_settings[ $setting_name ];
|
309 |
+
if ( is_numeric( $action_settings[ $setting_name ] ) ) {
|
310 |
+
array_push( $insert_columns_types, '%d' );
|
311 |
+
} else {
|
312 |
+
array_push( $insert_columns_types, '%s' );
|
313 |
+
}
|
314 |
+
}
|
315 |
+
|
316 |
+
// Insert Action
|
317 |
+
$this->_db->insert( "{$this->_db->prefix}nf3_actions", $insert_columns, $insert_columns_types );
|
318 |
+
|
319 |
+
// Get our new action ID.
|
320 |
+
$action_id = $this->_db->insert_id;
|
321 |
+
|
322 |
+
// Insert Action Meta.
|
323 |
+
$insert_values = '';
|
324 |
+
/**
|
325 |
+
* Anything left in the $action_meta array should be inserted as meta.
|
326 |
+
*
|
327 |
+
* Loop over each of our settings and add it to our insert sql string.
|
328 |
+
*/
|
329 |
+
$insert_values = '';
|
330 |
+
foreach ( $action_meta as $meta_key => $meta_value ) {
|
331 |
+
$meta_value = maybe_serialize( $meta_value );
|
332 |
+
$this->_db->escape_by_ref( $meta_value );
|
333 |
+
$insert_values .= "( {$action_id}, '{$meta_key}', '{$meta_value}'";
|
334 |
+
if ( $this->form[ 'db_stage_one_complete'] ) {
|
335 |
+
$insert_values .= ", '{$meta_key}', '{$meta_value}'";
|
336 |
+
}
|
337 |
+
$insert_values .= "),";
|
338 |
+
}
|
339 |
+
|
340 |
+
// Remove the trailing comma.
|
341 |
+
$insert_values = rtrim( $insert_values, ',' );
|
342 |
+
$insert_columns = '`parent_id`, `key`, `value`';
|
343 |
+
if ( $this->form[ 'db_stage_one_complete'] ) {
|
344 |
+
$insert_columns .= ', `meta_key`, `meta_value`';
|
345 |
+
}
|
346 |
+
// Create SQL string.
|
347 |
+
$sql = "INSERT INTO {$this->_db->prefix}nf3_action_meta ( {$insert_columns} ) VALUES {$insert_values}";
|
348 |
+
|
349 |
+
// Run our SQL query.
|
350 |
+
$this->_db->query( $sql );
|
351 |
+
}
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* If we have a Form ID set, then we've already inserted our Form, Form Meta, Actions, and Action Meta.
|
356 |
+
* All we have left to insert are fields.
|
357 |
+
*
|
358 |
+
* Loop over our fields array and insert up to $this->fields_per_step.
|
359 |
+
* After we've inserted the field, unset it from our form array.
|
360 |
+
* Update our processing option with $this->form.
|
361 |
+
* Respond with the remaining steps.
|
362 |
+
*
|
363 |
+
* @since 3.4.0
|
364 |
+
* @return void
|
365 |
+
*/
|
366 |
+
public function insert_fields()
|
367 |
+
{
|
368 |
+
// Remove new field table columns if we haven't completed stage one of our DB conversion.
|
369 |
+
if ( ! $this->form[ 'db_stage_one_complete' ] ) {
|
370 |
+
// Remove field columns added after stage one.
|
371 |
+
unset( $this->fields_db_columns[ 'field_key' ] );
|
372 |
+
unset( $this->fields_db_columns[ 'field_label' ] );
|
373 |
+
unset( $this->fields_db_columns[ 'order' ] );
|
374 |
+
unset( $this->fields_db_columns[ 'required' ] );
|
375 |
+
unset( $this->fields_db_columns[ 'default_value' ] );
|
376 |
+
unset( $this->fields_db_columns[ 'label_pos' ] );
|
377 |
+
unset( $this->fields_db_columns[ 'personally_identifiable' ] );
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* Loop over our field array up to $this->fields_per_step.
|
382 |
+
*/
|
383 |
+
for ( $i = 0; $i < $this->fields_per_step; $i++ ) {
|
384 |
+
// If we don't have a field, skip this $i.
|
385 |
+
if ( ! isset ( $this->form[ 'fields' ][ $i ] ) ) continue;
|
386 |
+
|
387 |
+
$field_settings = $this->form[ 'fields' ][ $i ];
|
388 |
+
// Remove a field ID if we have one set.
|
389 |
+
unset( $field_settings[ 'id' ] );
|
390 |
+
$field_settings[ 'parent_id' ] = $this->form[ 'ID' ];
|
391 |
+
// Array that tracks which settings need to be meta and which are columns.
|
392 |
+
$field_meta = $field_settings;
|
393 |
+
$insert_columns = array();
|
394 |
+
$insert_columns_types = array();
|
395 |
+
// Loop over all our action columns to get their values.
|
396 |
+
foreach ( $this->fields_db_columns as $column_name => $setting_name ) {
|
397 |
+
$insert_columns[ $column_name ] = $field_settings[ $setting_name ];
|
398 |
+
if ( is_numeric( $field_settings[ $setting_name ] ) ) {
|
399 |
+
array_push( $insert_columns_types, '%d' );
|
400 |
+
} else {
|
401 |
+
array_push( $insert_columns_types, '%s' );
|
402 |
+
}
|
403 |
+
}
|
404 |
+
|
405 |
+
// Add our field to the database.
|
406 |
+
$this->_db->insert( "{$this->_db->prefix}nf3_fields", $insert_columns, $insert_columns_types );
|
407 |
+
|
408 |
+
/**
|
409 |
+
* Get our new field ID.
|
410 |
+
*/
|
411 |
+
$field_id = $this->_db->insert_id;
|
412 |
+
|
413 |
+
$insert_values = '';
|
414 |
+
/**
|
415 |
+
* Anything left in the $field_meta array should be inserted as meta.
|
416 |
+
*
|
417 |
+
* Loop over each of our settings and add it to our insert sql string.
|
418 |
+
*/
|
419 |
+
$insert_values = '';
|
420 |
+
foreach ( $field_meta as $meta_key => $meta_value ) {
|
421 |
+
$meta_value = maybe_serialize( $meta_value );
|
422 |
+
$this->_db->escape_by_ref( $meta_value );
|
423 |
+
$insert_values .= "( {$field_id}, '{$meta_key}', '{$meta_value}'";
|
424 |
+
if ( $this->form[ 'db_stage_one_complete'] ) {
|
425 |
+
$insert_values .= ", '{$meta_key}', '{$meta_value}'";
|
426 |
+
}
|
427 |
+
$insert_values .= "),";
|
428 |
+
}
|
429 |
+
|
430 |
+
// Remove the trailing comma.
|
431 |
+
$insert_values = rtrim( $insert_values, ',' );
|
432 |
+
$insert_columns = '`parent_id`, `key`, `value`';
|
433 |
+
if ( $this->form[ 'db_stage_one_complete'] ) {
|
434 |
+
$insert_columns .= ', `meta_key`, `meta_value`';
|
435 |
+
}
|
436 |
+
// Create SQL string.
|
437 |
+
$sql = "INSERT INTO {$this->_db->prefix}nf3_field_meta ( {$insert_columns} ) VALUES {$insert_values}";
|
438 |
+
|
439 |
+
// Run our SQL query.
|
440 |
+
$this->_db->query( $sql );
|
441 |
+
|
442 |
+
// Remove this field from our fields array.
|
443 |
+
unset( $this->form[ 'fields' ][ $i ] );
|
444 |
+
}
|
445 |
+
}
|
446 |
+
|
447 |
+
/*
|
448 |
+
|--------------------------------------------------------------------------
|
449 |
+
| Backwards Compatibility
|
450 |
+
|--------------------------------------------------------------------------
|
451 |
+
*/
|
452 |
+
|
453 |
+
public function import_form_backwards_compatibility( $import )
|
454 |
+
{
|
455 |
+
// Rename `data` to `settings`
|
456 |
+
if( isset( $import[ 'data' ] ) ){
|
457 |
+
$import[ 'settings' ] = $import[ 'data' ];
|
458 |
+
unset( $import[ 'data' ] );
|
459 |
+
}
|
460 |
+
|
461 |
+
// Rename `notifications` to `actions`
|
462 |
+
if( isset( $import[ 'notifications' ] ) ){
|
463 |
+
$import[ 'actions' ] = $import[ 'notifications' ];
|
464 |
+
unset( $import[ 'notifications' ] );
|
465 |
+
}
|
466 |
+
|
467 |
+
// Rename `form_title` to `title`
|
468 |
+
if( isset( $import[ 'settings' ][ 'form_title' ] ) ){
|
469 |
+
$import[ 'settings' ][ 'title' ] = $import[ 'settings' ][ 'form_title' ];
|
470 |
+
unset( $import[ 'settings' ][ 'form_title' ] );
|
471 |
+
}
|
472 |
+
|
473 |
+
// Convert `last_sub` to `_seq_num`
|
474 |
+
if( isset( $import[ 'settings' ][ 'last_sub' ] ) ) {
|
475 |
+
$import[ 'settings' ][ '_seq_num' ] = $import[ 'settings' ][ 'last_sub' ] + 1;
|
476 |
+
}
|
477 |
+
|
478 |
+
// Make sure
|
479 |
+
if( ! isset( $import[ 'fields' ] ) ){
|
480 |
+
$import[ 'fields' ] = array();
|
481 |
+
}
|
482 |
+
|
483 |
+
// `Field` to `Fields`
|
484 |
+
if( isset( $import[ 'field' ] ) ){
|
485 |
+
$import[ 'fields' ] = $import[ 'field' ];
|
486 |
+
unset( $import[ 'field' ] );
|
487 |
+
}
|
488 |
+
|
489 |
+
$import = apply_filters( 'ninja_forms_upgrade_settings', $import );
|
490 |
+
|
491 |
+
// Combine Field and Field Data
|
492 |
+
foreach( $import[ 'fields' ] as $key => $field ){
|
493 |
+
|
494 |
+
if( '_honeypot' == $field[ 'type' ] ) {
|
495 |
+
unset( $import[ 'fields' ][ $key ] );
|
496 |
+
continue;
|
497 |
+
}
|
498 |
+
|
499 |
+
if( ! $field[ 'type' ] ) {
|
500 |
+
unset( $import[ 'fields'][ $key ] );
|
501 |
+
continue;
|
502 |
+
}
|
503 |
+
|
504 |
+
// TODO: Split Credit Card field into multiple fields.
|
505 |
+
$field = $this->import_field_backwards_compatibility( $field );
|
506 |
+
|
507 |
+
if( isset( $field[ 'new_fields' ] ) ){
|
508 |
+
foreach( $field[ 'new_fields' ] as $new_field ){
|
509 |
+
$import[ 'fields' ][] = $new_field;
|
510 |
+
}
|
511 |
+
unset( $field[ 'new_fields' ] );
|
512 |
+
}
|
513 |
+
|
514 |
+
$import[ 'fields' ][ $key ] = $field;
|
515 |
+
}
|
516 |
+
|
517 |
+
$has_save_action = FALSE;
|
518 |
+
foreach( $import[ 'actions' ] as $key => $action ){
|
519 |
+
$action = $this->import_action_backwards_compatibility( $action );
|
520 |
+
$import[ 'actions' ][ $key ] = $action;
|
521 |
+
|
522 |
+
if( 'save' == $action[ 'type' ] ) $has_save_action = TRUE;
|
523 |
+
}
|
524 |
+
|
525 |
+
if( ! $has_save_action ) {
|
526 |
+
$import[ 'actions' ][] = array(
|
527 |
+
'type' => 'save',
|
528 |
+
'label' => __( 'Save Form', 'ninja-forms' ),
|
529 |
+
'active' => TRUE
|
530 |
+
);
|
531 |
+
}
|
532 |
+
|
533 |
+
$import = $this->import_merge_tags_backwards_compatibility( $import );
|
534 |
+
|
535 |
+
return apply_filters( 'ninja_forms_after_upgrade_settings', $import );
|
536 |
+
}
|
537 |
+
|
538 |
+
public function import_merge_tags_backwards_compatibility( $import )
|
539 |
+
{
|
540 |
+
$field_lookup = array();
|
541 |
+
|
542 |
+
foreach( $import[ 'fields' ] as $key => $field ){
|
543 |
+
|
544 |
+
if( ! isset( $field[ 'id' ] ) ) continue;
|
545 |
+
|
546 |
+
$field_id = $field[ 'id' ];
|
547 |
+
$field_key = $field[ 'type' ] . '_' . $field_id;
|
548 |
+
$field_lookup[ $field_id ] = $import[ 'fields' ][ $key ][ 'key' ] = $field_key;
|
549 |
+
}
|
550 |
+
|
551 |
+
foreach( $import[ 'actions' ] as $key => $action_settings ){
|
552 |
+
foreach( $action_settings as $setting => $value ){
|
553 |
+
foreach( $field_lookup as $field_id => $field_key ){
|
554 |
+
|
555 |
+
// Convert Tokenizer
|
556 |
+
$token = 'field_' . $field_id;
|
557 |
+
if( ! is_array( $value ) ) {
|
558 |
+
if (FALSE !== strpos($value, $token)) {
|
559 |
+
$value = str_replace($token, '{field:' . $field_key . '}', $value);
|
560 |
+
}
|
561 |
+
}
|
562 |
+
|
563 |
+
// Convert Shortcodes
|
564 |
+
$shortcode = "[ninja_forms_field id=$field_id]";
|
565 |
+
if( ! is_array( $value ) ) {
|
566 |
+
if ( FALSE !== strpos( $value, $shortcode ) ) {
|
567 |
+
$value = str_replace( $shortcode, '{field:' . $field_key . '}', $value );
|
568 |
+
}
|
569 |
+
}
|
570 |
+
}
|
571 |
+
|
572 |
+
//Checks for the nf_sub_seq_num short code and replaces it with the submission sequence merge tag
|
573 |
+
$sub_seq = '[nf_sub_seq_num]';
|
574 |
+
if( ! is_array( $value ) ) {
|
575 |
+
if( FALSE !== strpos( $value, $sub_seq ) ){
|
576 |
+
$value = str_replace( $sub_seq, '{submission:sequence}', $value );
|
577 |
+
}
|
578 |
+
}
|
579 |
+
|
580 |
+
if( ! is_array( $value ) ) {
|
581 |
+
if (FALSE !== strpos($value, '[ninja_forms_all_fields]')) {
|
582 |
+
$value = str_replace('[ninja_forms_all_fields]', '{field:all_fields}', $value);
|
583 |
+
}
|
584 |
+
}
|
585 |
+
$action_settings[ $setting ] = $value;
|
586 |
+
$import[ 'actions' ][ $key ] = $action_settings;
|
587 |
+
}
|
588 |
+
}
|
589 |
+
|
590 |
+
return $import;
|
591 |
+
}
|
592 |
+
|
593 |
+
public function import_action_backwards_compatibility( $action )
|
594 |
+
{
|
595 |
+
// Remove `_` from type
|
596 |
+
if( isset( $action[ 'type' ] ) ) {
|
597 |
+
$action['type'] = str_replace('_', '', $action['type']);
|
598 |
+
}
|
599 |
+
|
600 |
+
if( 'email' == $action[ 'type' ] ){
|
601 |
+
$action[ 'to' ] = str_replace( '`', ',', $action[ 'to' ] );
|
602 |
+
$action[ 'email_subject' ] = str_replace( '`', ',', $action[ 'email_subject' ] );
|
603 |
+
$action[ 'cc' ] = str_replace( '`', ',', $action[ 'cc' ] );
|
604 |
+
$action[ 'bcc' ] = str_replace( '`', ',', $action[ 'bcc' ] );
|
605 |
+
// If our email is in plain text...
|
606 |
+
if ( $action[ 'email_format' ] == 'plain' ) {
|
607 |
+
// Record it as such.
|
608 |
+
$action[ 'email_message_plain' ] = $action[ 'email_message' ];
|
609 |
+
} // Otherwise... (It's not plain text.)
|
610 |
+
else {
|
611 |
+
// Record it as HTML.
|
612 |
+
$action[ 'email_message' ] = nl2br( $action[ 'email_message' ] );
|
613 |
+
}
|
614 |
+
}
|
615 |
+
|
616 |
+
// Convert `name` to `label`
|
617 |
+
if( isset( $action[ 'name' ] ) ) {
|
618 |
+
$action['label'] = $action['name'];
|
619 |
+
unset($action['name']);
|
620 |
+
}
|
621 |
+
|
622 |
+
return apply_filters( 'ninja_forms_upgrade_action_' . $action[ 'type' ], $action );
|
623 |
+
}
|
624 |
+
|
625 |
+
public function import_field_backwards_compatibility( $field )
|
626 |
+
{
|
627 |
+
// Flatten field settings array
|
628 |
+
if( isset( $field[ 'data' ] ) && is_array( $field[ 'data' ] ) ){
|
629 |
+
$field = array_merge( $field, $field[ 'data' ] );
|
630 |
+
}
|
631 |
+
unset( $field[ 'data' ] );
|
632 |
+
|
633 |
+
// Drop form_id in favor of parent_id, which is set by the form.
|
634 |
+
if( isset( $field[ 'form_id' ] ) ){
|
635 |
+
unset( $field[ 'form_id' ] );
|
636 |
+
}
|
637 |
+
|
638 |
+
// Remove `_` prefix from type setting
|
639 |
+
$field[ 'type' ] = ltrim( $field[ 'type' ], '_' );
|
640 |
+
|
641 |
+
// Type: `text` -> `textbox`
|
642 |
+
if( 'text' == $field[ 'type' ] ){
|
643 |
+
$field[ 'type' ] = 'textbox';
|
644 |
+
}
|
645 |
+
|
646 |
+
if( 'submit' == $field[ 'type' ] ){
|
647 |
+
$field[ 'processing_label' ] = 'Processing';
|
648 |
+
}
|
649 |
+
|
650 |
+
if( isset( $field[ 'email' ] ) ){
|
651 |
+
|
652 |
+
if( 'textbox' == $field[ 'type' ] && $field[ 'email' ] ) {
|
653 |
+
$field['type'] = 'email';
|
654 |
+
}
|
655 |
+
unset( $field[ 'email' ] );
|
656 |
+
}
|
657 |
+
|
658 |
+
if( isset( $field[ 'class' ] ) ){
|
659 |
+
$field[ 'element_class' ] = $field[ 'class' ];
|
660 |
+
unset( $field[ 'class' ] );
|
661 |
+
}
|
662 |
+
|
663 |
+
if( isset( $field[ 'req' ] ) ){
|
664 |
+
$field[ 'required' ] = $field[ 'req' ];
|
665 |
+
unset( $field[ 'req' ] );
|
666 |
+
}
|
667 |
+
|
668 |
+
if( isset( $field[ 'default_value_type' ] ) ){
|
669 |
+
|
670 |
+
/* User Data */
|
671 |
+
if( '_user_id' == $field[ 'default_value_type' ] ) $field[ 'default' ] = '{wp:user_id}';
|
672 |
+
if( '_user_email' == $field[ 'default_value_type' ] ) $field[ 'default' ] = '{wp:user_email}';
|
673 |
+
if( '_user_lastname' == $field[ 'default_value_type' ] ) $field[ 'default' ] = '{wp:user_last_name}';
|
674 |
+
if( '_user_firstname' == $field[ 'default_value_type' ] ) $field[ 'default' ] = '{wp:user_first_name}';
|
675 |
+
if( '_user_display_name' == $field[ 'default_value_type' ] ) $field[ 'default' ] = '{wp:user_display_name}';
|
676 |
+
|
677 |
+
/* Post Data */
|
678 |
+
if( 'post_id' == $field[ 'default_value_type' ] ) $field[ 'default' ] = '{wp:post_id}';
|
679 |
+
if( 'post_url' == $field[ 'default_value_type' ] ) $field[ 'default' ] = '{wp:post_url}';
|
680 |
+
if( 'post_title' == $field[ 'default_value_type' ] ) $field[ 'default' ] = '{wp:post_title}';
|
681 |
+
|
682 |
+
/* System Data */
|
683 |
+
if( 'today' == $field[ 'default_value_type' ] ) $field[ 'default' ] = '{other:date}';
|
684 |
+
|
685 |
+
/* Miscellaneous */
|
686 |
+
if( '_custom' == $field[ 'default_value_type' ] && isset( $field[ 'default_value' ] ) ){
|
687 |
+
$field[ 'default' ] = $field[ 'default_value' ];
|
688 |
+
}
|
689 |
+
if( 'querystring' == $field[ 'default_value_type' ] && isset( $field[ 'default_value' ] ) ){
|
690 |
+
$field[ 'default' ] = '{querystring:' . $field[ 'default_value' ] . '}';
|
691 |
+
}
|
692 |
+
|
693 |
+
unset( $field[ 'default_value' ] );
|
694 |
+
unset( $field[ 'default_value_type' ] );
|
695 |
+
} else if ( isset ( $field[ 'default_value' ] ) ) {
|
696 |
+
$field[ 'default' ] = $field[ 'default_value' ];
|
697 |
+
}
|
698 |
+
|
699 |
+
if( 'list' == $field[ 'type' ] ) {
|
700 |
+
|
701 |
+
if ( isset( $field[ 'list_type' ] ) ) {
|
702 |
+
|
703 |
+
if ('dropdown' == $field['list_type']) {
|
704 |
+
$field['type'] = 'listselect';
|
705 |
+
}
|
706 |
+
if ('radio' == $field['list_type']) {
|
707 |
+
$field['type'] = 'listradio';
|
708 |
+
}
|
709 |
+
if ('checkbox' == $field['list_type']) {
|
710 |
+
$field['type'] = 'listcheckbox';
|
711 |
+
}
|
712 |
+
if ('multi' == $field['list_type']) {
|
713 |
+
$field['type'] = 'listmultiselect';
|
714 |
+
}
|
715 |
+
}
|
716 |
+
|
717 |
+
if( isset( $field[ 'list' ][ 'options' ] ) ) {
|
718 |
+
$field[ 'options' ] = array_values( $field[ 'list' ][ 'options' ] );
|
719 |
+
unset( $field[ 'list' ][ 'options' ] );
|
720 |
+
}
|
721 |
+
|
722 |
+
foreach( $field[ 'options' ] as &$option ){
|
723 |
+
if( isset( $option[ 'value' ] ) && $option[ 'value' ] ) continue;
|
724 |
+
$option[ 'value' ] = $option[ 'label' ];
|
725 |
+
}
|
726 |
+
}
|
727 |
+
|
728 |
+
if( 'country' == $field[ 'type' ] ){
|
729 |
+
$field[ 'type' ] = 'listcountry';
|
730 |
+
$field[ 'options' ] = array();
|
731 |
+
}
|
732 |
+
|
733 |
+
// Convert `textbox` to other field types
|
734 |
+
foreach( array( 'fist_name', 'last_name', 'user_zip', 'user_city', 'user_phone', 'user_email', 'user_address_1', 'user_address_2', 'datepicker' ) as $item ) {
|
735 |
+
if ( isset( $field[ $item ] ) && $field[ $item ] ) {
|
736 |
+
$field[ 'type' ] = str_replace( array( '_', 'user', '1', '2', 'picker' ), '', $item );
|
737 |
+
|
738 |
+
unset( $field[ $item ] );
|
739 |
+
}
|
740 |
+
}
|
741 |
+
|
742 |
+
if( 'timed_submit' == $field[ 'type' ] ) {
|
743 |
+
$field[ 'type' ] = 'submit';
|
744 |
+
}
|
745 |
+
|
746 |
+
if( 'checkbox' == $field[ 'type' ] ){
|
747 |
+
|
748 |
+
if( isset( $field[ 'calc_value' ] ) ){
|
749 |
+
|
750 |
+
if( isset( $field[ 'calc_value' ][ 'checked' ] ) ){
|
751 |
+
$field[ 'checked_calc_value' ] = $field[ 'calc_value' ][ 'checked' ];
|
752 |
+
unset( $field[ 'calc_value' ][ 'checked' ] );
|
753 |
+
}
|
754 |
+
if( isset( $field[ 'calc_value' ][ 'unchecked' ] ) ){
|
755 |
+
$field[ 'unchecked_calc_value' ] = $field[ 'calc_value' ][ 'unchecked' ];
|
756 |
+
unset( $field[ 'calc_value' ][ 'unchecked' ] );
|
757 |
+
}
|
758 |
+
}
|
759 |
+
}
|
760 |
+
|
761 |
+
if( 'rating' == $field[ 'type' ] ){
|
762 |
+
$field[ 'type' ] = 'starrating';
|
763 |
+
|
764 |
+
if( isset( $field[ 'rating_stars' ] ) ){
|
765 |
+
$field[ 'default' ] = $field[ 'rating_stars' ];
|
766 |
+
unset( $field[ 'rating_stars' ] );
|
767 |
+
}
|
768 |
+
}
|
769 |
+
|
770 |
+
if( 'number' == $field[ 'type' ] ){
|
771 |
+
|
772 |
+
if( ! isset( $field[ 'number_min' ] ) || ! $field[ 'number_min' ] ){
|
773 |
+
$field[ 'num_min' ] = '';
|
774 |
+
} else {
|
775 |
+
$field[ 'num_min' ] = $field[ 'number_min' ];
|
776 |
+
}
|
777 |
+
|
778 |
+
if( ! isset( $field[ 'number_max' ] ) || ! $field[ 'number_max' ] ){
|
779 |
+
$field[ 'num_max' ] = '';
|
780 |
+
} else {
|
781 |
+
$field[ 'num_max' ] = $field[ 'number_max' ];
|
782 |
+
}
|
783 |
+
|
784 |
+
if( ! isset( $field[ 'number_step' ] ) || ! $field[ 'number_step' ] ){
|
785 |
+
$field[ 'num_step' ] = 1;
|
786 |
+
} else {
|
787 |
+
$field[ 'num_step' ] = $field[ 'number_step' ];
|
788 |
+
}
|
789 |
+
}
|
790 |
+
|
791 |
+
if( 'profile_pass' == $field[ 'type' ] ){
|
792 |
+
$field[ 'type' ] = 'password';
|
793 |
+
|
794 |
+
$passwordconfirm = array_merge( $field, array(
|
795 |
+
'id' => '',
|
796 |
+
'type' => 'passwordconfirm',
|
797 |
+
'label' => $field[ 'label' ] . ' ' . __( 'Confirm', 'ninja-forms' ),
|
798 |
+
'confirm_field' => 'password_' . $field[ 'id' ]
|
799 |
+
));
|
800 |
+
$field[ 'new_fields' ][] = $passwordconfirm;
|
801 |
+
}
|
802 |
+
|
803 |
+
if( 'desc' == $field[ 'type' ] ){
|
804 |
+
$field[ 'type' ] = 'html';
|
805 |
+
}
|
806 |
+
|
807 |
+
if( 'credit_card' == $field[ 'type' ] ){
|
808 |
+
|
809 |
+
$field[ 'type' ] = 'creditcardnumber';
|
810 |
+
$field[ 'label' ] = $field[ 'cc_number_label' ];
|
811 |
+
$field[ 'label_pos' ] = 'above';
|
812 |
+
|
813 |
+
if( $field[ 'help_text' ] ){
|
814 |
+
$field[ 'help_text' ] = '<p>' . $field[ 'help_text' ] . '</p>';
|
815 |
+
}
|
816 |
+
|
817 |
+
$credit_card_fields = array(
|
818 |
+
'creditcardcvc' => $field[ 'cc_cvc_label' ],
|
819 |
+
'creditcardfullname' => $field[ 'cc_name_label' ],
|
820 |
+
'creditcardexpiration' => $field[ 'cc_exp_month_label' ] . ' ' . $field[ 'cc_exp_year_label' ],
|
821 |
+
'creditcardzip' => __( 'Credit Card Zip', 'ninja-forms' ),
|
822 |
+
);
|
823 |
+
|
824 |
+
|
825 |
+
foreach( $credit_card_fields as $new_type => $new_label ){
|
826 |
+
$field[ 'new_fields' ][] = array_merge( $field, array(
|
827 |
+
'id' => '',
|
828 |
+
'type' => $new_type,
|
829 |
+
'label' => $new_label,
|
830 |
+
'help_text' => '',
|
831 |
+
'desc_text' => ''
|
832 |
+
));
|
833 |
+
}
|
834 |
+
}
|
835 |
+
|
836 |
+
/*
|
837 |
+
* Convert inside label position over to placeholder
|
838 |
+
*/
|
839 |
+
if ( isset ( $field[ 'label_pos' ] ) && 'inside' == $field[ 'label_pos' ] ) {
|
840 |
+
if ( ! isset ( $field[ 'placeholder' ] ) || empty ( $field[ 'placeholder' ] ) ) {
|
841 |
+
$field[ 'placeholder' ] = $field[ 'label' ];
|
842 |
+
}
|
843 |
+
$field[ 'label_pos' ] = 'hidden';
|
844 |
+
}
|
845 |
+
|
846 |
+
if( isset( $field[ 'desc_text' ] ) ){
|
847 |
+
$field[ 'desc_text' ] = nl2br( $field[ 'desc_text' ] );
|
848 |
+
}
|
849 |
+
if( isset( $field[ 'help_text' ] ) ){
|
850 |
+
$field[ 'help_text' ] = nl2br( $field[ 'help_text' ] );
|
851 |
+
}
|
852 |
+
|
853 |
+
|
854 |
+
return apply_filters( 'ninja_forms_upgrade_field', $field );
|
855 |
+
}
|
856 |
+
}
|
includes/Admin/Processes/ImportFormTemplate.php
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class NF_Abstracts_Batch_Process
|
5 |
+
*/
|
6 |
+
class NF_Admin_Processes_ImportFormTemplate extends NF_Admin_Processes_ImportForm
|
7 |
+
{
|
8 |
+
protected $_slug = 'import_form_template';
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Function to run any setup steps necessary to begin processing.
|
12 |
+
*/
|
13 |
+
public function startup()
|
14 |
+
{
|
15 |
+
global $wpdb;
|
16 |
+
|
17 |
+
// If we haven't been passed a template as extraData, then bail.
|
18 |
+
if ( ! isset ( $_POST[ 'extraData' ][ 'template' ] ) || empty ( $_POST[ 'extraData' ][ 'template' ] ) ) {
|
19 |
+
$this->batch_complete();
|
20 |
+
}
|
21 |
+
|
22 |
+
$template_file_name = $_POST[ 'extraData' ][ 'template' ];
|
23 |
+
|
24 |
+
/**
|
25 |
+
* If our template_file_name is set to 'new', then respond with 'new' as our form id.
|
26 |
+
*
|
27 |
+
* This will redirect to the builder with a new form.
|
28 |
+
*/
|
29 |
+
if ( 'new' == $template_file_name ) {
|
30 |
+
$this->form[ 'ID' ] = 'new';
|
31 |
+
$this->batch_complete();
|
32 |
+
}
|
33 |
+
|
34 |
+
// Grab the data from the appropriate file location.
|
35 |
+
$registered_templates = Ninja_Forms::config( 'NewFormTemplates' );
|
36 |
+
|
37 |
+
if( isset( $registered_templates[ $template_file_name ] ) && ! empty( $registered_templates[ $template_file_name ][ 'form' ] ) ) {
|
38 |
+
$form_data = $registered_templates[ $template_file_name ][ 'form' ];
|
39 |
+
} else {
|
40 |
+
$form_data = Ninja_Forms::template( $template_file_name . '.nff', array(), TRUE );
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* If we don't have any form data, run cleanup.
|
45 |
+
*
|
46 |
+
* TODO: We probably need to show an error to the user here.
|
47 |
+
*/
|
48 |
+
if( ! $form_data ) {
|
49 |
+
$this->cleanup();
|
50 |
+
}
|
51 |
+
|
52 |
+
$this->form = json_decode( html_entity_decode( $form_data ), true );
|
53 |
+
|
54 |
+
// Determine how many steps this will take.
|
55 |
+
$this->response[ 'step_total' ] = $this->get_steps();
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Check to see if we've got new field columns.
|
59 |
+
*
|
60 |
+
* We do this here instead of the get_sql_queries() method so that we don't hit the db multiple times.
|
61 |
+
*/
|
62 |
+
$sql = "SHOW COLUMNS FROM {$wpdb->prefix}nf3_fields LIKE 'field_key'";
|
63 |
+
$results = $wpdb->get_results( $sql );
|
64 |
+
|
65 |
+
/**
|
66 |
+
* If we don't have the field_key column, we need to remove our new columns.
|
67 |
+
*
|
68 |
+
* Also, set our db stage 1 tracker to false.
|
69 |
+
*/
|
70 |
+
if ( empty ( $results ) ) {
|
71 |
+
unset( $this->actions_db_columns[ 'label' ] );
|
72 |
+
$db_stage_one_complete = false;
|
73 |
+
} else {
|
74 |
+
// Add a form value that stores whether or not we have our new DB columns.
|
75 |
+
$db_stage_one_complete = true;
|
76 |
+
}
|
77 |
+
|
78 |
+
$this->form[ 'db_stage_one_complete' ] = $db_stage_one_complete;
|
79 |
+
|
80 |
+
add_option( 'nf_doing_' . $this->_slug, 'true', false );
|
81 |
+
}
|
82 |
+
}
|
includes/Config/BatchProcesses.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
return apply_filters( 'ninja_forms_batch_processes', array(
|
4 |
+
'chunked_publish' => array(
|
5 |
+
'class_name' => 'NF_Admin_Processes_ChunkPublish',
|
6 |
+
),
|
7 |
+
'data_cleanup' => array(
|
8 |
+
'class_name' => 'NF_Admin_Processes_DataCleanup',
|
9 |
+
),
|
10 |
+
'expired_submission_cleanup' => array(
|
11 |
+
'class_name' => 'NF_Admin_Processes_ExpiredSubmissionCleanup',
|
12 |
+
),
|
13 |
+
'import_form' => array(
|
14 |
+
'class_name' => 'NF_Admin_Processes_ImportForm',
|
15 |
+
),
|
16 |
+
'import_form_template' => array(
|
17 |
+
'class_name' => 'NF_Admin_Processes_ImportFormTemplate',
|
18 |
+
),
|
19 |
+
));
|
includes/Config/NewFormTemplates.php
CHANGED
@@ -63,9 +63,9 @@ $templates = array(
|
|
63 |
),
|
64 |
|
65 |
'formtemplate-exportdata' => array(
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
),
|
70 |
);
|
71 |
|
63 |
),
|
64 |
|
65 |
'formtemplate-exportdata' => array(
|
66 |
+
'id' => 'formtemplate-exportdata',
|
67 |
+
'title' => __( 'Export Data Request', 'ninja-forms' ),
|
68 |
+
'template-desc' => __( 'Includes action to add users to WordPress\' personal data export tool, allowing admins to comply with the GDPR and other privacy regulations from the site\'s front end.', 'ninja-forms' ),
|
69 |
),
|
70 |
);
|
71 |
|
includes/Config/PluginSettingsAdvanced.php
CHANGED
@@ -113,4 +113,13 @@ return apply_filters( 'ninja_forms_plugin_settings_advanced', array(
|
|
113 |
'desc' => __( 'This setting maybe helpful if your WordPress installation is not moving expired submissions to the trash properly.', 'ninja-forms' ),
|
114 |
),
|
115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
));
|
113 |
'desc' => __( 'This setting maybe helpful if your WordPress installation is not moving expired submissions to the trash properly.', 'ninja-forms' ),
|
114 |
),
|
115 |
|
116 |
+
// Add a button for removing all forms from maintenance
|
117 |
+
'remove_maintenance_mode' => array(
|
118 |
+
'id' => 'remove_maintenance_mode',
|
119 |
+
'type' => 'html',
|
120 |
+
'html' => '<div id="nfRemoveMaintenanceMode" class="button">' . __( 'Remove Maintenance Mode', 'ninja-forms' ) . '</div><span id="nf_maintenanceModeProgress" style="display:none;margin-left:15px;"></span>',
|
121 |
+
'label' => __( 'Remove Maintenance Mode', 'ninja-forms' ),
|
122 |
+
'desc' => __( 'Click this button if any of your forms are still in \'Maintenance Mode\' after performing any required updates.' , 'ninja-forms' ),
|
123 |
+
),
|
124 |
+
|
125 |
));
|
includes/Config/RequiredUpdates.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
return apply_filters( 'ninja_forms_required_updates', array(
|
4 |
+
|
5 |
+
'CacheCollateActions' => array(
|
6 |
+
'class_name' => 'NF_Updates_CacheCollateActions',
|
7 |
+
'requires' => array( 'CacheCollateForms' ),
|
8 |
+
'nicename' => __( 'Update Actions Tables', 'ninja-forms' ),
|
9 |
+
),
|
10 |
+
'CacheCollateForms' => array(
|
11 |
+
'class_name' => 'NF_Updates_CacheCollateForms',
|
12 |
+
'requires' => array(),
|
13 |
+
'nicename' => __( 'Update Forms Tables', 'ninja-forms' ),
|
14 |
+
),
|
15 |
+
'CacheCollateFields' => array(
|
16 |
+
'class_name' => 'NF_Updates_CacheCollateFields',
|
17 |
+
'requires' => array( 'CacheCollateActions' ),
|
18 |
+
'nicename' => __( 'Update Fields Tables', 'ninja-forms' ),
|
19 |
+
),
|
20 |
+
'CacheCollateObjects' => array(
|
21 |
+
'class_name' => 'NF_Updates_CacheCollateObjects',
|
22 |
+
'requires' => array( 'CacheCollateFields' ),
|
23 |
+
'nicename' => __( 'Update Objects Tables', 'ninja-forms' ),
|
24 |
+
),
|
25 |
+
'CacheCollateCleanup' => array(
|
26 |
+
'class_name' => 'NF_Updates_CacheCollateCleanup',
|
27 |
+
'requires' => array( 'CacheCollateObjects' ),
|
28 |
+
'nicename' => __( 'Cleanup Orphan Records', 'ninja-forms' ),
|
29 |
+
),
|
30 |
+
|
31 |
+
));
|
includes/Database/FieldsController.php
CHANGED
@@ -8,15 +8,88 @@ final class NF_Database_FieldsController
|
|
8 |
private $insert_fields;
|
9 |
private $insert_field_meta = array();
|
10 |
private $insert_field_meta_chunk = 0;
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
private $update_field_meta = array();
|
13 |
private $update_field_meta_chunk = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
public function __construct( $form_id, $fields_data )
|
15 |
{
|
16 |
global $wpdb;
|
17 |
$this->db = $wpdb;
|
18 |
$this->form_id = $form_id;
|
19 |
$this->fields_data = $fields_data;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
}
|
21 |
public function run()
|
22 |
{
|
@@ -49,14 +122,67 @@ final class NF_Database_FieldsController
|
|
49 |
{
|
50 |
foreach( $this->fields_data as $field_data ){
|
51 |
$field_id = $field_data[ 'id' ];
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
$this->update_field( $field_id, $settings );
|
61 |
}
|
62 |
}
|
@@ -70,7 +196,7 @@ final class NF_Database_FieldsController
|
|
70 |
// we don't need object type or domain stored in the db
|
71 |
if( ! in_array( $key, array( 'objectType', 'objectDomain' ) ) ) {
|
72 |
if( isset( $existing_meta[ $field_id ][ $key ] ) ){
|
73 |
-
if( $value == $existing_meta[ $field_id ][ $key ] ) continue;
|
74 |
$this->update_field_meta( $field_id, $key, $value );
|
75 |
} else {
|
76 |
$this->insert_field_meta( $field_id, $key, $value );
|
@@ -81,8 +207,18 @@ final class NF_Database_FieldsController
|
|
81 |
}
|
82 |
private function get_existing_meta()
|
83 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
$results = $this->db->get_results("
|
85 |
-
SELECT
|
86 |
FROM `{$this->db->prefix}nf3_field_meta` AS m
|
87 |
LEFT JOIN `{$this->db->prefix}nf3_fields` AS f
|
88 |
ON m.parent_id = f.id
|
@@ -92,6 +228,12 @@ final class NF_Database_FieldsController
|
|
92 |
foreach( $results as $meta ){
|
93 |
if( ! isset( $field_meta[ $meta->parent_id ] ) ) $field_meta[ $meta->parent_id ] = array();
|
94 |
$field_meta[ $meta->parent_id ][ $meta->key ] = $meta->value;
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
}
|
96 |
return $field_meta;
|
97 |
}
|
@@ -121,20 +263,45 @@ final class NF_Database_FieldsController
|
|
121 |
*/
|
122 |
private function insert_field( $settings )
|
123 |
{
|
|
|
124 |
$this->insert_fields .= "(";
|
125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
$this->db->escape_by_ref( $value );
|
127 |
-
$
|
|
|
|
|
|
|
|
|
|
|
128 |
}
|
129 |
-
|
|
|
130 |
$this->insert_fields .= '),';
|
131 |
}
|
132 |
public function get_insert_fields_query()
|
133 |
{
|
134 |
if( ! $this->insert_fields ) return "";
|
135 |
$insert_fields = rtrim( $this->insert_fields, ',' ); // Strip trailing comma from SQl.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
return "
|
137 |
-
INSERT INTO {$this->db->prefix}nf3_fields (
|
138 |
VALUES {$insert_fields}
|
139 |
";
|
140 |
}
|
@@ -148,29 +315,50 @@ final class NF_Database_FieldsController
|
|
148 |
foreach ( $settings as $setting => $value ) {
|
149 |
$line = "WHEN `id` = '{$field_id}' ";
|
150 |
$this->db->escape_by_ref( $value );
|
151 |
-
$line .= "THEN
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
$this->update_fields[ $setting ] .= $line;
|
153 |
}
|
154 |
}
|
155 |
public function get_update_fields_query()
|
156 |
{
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
END
|
173 |
-
|
|
|
|
|
|
|
|
|
174 |
}
|
175 |
/*
|
176 |
|--------------------------------------------------------------------------
|
@@ -190,17 +378,38 @@ final class NF_Database_FieldsController
|
|
190 |
if( ! isset( $this->insert_field_meta[ $this->insert_field_meta_chunk ] ) || ! $this->insert_field_meta[ $this->insert_field_meta_chunk ] ) {
|
191 |
$this->insert_field_meta[ $this->insert_field_meta_chunk ] = '';
|
192 |
}
|
193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
$counter++;
|
195 |
if( 0 == $counter % 5000 ) $this->insert_field_meta_chunk++;
|
196 |
}
|
|
|
197 |
public function run_insert_field_meta_query()
|
198 |
{
|
199 |
if( ! $this->insert_field_meta ) return "";
|
200 |
foreach( $this->insert_field_meta as $insert_field_meta ){
|
201 |
$insert_field_meta = rtrim( $insert_field_meta, ',' ); // Strip trailing comma from SQl.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
$this->db->query( "
|
203 |
-
INSERT INTO {$this->db->prefix}nf3_field_meta (
|
204 |
VALUES {$insert_field_meta}
|
205 |
");
|
206 |
}
|
@@ -229,10 +438,17 @@ final class NF_Database_FieldsController
|
|
229 |
{
|
230 |
if( empty( $this->update_field_meta ) ) return '';
|
231 |
foreach( $this->update_field_meta as $update_field_meta ){
|
232 |
-
|
233 |
-
|
234 |
-
SET `value` = CASE {$update_field_meta} ELSE `value` END
|
235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
return;
|
237 |
}
|
238 |
}
|
8 |
private $insert_fields;
|
9 |
private $insert_field_meta = array();
|
10 |
private $insert_field_meta_chunk = 0;
|
11 |
+
/**
|
12 |
+
* An array of UPDATE SQL strings.
|
13 |
+
*
|
14 |
+
* i.e. array( 'key' => 'WHERE `id` = X THEN...' )
|
15 |
+
*
|
16 |
+
* @var array
|
17 |
+
*/
|
18 |
+
private $update_fields = array(
|
19 |
+
'id' => '',
|
20 |
+
'key' => '',
|
21 |
+
'label' => '',
|
22 |
+
'type' => '',
|
23 |
+
'field_key' => '',
|
24 |
+
'field_label' => '',
|
25 |
+
'order' => '',
|
26 |
+
'default_value' => '',
|
27 |
+
'label_pos' => '',
|
28 |
+
'required' => '',
|
29 |
+
'personally_identifiable' => '',
|
30 |
+
);
|
31 |
private $update_field_meta = array();
|
32 |
private $update_field_meta_chunk = 0;
|
33 |
+
|
34 |
+
private $db_stage_1_complete = true;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Store an array of columns that we want to store in our table rather than meta.
|
38 |
+
*
|
39 |
+
* This array stores the column name and the name of the setting that it maps to.
|
40 |
+
*
|
41 |
+
* The format is:
|
42 |
+
*
|
43 |
+
* array( 'COLUMN_NAME' => 'SETTING_NAME' )
|
44 |
+
*/
|
45 |
+
private $db_columns = array(
|
46 |
+
'parent_id' => 'parent_id',
|
47 |
+
'id' => 'id',
|
48 |
+
'key' => 'key',
|
49 |
+
'type' => 'type',
|
50 |
+
'label' => 'label',
|
51 |
+
'field_key' => 'key',
|
52 |
+
'field_label' => 'label',
|
53 |
+
'order' => 'order',
|
54 |
+
'required' => 'required',
|
55 |
+
'default_value' => 'default',
|
56 |
+
'label_pos' => 'label_pos',
|
57 |
+
'personally_identifiable' => 'personally_identifiable',
|
58 |
+
);
|
59 |
+
|
60 |
+
private $db_bit_columns = array(
|
61 |
+
'required',
|
62 |
+
'personally_identifiable',
|
63 |
+
);
|
64 |
+
|
65 |
public function __construct( $form_id, $fields_data )
|
66 |
{
|
67 |
global $wpdb;
|
68 |
$this->db = $wpdb;
|
69 |
$this->form_id = $form_id;
|
70 |
$this->fields_data = $fields_data;
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Remove new DB columns from our $db_columns list if the user hasn't completed required upgrades stage 1.
|
74 |
+
*/
|
75 |
+
$sql = "SHOW COLUMNS FROM {$this->db->prefix}nf3_fields LIKE 'field_key'";
|
76 |
+
$results = $this->db->get_results( $sql );
|
77 |
+
/**
|
78 |
+
* If we don't have the field_key column, we need to remove our new columns.
|
79 |
+
*
|
80 |
+
* Also, set our db stage 1 tracker to false.
|
81 |
+
*/
|
82 |
+
if ( empty ( $results ) ) {
|
83 |
+
unset( $this->db_columns[ 'field_key' ] );
|
84 |
+
unset( $this->db_columns[ 'field_label' ] );
|
85 |
+
unset( $this->db_columns[ 'order' ] );
|
86 |
+
unset( $this->db_columns[ 'required' ] );
|
87 |
+
unset( $this->db_columns[ 'default_value' ] );
|
88 |
+
unset( $this->db_columns[ 'label_pos' ] );
|
89 |
+
unset( $this->db_columns[ 'personally_identifiable' ] );
|
90 |
+
|
91 |
+
$this->db_stage_1_complete = false;
|
92 |
+
}
|
93 |
}
|
94 |
public function run()
|
95 |
{
|
122 |
{
|
123 |
foreach( $this->fields_data as $field_data ){
|
124 |
$field_id = $field_data[ 'id' ];
|
125 |
+
|
126 |
+
/**
|
127 |
+
* We've defined which items go into our DB, as well as which settings they map to.
|
128 |
+
*
|
129 |
+
* Loop over our $db_columns array and setup an array for $settings.
|
130 |
+
*/
|
131 |
+
$settings = array();
|
132 |
+
|
133 |
+
foreach( $this->db_columns as $column_name => $setting_name ) {
|
134 |
+
// If the setting value is numeric, make sure it's intval'd.
|
135 |
+
if ( is_numeric( $field_data[ 'settings' ][ $setting_name ] ) ) {
|
136 |
+
$value = intval( $field_data[ 'settings' ][ $setting_name ] );
|
137 |
+
} else {
|
138 |
+
$value = $field_data[ 'settings' ][ $setting_name ];
|
139 |
+
}
|
140 |
+
|
141 |
+
if ( in_array( $column_name, $this->db_bit_columns ) ) {
|
142 |
+
$value = absint( $value );
|
143 |
+
}
|
144 |
+
|
145 |
+
$settings[ $column_name ] = $value;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* We need to decide if we need to insert this field or update it in our fields table.
|
150 |
+
*
|
151 |
+
* If we don't have a numeric field id, we're dealing with a tmp field, which is a new field
|
152 |
+
*
|
153 |
+
* If this field exists in our cache, but doesn't exist in our table, we need to insert it.
|
154 |
+
*
|
155 |
+
* Otherwise, we're updating.
|
156 |
+
*
|
157 |
+
* Check our DB for a field with this id.
|
158 |
+
*/
|
159 |
+
if ( is_numeric( $field_id ) ) {
|
160 |
+
$field_in_db = $this->db->get_row( "SELECT `id` FROM `wp_nf3_fields` WHERE `id` = {$field_id}" );
|
161 |
} else {
|
162 |
+
$field_in_db = array();
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* If $field_id isn't a number, then it's a tmp-id.
|
167 |
+
*
|
168 |
+
* If we have a tmp-id OR the field hasn't been found in our DB, we need to insert it.
|
169 |
+
*/
|
170 |
+
if( ! is_numeric( $field_id ) || empty( $field_in_db ) ) {
|
171 |
+
|
172 |
+
/**
|
173 |
+
* If our $field_id is numeric, we want to insert it into the db with the row.
|
174 |
+
*
|
175 |
+
* If it's not, we want to pass NULL so that we get an autoincrement.
|
176 |
+
*/
|
177 |
+
if ( is_numeric( $field_id ) ) {
|
178 |
+
$settings[ 'id' ] = $field_id;
|
179 |
+
} else {
|
180 |
+
$settings[ 'id' ] = NULL;
|
181 |
+
}
|
182 |
+
// New Field.
|
183 |
+
$this->insert_field( $settings );
|
184 |
+
} else {
|
185 |
+
// We're updating field settings.
|
186 |
$this->update_field( $field_id, $settings );
|
187 |
}
|
188 |
}
|
196 |
// we don't need object type or domain stored in the db
|
197 |
if( ! in_array( $key, array( 'objectType', 'objectDomain' ) ) ) {
|
198 |
if( isset( $existing_meta[ $field_id ][ $key ] ) ){
|
199 |
+
if( $value == $existing_meta[ $field_id ][ $key ] && $value == $existing_meta[ $field_id ][ 'meta_key' ][ $key ] ) continue;
|
200 |
$this->update_field_meta( $field_id, $key, $value );
|
201 |
} else {
|
202 |
$this->insert_field_meta( $field_id, $key, $value );
|
207 |
}
|
208 |
private function get_existing_meta()
|
209 |
{
|
210 |
+
|
211 |
+
$sql_select = "m.parent_id, m.key, m.value";
|
212 |
+
|
213 |
+
/**
|
214 |
+
* If we have completed stage 1 of our db migration, pull meta_key and meta_value as well as key and value.
|
215 |
+
*/
|
216 |
+
if ( $this->db_stage_1_complete ) {
|
217 |
+
$sql_select .= " , m.meta_key, m.meta_value";
|
218 |
+
}
|
219 |
+
|
220 |
$results = $this->db->get_results("
|
221 |
+
SELECT {$sql_select}
|
222 |
FROM `{$this->db->prefix}nf3_field_meta` AS m
|
223 |
LEFT JOIN `{$this->db->prefix}nf3_fields` AS f
|
224 |
ON m.parent_id = f.id
|
228 |
foreach( $results as $meta ){
|
229 |
if( ! isset( $field_meta[ $meta->parent_id ] ) ) $field_meta[ $meta->parent_id ] = array();
|
230 |
$field_meta[ $meta->parent_id ][ $meta->key ] = $meta->value;
|
231 |
+
if ( is_null( $meta->meta_value ) ) {
|
232 |
+
$meta_value = '';
|
233 |
+
} else {
|
234 |
+
$meta_value = $meta->meta_value;
|
235 |
+
}
|
236 |
+
$field_meta[ $meta->parent_id ]['meta_key'][ $meta->key ] = $meta_value;
|
237 |
}
|
238 |
return $field_meta;
|
239 |
}
|
263 |
*/
|
264 |
private function insert_field( $settings )
|
265 |
{
|
266 |
+
// Add our initial opening parenthesis.
|
267 |
$this->insert_fields .= "(";
|
268 |
+
// Add our form id to our settings as 'parent_id'.
|
269 |
+
$settings[ 'parent_id' ] = $this->form_id;
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Loop over each of our $this->db_columns to create a value list for our SQL statement.
|
273 |
+
*/
|
274 |
+
foreach ( $this->db_columns as $column_name => $setting_name ) {
|
275 |
+
$value = $settings[ $column_name ];
|
276 |
$this->db->escape_by_ref( $value );
|
277 |
+
if ( is_numeric( $value ) ) {
|
278 |
+
$this->insert_fields .= "{$value},";
|
279 |
+
} else {
|
280 |
+
$this->insert_fields .= "'{$value}',";
|
281 |
+
}
|
282 |
+
|
283 |
}
|
284 |
+
// Remove any trailing commas from our SQL string.
|
285 |
+
$this->insert_fields = rtrim( $this->insert_fields, ',' );
|
286 |
$this->insert_fields .= '),';
|
287 |
}
|
288 |
public function get_insert_fields_query()
|
289 |
{
|
290 |
if( ! $this->insert_fields ) return "";
|
291 |
$insert_fields = rtrim( $this->insert_fields, ',' ); // Strip trailing comma from SQl.
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Loop over each of our $this->db_columns to create a column list for our SQL statement below.
|
295 |
+
*/
|
296 |
+
$columns = '';
|
297 |
+
foreach( $this->db_columns as $column_name => $setting_name ) {
|
298 |
+
$columns .= "`{$column_name}` ,";
|
299 |
+
}
|
300 |
+
|
301 |
+
$columns = rtrim( $columns, ',' );
|
302 |
+
|
303 |
return "
|
304 |
+
INSERT INTO {$this->db->prefix}nf3_fields ( {$columns} )
|
305 |
VALUES {$insert_fields}
|
306 |
";
|
307 |
}
|
315 |
foreach ( $settings as $setting => $value ) {
|
316 |
$line = "WHEN `id` = '{$field_id}' ";
|
317 |
$this->db->escape_by_ref( $value );
|
318 |
+
$line .= "THEN ";
|
319 |
+
if ( is_numeric( $value ) ) {
|
320 |
+
$line .= "{$value} ";
|
321 |
+
} else {
|
322 |
+
$line .= "'{$value}' ";
|
323 |
+
}
|
324 |
+
|
325 |
$this->update_fields[ $setting ] .= $line;
|
326 |
}
|
327 |
}
|
328 |
public function get_update_fields_query()
|
329 |
{
|
330 |
+
/**
|
331 |
+
* Loop over our $db_columns class var and make sure that none of them are empty.
|
332 |
+
*
|
333 |
+
* If they are empty, return an empty string to prevent errors.
|
334 |
+
*/
|
335 |
+
|
336 |
+
foreach ( $this->db_columns as $column_name => $setting_name ) {
|
337 |
+
if ( empty( $this->update_fields[ $column_name ] ) ) {
|
338 |
+
return "";
|
339 |
+
}
|
340 |
+
}
|
341 |
+
|
342 |
+
/**
|
343 |
+
* Build our return statement based upon our $db_columns class var.
|
344 |
+
*/
|
345 |
+
|
346 |
+
$return = "UPDATE {$this->db->prefix}nf3_fields
|
347 |
+
SET ";
|
348 |
+
|
349 |
+
foreach( $this->db_columns as $column_name => $setting_name ) {
|
350 |
+
// We don't need to update our parent_id or our id.
|
351 |
+
if ( 'id' == $column_name || 'parent_id' == $column_name ) {
|
352 |
+
continue;
|
353 |
+
}
|
354 |
+
$return .= "`{$column_name}` = CASE {$this->update_fields[ $column_name ]}
|
355 |
+
ELSE `{$column_name}`
|
356 |
END
|
357 |
+
,";
|
358 |
+
}
|
359 |
+
|
360 |
+
$return = rtrim( $return, ',' );
|
361 |
+
return $return;
|
362 |
}
|
363 |
/*
|
364 |
|--------------------------------------------------------------------------
|
378 |
if( ! isset( $this->insert_field_meta[ $this->insert_field_meta_chunk ] ) || ! $this->insert_field_meta[ $this->insert_field_meta_chunk ] ) {
|
379 |
$this->insert_field_meta[ $this->insert_field_meta_chunk ] = '';
|
380 |
}
|
381 |
+
|
382 |
+
$insert_values = "'{$field_id}','{$key}','{$value}'";
|
383 |
+
|
384 |
+
/**
|
385 |
+
* If we have completed stage 1 of our db update process, then we want to add meta_key and meta_value as well as key and value.
|
386 |
+
*/
|
387 |
+
if ( $this->db_stage_1_complete ) {
|
388 |
+
$insert_values .= ", '{$key}','{$value}'";
|
389 |
+
}
|
390 |
+
|
391 |
+
$this->insert_field_meta[ $this->insert_field_meta_chunk ] .= "( {$insert_values} ),";
|
392 |
+
|
393 |
$counter++;
|
394 |
if( 0 == $counter % 5000 ) $this->insert_field_meta_chunk++;
|
395 |
}
|
396 |
+
|
397 |
public function run_insert_field_meta_query()
|
398 |
{
|
399 |
if( ! $this->insert_field_meta ) return "";
|
400 |
foreach( $this->insert_field_meta as $insert_field_meta ){
|
401 |
$insert_field_meta = rtrim( $insert_field_meta, ',' ); // Strip trailing comma from SQl.
|
402 |
+
|
403 |
+
/**
|
404 |
+
* If we have completed stage 1 of our db update process, then we want to insert meta_key and meta_value as well.
|
405 |
+
*/
|
406 |
+
$insert_columns = '`parent_id`, `key`, `value`';
|
407 |
+
if ( $this->db_stage_1_complete ) {
|
408 |
+
$insert_columns .= ', `meta_key`, `meta_value`';
|
409 |
+
}
|
410 |
+
|
411 |
$this->db->query( "
|
412 |
+
INSERT INTO {$this->db->prefix}nf3_field_meta ( {$insert_columns} )
|
413 |
VALUES {$insert_field_meta}
|
414 |
");
|
415 |
}
|
438 |
{
|
439 |
if( empty( $this->update_field_meta ) ) return '';
|
440 |
foreach( $this->update_field_meta as $update_field_meta ){
|
441 |
+
|
442 |
+
$sql = "UPDATE {$this->db->prefix}nf3_field_meta as field_meta
|
443 |
+
SET `value` = CASE {$update_field_meta} ELSE `value` END";
|
444 |
+
/**
|
445 |
+
* If we have completed stage 1 of our db update process, then we want to update meta_value as well as value.
|
446 |
+
*/
|
447 |
+
if ( $this->db_stage_1_complete ) {
|
448 |
+
$sql .= ", `meta_value` = CASE {$update_field_meta} ELSE `meta_value` END, `meta_key` = CASE WHEN `parent_id` = '-999' THEN NULL ELSE `key` END";
|
449 |
+
}
|
450 |
+
|
451 |
+
$this->db->query( $sql );
|
452 |
return;
|
453 |
}
|
454 |
}
|
includes/Database/Migrations.php
CHANGED
@@ -4,6 +4,14 @@ class NF_Database_Migrations
|
|
4 |
{
|
5 |
protected $migrations = array();
|
6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
public function __construct()
|
8 |
{
|
9 |
$this->migrations[ 'forms' ] = new NF_Database_Migrations_Forms();
|
@@ -20,29 +28,40 @@ class NF_Database_Migrations
|
|
20 |
$this->migrations[ 'chunks' ] = new NF_Database_Migrations_Chunks();
|
21 |
}
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
public function migrate()
|
24 |
{
|
25 |
foreach( $this->migrations as $migration ){
|
26 |
$migration->_run();
|
27 |
}
|
28 |
}
|
29 |
-
|
|
|
30 |
/**
|
31 |
-
* Function to run
|
|
|
|
|
|
|
|
|
32 |
*/
|
33 |
-
public function
|
34 |
{
|
35 |
foreach( $this->migrations as $migration ) {
|
36 |
-
$migration->
|
37 |
}
|
38 |
}
|
39 |
|
40 |
/**
|
41 |
* This function drops ninja forms tables and options
|
42 |
*
|
43 |
-
* @param $areYouSure
|
44 |
-
* @param $areYouReallySure
|
45 |
-
* @param $nuke_multisite
|
46 |
*
|
47 |
* @since 2.9.34
|
48 |
* @updated 3.3.16
|
@@ -72,6 +91,12 @@ class NF_Database_Migrations
|
|
72 |
}
|
73 |
}
|
74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
private function _nuke()
|
76 |
{
|
77 |
global $wpdb;
|
@@ -87,6 +112,15 @@ class NF_Database_Migrations
|
|
87 |
$wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE `option_name` LIKE '_transient_timeout_nf_form_%'" );
|
88 |
}
|
89 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
public function nuke_settings( $areYouSure = FALSE, $areYouReallySure = FALSE )
|
91 |
{
|
92 |
if( ! $areYouSure || ! $areYouReallySure ) return;
|
@@ -107,6 +141,12 @@ class NF_Database_Migrations
|
|
107 |
}
|
108 |
}
|
109 |
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
private function _nuke_settings()
|
111 |
{
|
112 |
global $wpdb;
|
@@ -134,7 +174,16 @@ class NF_Database_Migrations
|
|
134 |
$wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE `option_name` LIKE 'wp_nf_update_fields_%'" );
|
135 |
}
|
136 |
|
137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
{
|
139 |
if( ! $areYouSure || ! $areYouReallySure ) return;
|
140 |
|
@@ -154,6 +203,12 @@ class NF_Database_Migrations
|
|
154 |
}
|
155 |
}
|
156 |
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
private function _nuke_deprecated()
|
158 |
{
|
159 |
global $wpdb;
|
4 |
{
|
5 |
protected $migrations = array();
|
6 |
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Constructor method for the NF_Database_Migrations class.
|
10 |
+
*
|
11 |
+
* @since 3.0.0
|
12 |
+
*
|
13 |
+
* @updated 3.3.8
|
14 |
+
*/
|
15 |
public function __construct()
|
16 |
{
|
17 |
$this->migrations[ 'forms' ] = new NF_Database_Migrations_Forms();
|
28 |
$this->migrations[ 'chunks' ] = new NF_Database_Migrations_Chunks();
|
29 |
}
|
30 |
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Function to run each migration on the stack.
|
34 |
+
*
|
35 |
+
* @since 3.0.0
|
36 |
+
*/
|
37 |
public function migrate()
|
38 |
{
|
39 |
foreach( $this->migrations as $migration ){
|
40 |
$migration->_run();
|
41 |
}
|
42 |
}
|
43 |
+
|
44 |
+
|
45 |
/**
|
46 |
+
* Function to run any required database upgrades.
|
47 |
+
*
|
48 |
+
* @param $callback (String) The method this upgrade will call from individual migration files.
|
49 |
+
*
|
50 |
+
* @since 3.4.0
|
51 |
*/
|
52 |
+
public function do_upgrade( $callback )
|
53 |
{
|
54 |
foreach( $this->migrations as $migration ) {
|
55 |
+
$migration->_do_upgrade( $callback );
|
56 |
}
|
57 |
}
|
58 |
|
59 |
/**
|
60 |
* This function drops ninja forms tables and options
|
61 |
*
|
62 |
+
* @param $areYouSure (Boolean)
|
63 |
+
* @param $areYouReallySure (Boolean)
|
64 |
+
* @param $nuke_multisite (Boolean)
|
65 |
*
|
66 |
* @since 2.9.34
|
67 |
* @updated 3.3.16
|
91 |
}
|
92 |
}
|
93 |
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Function to handle the actual deletion of tables and caches.
|
97 |
+
*
|
98 |
+
* @since 3.1.0
|
99 |
+
*/
|
100 |
private function _nuke()
|
101 |
{
|
102 |
global $wpdb;
|
112 |
$wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE `option_name` LIKE '_transient_timeout_nf_form_%'" );
|
113 |
}
|
114 |
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Function to nuke our 3.0 settings.
|
118 |
+
*
|
119 |
+
* @param $areYouSure (Boolean)
|
120 |
+
* @param $areYouReallySure (Boolean)
|
121 |
+
*
|
122 |
+
* @since 3.1.0
|
123 |
+
*/
|
124 |
public function nuke_settings( $areYouSure = FALSE, $areYouReallySure = FALSE )
|
125 |
{
|
126 |
if( ! $areYouSure || ! $areYouReallySure ) return;
|
141 |
}
|
142 |
}
|
143 |
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Function to handle the actual deletion of our 3.0 settings.
|
147 |
+
*
|
148 |
+
* @since 3.1.0
|
149 |
+
*/
|
150 |
private function _nuke_settings()
|
151 |
{
|
152 |
global $wpdb;
|
174 |
$wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE `option_name` LIKE 'wp_nf_update_fields_%'" );
|
175 |
}
|
176 |
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Function to nuke our 2.9 database tables.
|
180 |
+
*
|
181 |
+
* @param $areYouSure (Boolean)
|
182 |
+
* @param $areYouReallySure (Boolean)
|
183 |
+
*
|
184 |
+
* @since 3.1.0
|
185 |
+
*/
|
186 |
+
public function nuke_deprecated( $areYouSure = FALSE, $areYouReallySure = FALSE )
|
187 |
{
|
188 |
if( ! $areYouSure || ! $areYouReallySure ) return;
|
189 |
|
203 |
}
|
204 |
}
|
205 |
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Function to handle the actual deletion of deprecated tables and options.
|
209 |
+
*
|
210 |
+
* @since 3.1.0
|
211 |
+
*/
|
212 |
private function _nuke_deprecated()
|
213 |
{
|
214 |
global $wpdb;
|
includes/Database/Migrations/ActionMeta.php
CHANGED
@@ -2,6 +2,12 @@
|
|
2 |
|
3 |
class NF_Database_Migrations_ActionMeta extends NF_Abstracts_Migration
|
4 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
public function __construct()
|
6 |
{
|
7 |
parent::__construct(
|
@@ -10,6 +16,14 @@ class NF_Database_Migrations_ActionMeta extends NF_Abstracts_Migration
|
|
10 |
);
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function run()
|
14 |
{
|
15 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
@@ -17,10 +31,34 @@ class NF_Database_Migrations_ActionMeta extends NF_Abstracts_Migration
|
|
17 |
`parent_id` int NOT NULL,
|
18 |
`key` longtext NOT NULL,
|
19 |
`value` longtext,
|
|
|
|
|
20 |
UNIQUE KEY (`id`)
|
21 |
-
) {$this->charset_collate()};";
|
22 |
|
23 |
dbDelta( $query );
|
24 |
}
|
25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
}
|
2 |
|
3 |
class NF_Database_Migrations_ActionMeta extends NF_Abstracts_Migration
|
4 |
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Constructor method for the NF_Database_Migrations_ActionMeta class.
|
8 |
+
*
|
9 |
+
* @since 3.0.0
|
10 |
+
*/
|
11 |
public function __construct()
|
12 |
{
|
13 |
parent::__construct(
|
16 |
);
|
17 |
}
|
18 |
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Function to run our initial migration.
|
22 |
+
*
|
23 |
+
* @since 3.0.0
|
24 |
+
*
|
25 |
+
* @updated 3.4.0
|
26 |
+
*/
|
27 |
public function run()
|
28 |
{
|
29 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
31 |
`parent_id` int NOT NULL,
|
32 |
`key` longtext NOT NULL,
|
33 |
`value` longtext,
|
34 |
+
`meta_key` longtext,
|
35 |
+
`meta_value` longtext,
|
36 |
UNIQUE KEY (`id`)
|
37 |
+
) {$this->charset_collate( true )};";
|
38 |
|
39 |
dbDelta( $query );
|
40 |
}
|
41 |
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Function to be run as part of our CacheCollateActions required update.
|
45 |
+
*
|
46 |
+
* @since 3.3.12
|
47 |
+
*
|
48 |
+
* @updated 3.4.0
|
49 |
+
*/
|
50 |
+
public function cache_collate_actions()
|
51 |
+
{
|
52 |
+
// If the meta_key column has not already been defined...
|
53 |
+
if ( ! $this->column_exists( 'meta_key' ) ) {
|
54 |
+
global $wpdb;
|
55 |
+
// Modify our table.
|
56 |
+
$query = "ALTER TABLE {$this->table_name()}
|
57 |
+
ADD `meta_key` longtext {$this->charset_collate()},
|
58 |
+
ADD `meta_value` longtext {$this->charset_collate()};";
|
59 |
+
|
60 |
+
$wpdb->query( $query );
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
}
|
includes/Database/Migrations/Actions.php
CHANGED
@@ -2,6 +2,12 @@
|
|
2 |
|
3 |
class NF_Database_Migrations_Actions extends NF_Abstracts_Migration
|
4 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
public function __construct()
|
6 |
{
|
7 |
parent::__construct(
|
@@ -10,6 +16,14 @@ class NF_Database_Migrations_Actions extends NF_Abstracts_Migration
|
|
10 |
);
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function run()
|
14 |
{
|
15 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
@@ -21,10 +35,33 @@ class NF_Database_Migrations_Actions extends NF_Abstracts_Migration
|
|
21 |
`parent_id` int NOT NULL,
|
22 |
`created_at` TIMESTAMP,
|
23 |
`updated_at` DATETIME,
|
|
|
24 |
UNIQUE KEY (`id`)
|
25 |
-
) {$this->charset_collate()};";
|
26 |
|
27 |
dbDelta( $query );
|
28 |
}
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
}
|
2 |
|
3 |
class NF_Database_Migrations_Actions extends NF_Abstracts_Migration
|
4 |
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Constructor method for the NF_Database_Migrations_Actions class.
|
8 |
+
*
|
9 |
+
* @since 3.0.0
|
10 |
+
*/
|
11 |
public function __construct()
|
12 |
{
|
13 |
parent::__construct(
|
16 |
);
|
17 |
}
|
18 |
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Function to run our initial migration.
|
22 |
+
*
|
23 |
+
* @since 3.0.0
|
24 |
+
*
|
25 |
+
* @updated 3.4.0
|
26 |
+
*/
|
27 |
public function run()
|
28 |
{
|
29 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
35 |
`parent_id` int NOT NULL,
|
36 |
`created_at` TIMESTAMP,
|
37 |
`updated_at` DATETIME,
|
38 |
+
`label` longtext,
|
39 |
UNIQUE KEY (`id`)
|
40 |
+
) {$this->charset_collate( true )};";
|
41 |
|
42 |
dbDelta( $query );
|
43 |
}
|
44 |
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Function to be run as part of our CacheCollateActions required update.
|
48 |
+
*
|
49 |
+
* @since 3.3.12
|
50 |
+
*
|
51 |
+
* @updated 3.4.0
|
52 |
+
*/
|
53 |
+
public function cache_collate_actions()
|
54 |
+
{
|
55 |
+
// If the label column has not already been defined...
|
56 |
+
if ( ! $this->column_exists( 'label' ) ) {
|
57 |
+
global $wpdb;
|
58 |
+
// Modify our table.
|
59 |
+
$query = "ALTER TABLE {$this->table_name()}
|
60 |
+
ADD `label` longtext {$this->charset_collate()},
|
61 |
+
MODIFY `type` longtext {$this->charset_collate()};";
|
62 |
+
|
63 |
+
$wpdb->query( $query );
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
}
|
includes/Database/Migrations/Chunks.php
CHANGED
@@ -25,7 +25,7 @@ class NF_Database_Migrations_Chunks extends NF_Abstracts_Migration
|
|
25 |
`name` varchar(200),
|
26 |
`value` longtext,
|
27 |
UNIQUE KEY (`id`)
|
28 |
-
) {$this->charset_collate()};";
|
29 |
|
30 |
dbDelta( $query );
|
31 |
}
|
25 |
`name` varchar(200),
|
26 |
`value` longtext,
|
27 |
UNIQUE KEY (`id`)
|
28 |
+
) {$this->charset_collate( true )};";
|
29 |
|
30 |
dbDelta( $query );
|
31 |
}
|
includes/Database/Migrations/FieldMeta.php
CHANGED
@@ -2,6 +2,12 @@
|
|
2 |
|
3 |
class NF_Database_Migrations_FieldMeta extends NF_Abstracts_Migration
|
4 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
public function __construct()
|
6 |
{
|
7 |
parent::__construct(
|
@@ -10,6 +16,13 @@ class NF_Database_Migrations_FieldMeta extends NF_Abstracts_Migration
|
|
10 |
);
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function run()
|
14 |
{
|
15 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
@@ -17,10 +30,32 @@ class NF_Database_Migrations_FieldMeta extends NF_Abstracts_Migration
|
|
17 |
`parent_id` int NOT NULL,
|
18 |
`key` longtext NOT NULL,
|
19 |
`value` longtext,
|
20 |
-
|
21 |
-
|
|
|
|
|
22 |
|
23 |
dbDelta( $query );
|
24 |
}
|
25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
}
|
2 |
|
3 |
class NF_Database_Migrations_FieldMeta extends NF_Abstracts_Migration
|
4 |
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Constructor method for the NF_Database_Migrations_FieldMeta class.
|
8 |
+
*
|
9 |
+
* @since 3.0.0
|
10 |
+
*/
|
11 |
public function __construct()
|
12 |
{
|
13 |
parent::__construct(
|
16 |
);
|
17 |
}
|
18 |
|
19 |
+
/**
|
20 |
+
* Function to run our initial migration.
|
21 |
+
*
|
22 |
+
* @since 3.0.0
|
23 |
+
*
|
24 |
+
* @updated 3.4.0
|
25 |
+
*/
|
26 |
public function run()
|
27 |
{
|
28 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
30 |
`parent_id` int NOT NULL,
|
31 |
`key` longtext NOT NULL,
|
32 |
`value` longtext,
|
33 |
+
`meta_key` longtext,
|
34 |
+
`meta_value` longtext,
|
35 |
+
UNIQUE KEY (`id`)
|
36 |
+
) {$this->charset_collate( true )};";
|
37 |
|
38 |
dbDelta( $query );
|
39 |
}
|
40 |
|
41 |
+
/**
|
42 |
+
* Function to run our stage three upgrades.
|
43 |
+
*
|
44 |
+
* @since 3.3.12
|
45 |
+
*
|
46 |
+
* @updated 3.4.0
|
47 |
+
*/
|
48 |
+
public function cache_collate_fields()
|
49 |
+
{
|
50 |
+
// If the meta_key column has not already been defined...
|
51 |
+
if ( ! $this->column_exists( 'meta_key' ) ) {
|
52 |
+
global $wpdb;
|
53 |
+
// Modify our table.
|
54 |
+
$query = "ALTER TABLE {$this->table_name()}
|
55 |
+
ADD `meta_key` longtext {$this->charset_collate()},
|
56 |
+
ADD `meta_value` longtext {$this->charset_collate()}";
|
57 |
+
$wpdb->query( $query );
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
}
|
includes/Database/Migrations/Fields.php
CHANGED
@@ -2,6 +2,12 @@
|
|
2 |
|
3 |
class NF_Database_Migrations_Fields extends NF_Abstracts_Migration
|
4 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
public function __construct()
|
6 |
{
|
7 |
parent::__construct(
|
@@ -10,6 +16,13 @@ class NF_Database_Migrations_Fields extends NF_Abstracts_Migration
|
|
10 |
);
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function run()
|
14 |
{
|
15 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
@@ -20,10 +33,43 @@ class NF_Database_Migrations_Fields extends NF_Abstracts_Migration
|
|
20 |
`parent_id` int NOT NULL,
|
21 |
`created_at` TIMESTAMP,
|
22 |
`updated_at` DATETIME,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
UNIQUE KEY (`id`)
|
24 |
-
) {$this->charset_collate()};";
|
25 |
|
26 |
dbDelta( $query );
|
27 |
}
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
}
|
2 |
|
3 |
class NF_Database_Migrations_Fields extends NF_Abstracts_Migration
|
4 |
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Constructor method for the NF_Database_Migrations_Fields class.
|
8 |
+
*
|
9 |
+
* @since 3.0.0
|
10 |
+
*/
|
11 |
public function __construct()
|
12 |
{
|
13 |
parent::__construct(
|
16 |
);
|
17 |
}
|
18 |
|
19 |
+
/**
|
20 |
+
* Function to run our initial migration.
|
21 |
+
*
|
22 |
+
* @since 3.0.0
|
23 |
+
*
|
24 |
+
* @updated 3.4.0
|
25 |
+
*/
|
26 |
public function run()
|
27 |
{
|
28 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
33 |
`parent_id` int NOT NULL,
|
34 |
`created_at` TIMESTAMP,
|
35 |
`updated_at` DATETIME,
|
36 |
+
`field_label` longtext,
|
37 |
+
`field_key` longtext,
|
38 |
+
`order` int(11),
|
39 |
+
`required` bit,
|
40 |
+
`default_value` longtext,
|
41 |
+
`label_pos` varchar(15),
|
42 |
+
`personally_identifiable` bit,
|
43 |
UNIQUE KEY (`id`)
|
44 |
+
) {$this->charset_collate( true )};";
|
45 |
|
46 |
dbDelta( $query );
|
47 |
}
|
48 |
|
49 |
+
/**
|
50 |
+
* Function to run our stage two upgrades.
|
51 |
+
*
|
52 |
+
* @since 3.3.12
|
53 |
+
*
|
54 |
+
* @updated 3.4.0
|
55 |
+
*/
|
56 |
+
public function cache_collate_fields()
|
57 |
+
{
|
58 |
+
// If the field_label column has not already been defined...
|
59 |
+
if ( ! $this->column_exists( 'field_label' ) ) {
|
60 |
+
global $wpdb;
|
61 |
+
// Modify our table.
|
62 |
+
$query = "ALTER TABLE {$this->table_name()}
|
63 |
+
ADD `field_label` longtext {$this->charset_collate()},
|
64 |
+
ADD `field_key` longtext {$this->charset_collate()},
|
65 |
+
ADD `order` int(11),
|
66 |
+
ADD `required` bit,
|
67 |
+
ADD `default_value` longtext {$this->charset_collate()},
|
68 |
+
ADD `label_pos` varchar(15) {$this->charset_collate()},
|
69 |
+
ADD `personally_identifiable` bit,
|
70 |
+
MODIFY `type` longtext {$this->charset_collate()};";
|
71 |
+
$wpdb->query( $query );
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
}
|
includes/Database/Migrations/FormMeta.php
CHANGED
@@ -2,6 +2,12 @@
|
|
2 |
|
3 |
class NF_Database_Migrations_FormMeta extends NF_Abstracts_Migration
|
4 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
public function __construct()
|
6 |
{
|
7 |
parent::__construct(
|
@@ -10,6 +16,14 @@ class NF_Database_Migrations_FormMeta extends NF_Abstracts_Migration
|
|
10 |
);
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function run()
|
14 |
{
|
15 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
@@ -20,20 +34,33 @@ class NF_Database_Migrations_FormMeta extends NF_Abstracts_Migration
|
|
20 |
`meta_key` longtext,
|
21 |
`meta_value` longtext,
|
22 |
UNIQUE KEY (`id`)
|
23 |
-
) {$this->charset_collate()};";
|
24 |
|
25 |
dbDelta( $query );
|
26 |
}
|
27 |
-
|
28 |
/**
|
29 |
-
* Function to run our
|
|
|
|
|
30 |
*/
|
31 |
-
public function
|
32 |
{
|
33 |
-
$query = "ALTER TABLE {$this->table_name()}
|
34 |
-
ADD `meta_key` longtext {$this->collate()},
|
35 |
-
ADD `meta_value` longtext {$this->collate()}";
|
36 |
global $wpdb;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
$wpdb->query( $query );
|
38 |
}
|
39 |
|
2 |
|
3 |
class NF_Database_Migrations_FormMeta extends NF_Abstracts_Migration
|
4 |
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Constructor method for the NF_Database_Migrations_Actions class.
|
8 |
+
*
|
9 |
+
* @since 3.0.0
|
10 |
+
*/
|
11 |
public function __construct()
|
12 |
{
|
13 |
parent::__construct(
|
16 |
);
|
17 |
}
|
18 |
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Function to run our initial migration.
|
22 |
+
*
|
23 |
+
* @since 3.0.0
|
24 |
+
*
|
25 |
+
* @updated 3.4.0
|
26 |
+
*/
|
27 |
public function run()
|
28 |
{
|
29 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
34 |
`meta_key` longtext,
|
35 |
`meta_value` longtext,
|
36 |
UNIQUE KEY (`id`)
|
37 |
+
) {$this->charset_collate( true )};";
|
38 |
|
39 |
dbDelta( $query );
|
40 |
}
|
41 |
+
|
42 |
/**
|
43 |
+
* Function to be run as part of our CacheCollateForms required update.
|
44 |
+
*
|
45 |
+
* @since 3.4.0
|
46 |
*/
|
47 |
+
public function cache_collate_forms()
|
48 |
{
|
|
|
|
|
|
|
49 |
global $wpdb;
|
50 |
+
|
51 |
+
// If the meta_key column exists...
|
52 |
+
if ( $this->column_exists( 'meta_key' ) ) {
|
53 |
+
// Update our existing columns.
|
54 |
+
$query = "ALTER TABLE {$this->table_name()}
|
55 |
+
MODIFY `meta_key` longtext {$this->charset_collate()},
|
56 |
+
MODIFY `meta_value` longtext {$this->charset_collate()};";
|
57 |
+
} // Otherwise... (The meta_key column does not exist.)
|
58 |
+
else {
|
59 |
+
// Create the new columns.
|
60 |
+
$query = "ALTER TABLE {$this->table_name()}
|
61 |
+
ADD `meta_key` longtext {$this->charset_collate()},
|
62 |
+
ADD `meta_value` longtext {$this->charset_collate()};";
|
63 |
+
}
|
64 |
$wpdb->query( $query );
|
65 |
}
|
66 |
|
includes/Database/Migrations/Forms.php
CHANGED
@@ -2,6 +2,12 @@
|
|
2 |
|
3 |
class NF_Database_Migrations_Forms extends NF_Abstracts_Migration
|
4 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
public function __construct()
|
6 |
{
|
7 |
parent::__construct(
|
@@ -10,16 +16,24 @@ class NF_Database_Migrations_Forms extends NF_Abstracts_Migration
|
|
10 |
);
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function run()
|
14 |
{
|
15 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
16 |
`id` int NOT NULL AUTO_INCREMENT,
|
17 |
`title` longtext,
|
18 |
-
|
19 |
`created_at` TIMESTAMP,
|
20 |
`updated_at` DATETIME,
|
21 |
-
|
22 |
-
|
23 |
`form_title` longtext,
|
24 |
`default_label_pos` varchar(15),
|
25 |
`show_title` bit,
|
@@ -28,33 +42,38 @@ class NF_Database_Migrations_Forms extends NF_Abstracts_Migration
|
|
28 |
`logged_in` bit,
|
29 |
`seq_num` int,
|
30 |
UNIQUE KEY (`id`)
|
31 |
-
) {$this->charset_collate()};";
|
32 |
|
33 |
dbDelta( $query );
|
34 |
}
|
35 |
-
|
36 |
/**
|
37 |
-
* Function to run our
|
|
|
|
|
38 |
*/
|
39 |
-
public function
|
40 |
{
|
41 |
-
/**
|
42 |
-
* TODO:
|
43 |
-
*
|
44 |
-
DROP `key`,
|
45 |
-
DROP `views`,
|
46 |
-
DROP `subs`,
|
47 |
-
*
|
48 |
-
*/
|
49 |
-
$query = "ALTER TABLE {$this->table_name()}
|
50 |
-
ADD `form_title` longtext {$this->collate()},
|
51 |
-
ADD `default_label_pos` varchar(15) {$this->collate()},
|
52 |
-
ADD `show_title` bit,
|
53 |
-
ADD `clear_complete` bit,
|
54 |
-
ADD `hide_complete` bit,
|
55 |
-
ADD `logged_in` bit,
|
56 |
-
ADD `seq_num` int";
|
57 |
global $wpdb;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
$wpdb->query( $query );
|
59 |
}
|
60 |
|
2 |
|
3 |
class NF_Database_Migrations_Forms extends NF_Abstracts_Migration
|
4 |
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Constructor method for the NF_Database_Migrations_Actions class.
|
8 |
+
*
|
9 |
+
* @since 3.0.0
|
10 |
+
*/
|
11 |
public function __construct()
|
12 |
{
|
13 |
parent::__construct(
|
16 |
);
|
17 |
}
|
18 |
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Function to run our initial migration.
|
22 |
+
*
|
23 |
+
* @since 3.0.0
|
24 |
+
*
|
25 |
+
* @updated 3.4.0
|
26 |
+
*/
|
27 |
public function run()
|
28 |
{
|
29 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
30 |
`id` int NOT NULL AUTO_INCREMENT,
|
31 |
`title` longtext,
|
32 |
+
`key` longtext,
|
33 |
`created_at` TIMESTAMP,
|
34 |
`updated_at` DATETIME,
|
35 |
+
`views` int(11),
|
36 |
+
`subs` int(11),
|
37 |
`form_title` longtext,
|
38 |
`default_label_pos` varchar(15),
|
39 |
`show_title` bit,
|
42 |
`logged_in` bit,
|
43 |
`seq_num` int,
|
44 |
UNIQUE KEY (`id`)
|
45 |
+
) {$this->charset_collate( true )};";
|
46 |
|
47 |
dbDelta( $query );
|
48 |
}
|
49 |
+
|
50 |
/**
|
51 |
+
* Function to be run as part of our CacheCollateForms required update.
|
52 |
+
*
|
53 |
+
* @since 3.4.0
|
54 |
*/
|
55 |
+
public function cache_collate_forms()
|
56 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
global $wpdb;
|
58 |
+
|
59 |
+
// If the form_title column exists...
|
60 |
+
if ( $this->column_exists( 'form_title' ) ) {
|
61 |
+
// Update our existing columns.
|
62 |
+
$query = "ALTER TABLE {$this->table_name()}
|
63 |
+
MODIFY `form_title` longtext {$this->charset_collate()},
|
64 |
+
MODIFY `default_label_pos` varchar(15) {$this->charset_collate()};";
|
65 |
+
} // Otherwise... (The form_title column does not exist.)
|
66 |
+
else {
|
67 |
+
// Create the new columns.
|
68 |
+
$query = "ALTER TABLE {$this->table_name()}
|
69 |
+
ADD `form_title` longtext {$this->charset_collate()},
|
70 |
+
ADD `default_label_pos` varchar(15) {$this->charset_collate()},
|
71 |
+
ADD `show_title` bit,
|
72 |
+
ADD `clear_complete` bit,
|
73 |
+
ADD `hide_complete` bit,
|
74 |
+
ADD `logged_in` bit,
|
75 |
+
ADD `seq_num` int;";
|
76 |
+
}
|
77 |
$wpdb->query( $query );
|
78 |
}
|
79 |
|
includes/Database/Migrations/ObjectMeta.php
CHANGED
@@ -2,6 +2,11 @@
|
|
2 |
|
3 |
class NF_Database_Migrations_ObjectMeta extends NF_Abstracts_Migration
|
4 |
{
|
|
|
|
|
|
|
|
|
|
|
5 |
public function __construct()
|
6 |
{
|
7 |
parent::__construct(
|
@@ -10,6 +15,13 @@ class NF_Database_Migrations_ObjectMeta extends NF_Abstracts_Migration
|
|
10 |
);
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function run()
|
14 |
{
|
15 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
@@ -17,10 +29,30 @@ class NF_Database_Migrations_ObjectMeta extends NF_Abstracts_Migration
|
|
17 |
`parent_id` int NOT NULL,
|
18 |
`key` longtext NOT NULL,
|
19 |
`value` longtext,
|
|
|
|
|
20 |
UNIQUE KEY (`id`)
|
21 |
-
) {$this->charset_collate()};";
|
22 |
|
23 |
dbDelta( $query );
|
24 |
}
|
25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
}
|
2 |
|
3 |
class NF_Database_Migrations_ObjectMeta extends NF_Abstracts_Migration
|
4 |
{
|
5 |
+
/**
|
6 |
+
* Constructor method for the NF_Database_Migrations_ObjectMeta class.
|
7 |
+
*
|
8 |
+
* @since 3.0.0
|
9 |
+
*/
|
10 |
public function __construct()
|
11 |
{
|
12 |
parent::__construct(
|
15 |
);
|
16 |
}
|
17 |
|
18 |
+
/**
|
19 |
+
* Function to run our initial migration.
|
20 |
+
*
|
21 |
+
* @since 3.0.0
|
22 |
+
*
|
23 |
+
* @updated 3.4.0
|
24 |
+
*/
|
25 |
public function run()
|
26 |
{
|
27 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
29 |
`parent_id` int NOT NULL,
|
30 |
`key` longtext NOT NULL,
|
31 |
`value` longtext,
|
32 |
+
`meta_key` longtext,
|
33 |
+
`meta_value` longtext,
|
34 |
UNIQUE KEY (`id`)
|
35 |
+
) {$this->charset_collate( true )};";
|
36 |
|
37 |
dbDelta( $query );
|
38 |
}
|
39 |
|
40 |
+
/**
|
41 |
+
* Function to ensure proper collation of the object_meta table.
|
42 |
+
*
|
43 |
+
* @since 3.4.0
|
44 |
+
*/
|
45 |
+
public function cache_collate_objects()
|
46 |
+
{
|
47 |
+
// If the meta_key column has not already been defined...
|
48 |
+
if ( ! $this->column_exists( 'meta_key' ) ) {
|
49 |
+
global $wpdb;
|
50 |
+
// Modify our table.
|
51 |
+
$query = "ALTER TABLE {$this->table_name()}
|
52 |
+
ADD `meta_key` longtext {$this->charset_collate()},
|
53 |
+
ADD `meta_value` longtext {$this->charset_collate()};";
|
54 |
+
$wpdb->query( $query );
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
}
|
includes/Database/Migrations/Objects.php
CHANGED
@@ -2,6 +2,11 @@
|
|
2 |
|
3 |
class NF_Database_Migrations_Objects extends NF_Abstracts_Migration
|
4 |
{
|
|
|
|
|
|
|
|
|
|
|
5 |
public function __construct()
|
6 |
{
|
7 |
parent::__construct(
|
@@ -10,6 +15,13 @@ class NF_Database_Migrations_Objects extends NF_Abstracts_Migration
|
|
10 |
);
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function run()
|
14 |
{
|
15 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
@@ -18,10 +30,29 @@ class NF_Database_Migrations_Objects extends NF_Abstracts_Migration
|
|
18 |
`title` longtext,
|
19 |
`created_at` TIMESTAMP,
|
20 |
`updated_at` DATETIME,
|
|
|
21 |
UNIQUE KEY (`id`)
|
22 |
-
) {$this->charset_collate()};";
|
23 |
|
24 |
dbDelta( $query );
|
25 |
}
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
}
|
2 |
|
3 |
class NF_Database_Migrations_Objects extends NF_Abstracts_Migration
|
4 |
{
|
5 |
+
/**
|
6 |
+
* Constructor method for the NF_Database_Migrations_Objects class.
|
7 |
+
*
|
8 |
+
* @since 3.0.0
|
9 |
+
*/
|
10 |
public function __construct()
|
11 |
{
|
12 |
parent::__construct(
|
15 |
);
|
16 |
}
|
17 |
|
18 |
+
/**
|
19 |
+
* Function to run our initial migration.
|
20 |
+
*
|
21 |
+
* @since 3.0.0
|
22 |
+
*
|
23 |
+
* @updated 3.4.0
|
24 |
+
*/
|
25 |
public function run()
|
26 |
{
|
27 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
30 |
`title` longtext,
|
31 |
`created_at` TIMESTAMP,
|
32 |
`updated_at` DATETIME,
|
33 |
+
`object_title` longtext,
|
34 |
UNIQUE KEY (`id`)
|
35 |
+
) {$this->charset_collate( true )};";
|
36 |
|
37 |
dbDelta( $query );
|
38 |
}
|
39 |
|
40 |
+
/**
|
41 |
+
* Function to ensure proper collation of the objects table.
|
42 |
+
*
|
43 |
+
* @since 3.4.0
|
44 |
+
*/
|
45 |
+
public function cache_collate_objects()
|
46 |
+
{
|
47 |
+
// If the object_title column has not already been defined...
|
48 |
+
if ( ! $this->column_exists( 'object_title' ) ) {
|
49 |
+
global $wpdb;
|
50 |
+
// Modify our table.
|
51 |
+
$query = "ALTER TABLE {$this->table_name()}
|
52 |
+
ADD `object_title` longtext {$this->charset_collate()},
|
53 |
+
MODIFY `type` longtext {$this->charset_collate()};";
|
54 |
+
$wpdb->query( $query );
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
}
|
includes/Database/Migrations/Relationships.php
CHANGED
@@ -2,6 +2,11 @@
|
|
2 |
|
3 |
class NF_Database_Migrations_Relationships extends NF_Abstracts_Migration
|
4 |
{
|
|
|
|
|
|
|
|
|
|
|
5 |
public function __construct()
|
6 |
{
|
7 |
parent::__construct(
|
@@ -10,6 +15,11 @@ class NF_Database_Migrations_Relationships extends NF_Abstracts_Migration
|
|
10 |
);
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
13 |
public function run()
|
14 |
{
|
15 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
@@ -21,9 +31,24 @@ class NF_Database_Migrations_Relationships extends NF_Abstracts_Migration
|
|
21 |
`created_at` TIMESTAMP,
|
22 |
`updated_at` DATETIME,
|
23 |
UNIQUE KEY (`id`)
|
24 |
-
) {$this->charset_collate()};";
|
25 |
|
26 |
dbDelta( $query );
|
27 |
}
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
}
|
2 |
|
3 |
class NF_Database_Migrations_Relationships extends NF_Abstracts_Migration
|
4 |
{
|
5 |
+
/**
|
6 |
+
* Constructor method for the NF_Database_Migrations_Relationships class.
|
7 |
+
*
|
8 |
+
* @since 3.0.0
|
9 |
+
*/
|
10 |
public function __construct()
|
11 |
{
|
12 |
parent::__construct(
|
15 |
);
|
16 |
}
|
17 |
|
18 |
+
/**
|
19 |
+
* Function to run our initial migration.
|
20 |
+
*
|
21 |
+
* @since 3.0.0
|
22 |
+
*/
|
23 |
public function run()
|
24 |
{
|
25 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
31 |
`created_at` TIMESTAMP,
|
32 |
`updated_at` DATETIME,
|
33 |
UNIQUE KEY (`id`)
|
34 |
+
) {$this->charset_collate( true )};";
|
35 |
|
36 |
dbDelta( $query );
|
37 |
}
|
38 |
|
39 |
+
/**
|
40 |
+
* Function to ensure proper collation of the relationships table.
|
41 |
+
*
|
42 |
+
* @since 3.4.0
|
43 |
+
*/
|
44 |
+
public function cache_collate_objects()
|
45 |
+
{
|
46 |
+
global $wpdb;
|
47 |
+
// Modify our table.
|
48 |
+
$query = "ALTER TABLE {$this->table_name()}
|
49 |
+
MODIFY `child_type` longtext {$this->charset_collate()} NOT NULL,
|
50 |
+
MODIFY `parent_type` longtext {$this->charset_collate()} NOT NULL;";
|
51 |
+
$wpdb->query( $query );
|
52 |
+
}
|
53 |
+
|
54 |
}
|
includes/Database/Migrations/Upgrades.php
CHANGED
@@ -2,6 +2,12 @@
|
|
2 |
|
3 |
class NF_Database_Migrations_Upgrades extends NF_Abstracts_Migration
|
4 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
public function __construct()
|
6 |
{
|
7 |
parent::__construct(
|
@@ -10,16 +16,41 @@ class NF_Database_Migrations_Upgrades extends NF_Abstracts_Migration
|
|
10 |
);
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function run()
|
14 |
{
|
15 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
16 |
`id` INT(11) NOT NULL,
|
17 |
`cache` LONGTEXT,
|
18 |
`stage` INT(11) NOT NULL DEFAULT 0,
|
|
|
19 |
PRIMARY KEY ( id )
|
20 |
-
) {$this->charset_collate()};";
|
21 |
|
22 |
dbDelta( $query );
|
23 |
}
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
2 |
|
3 |
class NF_Database_Migrations_Upgrades extends NF_Abstracts_Migration
|
4 |
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Constructor method for the NF_Database_Migrations_Fields class.
|
8 |
+
*
|
9 |
+
* @since 3.3.11
|
10 |
+
*/
|
11 |
public function __construct()
|
12 |
{
|
13 |
parent::__construct(
|
16 |
);
|
17 |
}
|
18 |
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Function to run our initial migration.
|
22 |
+
*
|
23 |
+
* @since 3.3.11
|
24 |
+
*
|
25 |
+
* @updated 3.4.0
|
26 |
+
*/
|
27 |
public function run()
|
28 |
{
|
29 |
$query = "CREATE TABLE IF NOT EXISTS {$this->table_name()} (
|
30 |
`id` INT(11) NOT NULL,
|
31 |
`cache` LONGTEXT,
|
32 |
`stage` INT(11) NOT NULL DEFAULT 0,
|
33 |
+
`maintenance` bit DEFAULT 0,
|
34 |
PRIMARY KEY ( id )
|
35 |
+
) {$this->charset_collate( true )};";
|
36 |
|
37 |
dbDelta( $query );
|
38 |
}
|
39 |
|
40 |
+
/**
|
41 |
+
* Function to define our maintenance column.
|
42 |
+
*
|
43 |
+
* @since 3.4.0
|
44 |
+
*/
|
45 |
+
public function cache_collate_fields()
|
46 |
+
{
|
47 |
+
// If the maintenance column has not already been defined...
|
48 |
+
if ( ! $this->column_exists( 'maintenance' ) ) {
|
49 |
+
global $wpdb;
|
50 |
+
// Modify our table.
|
51 |
+
$query = "ALTER TABLE {$this->table_name()}
|
52 |
+
ADD `maintenance` bit DEFAULT 0;";
|
53 |
+
$wpdb->query( $query );
|
54 |
+
}
|
55 |
+
}
|
56 |
}
|
includes/Database/Models/Action.php
CHANGED
@@ -18,12 +18,32 @@ final class NF_Database_Models_Action extends NF_Abstracts_Model
|
|
18 |
'key',
|
19 |
'type',
|
20 |
'active',
|
21 |
-
'created_at'
|
|
|
22 |
);
|
23 |
|
24 |
public function __construct( $db, $id, $parent_id = '' )
|
25 |
{
|
26 |
parent::__construct( $db, $id, $parent_id );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
}
|
28 |
|
29 |
} // End NF_Database_Models_Action
|
18 |
'key',
|
19 |
'type',
|
20 |
'active',
|
21 |
+
'created_at',
|
22 |
+
'label'
|
23 |
);
|
24 |
|
25 |
public function __construct( $db, $id, $parent_id = '' )
|
26 |
{
|
27 |
parent::__construct( $db, $id, $parent_id );
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Remove new DB columns from our $_columns list if the user hasn't completed required upgrades stage 1.
|
31 |
+
*/
|
32 |
+
$sql = "SHOW COLUMNS FROM {$db->prefix}nf3_actions LIKE 'label'";
|
33 |
+
$results = $db->get_results( $sql );
|
34 |
+
/**
|
35 |
+
* If we don't have the label column, we need to remove our new columns.
|
36 |
+
*
|
37 |
+
* Also, set our db stage 1 tracker to false.
|
38 |
+
*/
|
39 |
+
if ( empty ( $results ) ) {
|
40 |
+
foreach( $this->_columns as $i => $col ) {
|
41 |
+
if( 'label' === $col ) {
|
42 |
+
unset( $this->_columns[ $i ] );
|
43 |
+
}
|
44 |
+
}
|
45 |
+
$this->db_stage_1_complete = false;
|
46 |
+
}
|
47 |
}
|
48 |
|
49 |
} // End NF_Database_Models_Action
|
includes/Database/Models/Form.php
CHANGED
@@ -226,10 +226,43 @@ final class NF_Database_Models_Form extends NF_Abstracts_Model
|
|
226 |
Ninja_Forms()->template( 'admin-notice-form-import.html.php', array( 'form_id'=> self::$imported_form_id ) );
|
227 |
}
|
228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
public static function duplicate( $form_id )
|
230 |
{
|
231 |
global $wpdb;
|
232 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
// Duplicate the Form Object.
|
234 |
$wpdb->query( $wpdb->prepare(
|
235 |
"
|
@@ -261,22 +294,28 @@ final class NF_Database_Models_Form extends NF_Abstracts_Model
|
|
261 |
", $form_id
|
262 |
));
|
263 |
|
|
|
|
|
|
|
|
|
264 |
foreach( $old_fields as $old_field ){
|
|
|
265 |
// Duplicate the Field Object.
|
266 |
$wpdb->query( $wpdb->prepare(
|
267 |
"
|
268 |
-
INSERT INTO {$wpdb->prefix}nf3_fields (
|
269 |
-
SELECT
|
270 |
FROM {$wpdb->prefix}nf3_fields
|
271 |
WHERE id = %d
|
272 |
", $new_form_id, $old_field->id
|
273 |
));
|
274 |
$new_field_id = $wpdb->insert_id;
|
|
|
275 |
// Duplicate the Field Meta.
|
276 |
$wpdb->query( $wpdb->prepare(
|
277 |
"
|
278 |
-
INSERT INTO {$wpdb->prefix}nf3_field_meta (
|
279 |
-
SELECT
|
280 |
FROM {$wpdb->prefix}nf3_field_meta
|
281 |
WHERE parent_id = %d;
|
282 |
", $new_field_id, $old_field->id
|
@@ -294,12 +333,16 @@ final class NF_Database_Models_Form extends NF_Abstracts_Model
|
|
294 |
", $form_id
|
295 |
));
|
296 |
|
|
|
|
|
|
|
|
|
297 |
foreach( $old_actions as $old_action ){
|
298 |
// Duplicate the Action Object.
|
299 |
$wpdb->query( $wpdb->prepare(
|
300 |
"
|
301 |
-
INSERT INTO {$wpdb->prefix}nf3_actions (
|
302 |
-
SELECT
|
303 |
FROM {$wpdb->prefix}nf3_actions
|
304 |
WHERE id = %d
|
305 |
", $new_form_id, $old_action->id
|
@@ -308,8 +351,8 @@ final class NF_Database_Models_Form extends NF_Abstracts_Model
|
|
308 |
// Duplicate the Action Meta.
|
309 |
$wpdb->query( $wpdb->prepare(
|
310 |
"
|
311 |
-
INSERT INTO {$wpdb->prefix}nf3_action_meta (
|
312 |
-
SELECT
|
313 |
FROM {$wpdb->prefix}nf3_action_meta
|
314 |
WHERE parent_id = %d;
|
315 |
", $new_action_id, $old_action->id
|
@@ -324,9 +367,130 @@ final class NF_Database_Models_Form extends NF_Abstracts_Model
|
|
324 |
$new_form->update_settings( $new_form->get_settings() );
|
325 |
$new_form->save();
|
326 |
|
|
|
|
|
|
|
|
|
|
|
327 |
return $new_form_id;
|
328 |
}
|
329 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
330 |
public static function export( $form_id, $return = FALSE )
|
331 |
{
|
332 |
//TODO: Set Date Format from Plugin Settings
|
226 |
Ninja_Forms()->template( 'admin-notice-form-import.html.php', array( 'form_id'=> self::$imported_form_id ) );
|
227 |
}
|
228 |
|
229 |
+
/**
|
230 |
+
* This static method is called to duplicate a form using the form ID.
|
231 |
+
*
|
232 |
+
* To duplicate a form we:
|
233 |
+
*
|
234 |
+
* Check to see if we've ran stage one of the db update process.
|
235 |
+
* Use SQL to insert a copy of our form and form meta.
|
236 |
+
* Grab all fields for a specific form.
|
237 |
+
* Loop over those fields and insert fields and field meta.
|
238 |
+
* Run ->update_settings() and ->save() on the form model.
|
239 |
+
* Call our WPN_Helper method to build a form cache.
|
240 |
+
*
|
241 |
+
* @since 3.0
|
242 |
+
* @update 3.4.0
|
243 |
+
* @param int $form_id ID of the form being duplicated.
|
244 |
+
* @return $new_form_id ID of our form duplicate.
|
245 |
+
*/
|
246 |
public static function duplicate( $form_id )
|
247 |
{
|
248 |
global $wpdb;
|
249 |
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Check to see if we've got new field columns.
|
253 |
+
*
|
254 |
+
* We do this here instead of the get_sql_queries() method so that we don't hit the db multiple times.
|
255 |
+
*/
|
256 |
+
$sql = "SHOW COLUMNS FROM {$wpdb->prefix}nf3_fields LIKE 'field_key'";
|
257 |
+
$results = $wpdb->get_results( $sql );
|
258 |
+
|
259 |
+
// If we don't have the field_key column, we need to remove our new columns.
|
260 |
+
if ( empty ( $results ) ) {
|
261 |
+
$db_stage_one_complete = false;
|
262 |
+
} else {
|
263 |
+
$db_stage_one_complete = true;
|
264 |
+
}
|
265 |
+
|
266 |
// Duplicate the Form Object.
|
267 |
$wpdb->query( $wpdb->prepare(
|
268 |
"
|
294 |
", $form_id
|
295 |
));
|
296 |
|
297 |
+
// Get our field and field_meta table column names and values.
|
298 |
+
$fields_sql = self::get_sql_queries( 'field_table_columns' );
|
299 |
+
$field_meta_sql = self::get_sql_queries( 'field_meta_table_columns' );
|
300 |
+
|
301 |
foreach( $old_fields as $old_field ){
|
302 |
+
|
303 |
// Duplicate the Field Object.
|
304 |
$wpdb->query( $wpdb->prepare(
|
305 |
"
|
306 |
+
INSERT INTO {$wpdb->prefix}nf3_fields ( {$fields_sql[ 'insert' ]} )
|
307 |
+
SELECT {$fields_sql[ 'select' ]}
|
308 |
FROM {$wpdb->prefix}nf3_fields
|
309 |
WHERE id = %d
|
310 |
", $new_form_id, $old_field->id
|
311 |
));
|
312 |
$new_field_id = $wpdb->insert_id;
|
313 |
+
|
314 |
// Duplicate the Field Meta.
|
315 |
$wpdb->query( $wpdb->prepare(
|
316 |
"
|
317 |
+
INSERT INTO {$wpdb->prefix}nf3_field_meta ( {$field_meta_sql[ 'insert' ]} )
|
318 |
+
SELECT {$field_meta_sql[ 'select' ]}
|
319 |
FROM {$wpdb->prefix}nf3_field_meta
|
320 |
WHERE parent_id = %d;
|
321 |
", $new_field_id, $old_field->id
|
333 |
", $form_id
|
334 |
));
|
335 |
|
336 |
+
// Get our action and action_meta table columns and values.
|
337 |
+
$actions_sql = self::get_sql_queries( 'action_table_columns' );
|
338 |
+
$actions_meta_sql = self::get_sql_queries( 'action_meta_table_columns' );
|
339 |
+
|
340 |
foreach( $old_actions as $old_action ){
|
341 |
// Duplicate the Action Object.
|
342 |
$wpdb->query( $wpdb->prepare(
|
343 |
"
|
344 |
+
INSERT INTO {$wpdb->prefix}nf3_actions ( {$actions_sql[ 'insert' ]} )
|
345 |
+
SELECT {$actions_sql[ 'select' ]}
|
346 |
FROM {$wpdb->prefix}nf3_actions
|
347 |
WHERE id = %d
|
348 |
", $new_form_id, $old_action->id
|
351 |
// Duplicate the Action Meta.
|
352 |
$wpdb->query( $wpdb->prepare(
|
353 |
"
|
354 |
+
INSERT INTO {$wpdb->prefix}nf3_action_meta ( {$actions_meta_sql[ 'insert' ]} )
|
355 |
+
SELECT {$actions_meta_sql[ 'select' ]}
|
356 |
FROM {$wpdb->prefix}nf3_action_meta
|
357 |
WHERE parent_id = %d;
|
358 |
", $new_action_id, $old_action->id
|
367 |
$new_form->update_settings( $new_form->get_settings() );
|
368 |
$new_form->save();
|
369 |
|
370 |
+
/*
|
371 |
+
* Build a cache for this new form.
|
372 |
+
*/
|
373 |
+
WPN_Helper::build_nf_cache( $new_form_id );
|
374 |
+
|
375 |
return $new_form_id;
|
376 |
}
|
377 |
|
378 |
+
/**
|
379 |
+
* When duplicating a form, we need to build specific SQL queries.
|
380 |
+
*
|
381 |
+
* This is a fairly repetative task, so we've extrapolated the code to its own function.
|
382 |
+
*
|
383 |
+
* @since 3.4.0
|
384 |
+
* @param string $table_name Name of the table we want to update.
|
385 |
+
* @return array Associative array like: ['insert' => "`column1`, "`column2`", etc", 'select' => "`column1`, etc."]
|
386 |
+
*/
|
387 |
+
private function get_sql_queries( $table_name, $db_stage_one_complete = true )
|
388 |
+
{
|
389 |
+
/**
|
390 |
+
* These arrays contain the columns in our database.
|
391 |
+
*
|
392 |
+
* Later, if the user hasn't ran stage one of our db update process, we'll remove the items that aren't supported.
|
393 |
+
*/
|
394 |
+
$db_columns = array(
|
395 |
+
'field_table_columns' => array(
|
396 |
+
'label',
|
397 |
+
'key',
|
398 |
+
'type',
|
399 |
+
'parent_id',
|
400 |
+
'field_label',
|
401 |
+
'field_key',
|
402 |
+
'order',
|
403 |
+
'required',
|
404 |
+
'default_value',
|
405 |
+
'label_pos',
|
406 |
+
'personally_identifiable',
|
407 |
+
),
|
408 |
+
|
409 |
+
'field_meta_table_columns' => array(
|
410 |
+
'parent_id',
|
411 |
+
'key',
|
412 |
+
'value',
|
413 |
+
'meta_key',
|
414 |
+
'meta_value',
|
415 |
+
),
|
416 |
+
|
417 |
+
'action_table_columns' => array(
|
418 |
+
'title',
|
419 |
+
'key',
|
420 |
+
'type',
|
421 |
+
'active',
|
422 |
+
'parent_id',
|
423 |
+
'label',
|
424 |
+
),
|
425 |
+
|
426 |
+
'action_meta_table_columns' => array(
|
427 |
+
'parent_id',
|
428 |
+
'key',
|
429 |
+
'value',
|
430 |
+
'meta_key',
|
431 |
+
'meta_value',
|
432 |
+
),
|
433 |
+
);
|
434 |
+
|
435 |
+
// If we haven't been passed a table name or the table name is invalid, return false.
|
436 |
+
if ( empty( $table_name ) || ! isset( $db_columns[ $table_name ] ) ) return false;
|
437 |
+
|
438 |
+
// If we have not completed stage one of our db update, then we unset new db columns.
|
439 |
+
if ( ! $db_stage_one_complete ) {
|
440 |
+
unset(
|
441 |
+
$field_table_columns[ 'field_label' ],
|
442 |
+
$field_table_columns[ 'field_key' ],
|
443 |
+
$field_table_columns[ 'order' ],
|
444 |
+
$field_table_columns[ 'required' ],
|
445 |
+
$field_table_columns[ 'default_value' ],
|
446 |
+
$field_table_columns[ 'label_pos' ],
|
447 |
+
$field_table_columns[ 'personally_identifiable' ]
|
448 |
+
);
|
449 |
+
|
450 |
+
unset(
|
451 |
+
$field_meta_table_columns[ 'meta_key' ],
|
452 |
+
$field_meta_table_columns[ 'meta_value' ]
|
453 |
+
);
|
454 |
+
|
455 |
+
unset(
|
456 |
+
$action_table_columns[ 'label' ]
|
457 |
+
);
|
458 |
+
|
459 |
+
unset(
|
460 |
+
$action_meta_table_columns[ 'meta_key' ],
|
461 |
+
$action_meta_table_columns[ 'meta_value' ]
|
462 |
+
);
|
463 |
+
}
|
464 |
+
|
465 |
+
/**
|
466 |
+
* $sql_insert is a var that tracks which table columns we want to insert.
|
467 |
+
*/
|
468 |
+
$sql_insert = "";
|
469 |
+
/**
|
470 |
+
* $sql_select is a var that tracks the values for each field table column.
|
471 |
+
*/
|
472 |
+
$sql_select = "";
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Loop over our table column names and add them to our $sql_insert var.
|
476 |
+
*/
|
477 |
+
foreach( $db_columns[ $table_name ] as $column_name ) {
|
478 |
+
$sql_insert .= "`{$column_name}`,";
|
479 |
+
|
480 |
+
if ( 'parent_id' == $column_name ) {
|
481 |
+
$sql_select .= "%d,";
|
482 |
+
} else {
|
483 |
+
$sql_select .= "`{$column_name}`,";
|
484 |
+
}
|
485 |
+
}
|
486 |
+
|
487 |
+
// Remove any trailing commas.
|
488 |
+
$sql_insert = rtrim( $sql_insert, ',' );
|
489 |
+
$sql_select = rtrim( $sql_select, ',' );
|
490 |
+
|
491 |
+
return array( 'insert' => $sql_insert, 'select' => $sql_select );
|
492 |
+
}
|
493 |
+
|
494 |
public static function export( $form_id, $return = FALSE )
|
495 |
{
|
496 |
//TODO: Set Date Format from Plugin Settings
|
includes/Database/Models/Object.php
CHANGED
@@ -13,7 +13,8 @@ final class NF_Database_Models_Object extends NF_Abstracts_Model
|
|
13 |
|
14 |
protected $_columns = array(
|
15 |
'type',
|
16 |
-
'created_at'
|
|
|
17 |
);
|
18 |
|
19 |
public function __construct( $db, $id, $parent_id = '', $parent_type = '' )
|
@@ -21,6 +22,25 @@ final class NF_Database_Models_Object extends NF_Abstracts_Model
|
|
21 |
parent::__construct( $db, $id, $parent_id );
|
22 |
|
23 |
$this->_parent_type = $parent_type;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
}
|
25 |
|
26 |
public function save()
|
13 |
|
14 |
protected $_columns = array(
|
15 |
'type',
|
16 |
+
'created_at',
|
17 |
+
'object_title'
|
18 |
);
|
19 |
|
20 |
public function __construct( $db, $id, $parent_id = '', $parent_type = '' )
|
22 |
parent::__construct( $db, $id, $parent_id );
|
23 |
|
24 |
$this->_parent_type = $parent_type;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Remove new DB columns from our $_columns list if the user hasn't completed required upgrades stage 1.
|
28 |
+
*/
|
29 |
+
$sql = "SHOW COLUMNS FROM {$db->prefix}nf3_objects LIKE 'object_title'";
|
30 |
+
$results = $db->get_results( $sql );
|
31 |
+
/**
|
32 |
+
* If we don't have the object_title column, we need to remove our new columns.
|
33 |
+
*
|
34 |
+
* Also, set our db stage 1 tracker to false.
|
35 |
+
*/
|
36 |
+
if ( empty ( $results ) ) {
|
37 |
+
foreach( $this->_columns as $i => $col ) {
|
38 |
+
if( 'object_title' === $col ) {
|
39 |
+
unset( $this->_columns[ $i ] );
|
40 |
+
}
|
41 |
+
}
|
42 |
+
$this->db_stage_1_complete = false;
|
43 |
+
}
|
44 |
}
|
45 |
|
46 |
public function save()
|
includes/Display/Render.php
CHANGED
@@ -108,6 +108,20 @@ final class NF_Display_Render
|
|
108 |
}
|
109 |
}
|
110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
if( ! apply_filters( 'ninja_forms_display_show_form', true, $form_id, $form ) ) return;
|
112 |
|
113 |
$currency = $form->get_setting( 'currency', Ninja_Forms()->get_setting( 'currency' ) );
|
108 |
}
|
109 |
}
|
110 |
|
111 |
+
// Get our maintenance value out of the DB.
|
112 |
+
$maintenance = WPN_Helper::form_in_maintenance( $form_id );
|
113 |
+
|
114 |
+
// If maintenance isn't empty and the bool is set to 1 then..
|
115 |
+
if( true == $maintenance ) {
|
116 |
+
// Set a filterable maintenance message and echo it out.
|
117 |
+
$maintenance_msg = apply_filters( 'nf_maintenance_message', __( 'This form is currently undergoing maintenance. Please try again later.', 'ninja-forms' ) );
|
118 |
+
echo $maintenance_msg;
|
119 |
+
|
120 |
+
// bail.
|
121 |
+
return false;
|
122 |
+
}
|
123 |
+
|
124 |
+
|
125 |
if( ! apply_filters( 'ninja_forms_display_show_form', true, $form_id, $form ) ) return;
|
126 |
|
127 |
$currency = $form->get_setting( 'currency', Ninja_Forms()->get_setting( 'currency' ) );
|
includes/Helper.php
CHANGED
@@ -291,12 +291,13 @@ final class WPN_Helper
|
|
291 |
*
|
292 |
* @param $id (int) The form ID.
|
293 |
* @param $data (string) The form cache.
|
|
|
294 |
*
|
295 |
* @since 3.3.7
|
|
|
296 |
*/
|
297 |
-
public static function update_nf_cache( $id, $data ) {
|
298 |
-
|
299 |
-
$CURRENT_STAGE = 1;
|
300 |
// Serialize our data.
|
301 |
$cache = serialize( $data );
|
302 |
global $wpdb;
|
@@ -306,14 +307,69 @@ final class WPN_Helper
|
|
306 |
// If we don't already have the data...
|
307 |
if ( empty( $result ) ) {
|
308 |
// Insert it.
|
309 |
-
|
310 |
} // Otherwise... (We do have the data.)
|
311 |
else {
|
312 |
// Update the existing record.
|
313 |
-
|
314 |
}
|
315 |
$wpdb->query( $sql );
|
316 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
317 |
|
318 |
/**
|
319 |
* Function to delete our cache.
|
@@ -336,4 +392,96 @@ final class WPN_Helper
|
|
336 |
}
|
337 |
}
|
338 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
} // End Class WPN_Helper
|
291 |
*
|
292 |
* @param $id (int) The form ID.
|
293 |
* @param $data (string) The form cache.
|
294 |
+
* @param $stage (int) The target stage of this update. Default to the current max stage.
|
295 |
*
|
296 |
* @since 3.3.7
|
297 |
+
* @updated 3.4.0
|
298 |
*/
|
299 |
+
public static function update_nf_cache( $id, $data, $stage = 0 ) {
|
300 |
+
$stage = ( $stage ) ? $stage : WPN_Helper::get_stage();
|
|
|
301 |
// Serialize our data.
|
302 |
$cache = serialize( $data );
|
303 |
global $wpdb;
|
307 |
// If we don't already have the data...
|
308 |
if ( empty( $result ) ) {
|
309 |
// Insert it.
|
310 |
+
$sql = $wpdb->prepare( "INSERT INTO `{$wpdb->prefix}nf3_upgrades` (id, cache, stage) VALUES (%d, %s, %s)", intval( $id ), $cache, intval( $stage ) );
|
311 |
} // Otherwise... (We do have the data.)
|
312 |
else {
|
313 |
// Update the existing record.
|
314 |
+
$sql = $wpdb->prepare( "UPDATE `{$wpdb->prefix}nf3_upgrades` SET cache = %s, stage = %d WHERE id = %d", $cache, intval( $stage ), intval( $id ) );
|
315 |
}
|
316 |
$wpdb->query( $sql );
|
317 |
}
|
318 |
+
|
319 |
+
/**
|
320 |
+
* Function to retrieve our upgrade stage.
|
321 |
+
* Remove this after the cache has been resolved.
|
322 |
+
*
|
323 |
+
* @return int
|
324 |
+
*
|
325 |
+
* @since 3.4.0
|
326 |
+
*/
|
327 |
+
public static function get_stage() {
|
328 |
+
$ver = Ninja_Forms::$db_version;
|
329 |
+
$stack = explode( '.', $ver );
|
330 |
+
return intval( array_pop( $stack ) );
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Function to build our form cache from the table.
|
335 |
+
*
|
336 |
+
* @param $id (int) The form ID.
|
337 |
+
* @since 3.3.18
|
338 |
+
* @return $form_cache Array of form data.
|
339 |
+
* @updated 3.4.0
|
340 |
+
*/
|
341 |
+
public static function build_nf_cache( $id ) {
|
342 |
+
$form = Ninja_Forms()->form( $id )->get();
|
343 |
+
|
344 |
+
$form_cache = array(
|
345 |
+
'id' => $id,
|
346 |
+
'fields' => array(),
|
347 |
+
'actions' => array(),
|
348 |
+
'settings' => $form->get_settings(),
|
349 |
+
);
|
350 |
+
|
351 |
+
$fields = Ninja_Forms()->form( $id )->get_fields();
|
352 |
+
|
353 |
+
foreach( $fields as $field ){
|
354 |
+
// If the field is set.
|
355 |
+
if ( ! is_null( $field ) && ! empty( $field ) ) {
|
356 |
+
array_push( $form_cache[ 'fields' ], array( 'settings' => $field->get_settings(), 'id' => $field->get_id() ) );
|
357 |
+
}
|
358 |
+
}
|
359 |
+
|
360 |
+
$actions = Ninja_Forms()->form( $id )->get_actions();
|
361 |
+
|
362 |
+
foreach( $actions as $action ){
|
363 |
+
// If the action is set.
|
364 |
+
if ( ! is_null( $action ) && ! empty( $action ) ) {
|
365 |
+
array_push( $form_cache[ 'actions' ], array( 'settings' => $action->get_settings(), 'id' => $action->get_id() ) );
|
366 |
+
}
|
367 |
+
}
|
368 |
+
|
369 |
+
WPN_Helper::update_nf_cache( $id, $form_cache );
|
370 |
+
|
371 |
+
return $form_cache;
|
372 |
+
}
|
373 |
|
374 |
/**
|
375 |
* Function to delete our cache.
|
392 |
}
|
393 |
}
|
394 |
|
395 |
+
/**
|
396 |
+
* This funtion gets/creates the Ninja Forms gate keeper( a random integer
|
397 |
+
* between 1 and 100 ). We will use this number when deciding whether a
|
398 |
+
* particular install is eligible for an upgrade or whatever else we decide
|
399 |
+
* to use it for
|
400 |
+
*
|
401 |
+
* @return int $zuul
|
402 |
+
*
|
403 |
+
* @since 3.4.0
|
404 |
+
*/
|
405 |
+
public static function get_zuul() {
|
406 |
+
$zuul = get_option( 'ninja_forms_zuul', -1 );
|
407 |
+
|
408 |
+
if( -1 === $zuul ) {
|
409 |
+
$zuul = rand( 1, 100 );
|
410 |
+
update_option( 'ninja_forms_zuul', $zuul, false );
|
411 |
+
}
|
412 |
+
|
413 |
+
return $zuul;
|
414 |
+
}
|
415 |
+
|
416 |
+
/**
|
417 |
+
* This function will return true/false based on an option( ninja_forms_zuul )
|
418 |
+
* and a threshold that we set. We can use this to limit updates
|
419 |
+
*
|
420 |
+
* @param $threshold
|
421 |
+
*
|
422 |
+
* @return bool
|
423 |
+
*
|
424 |
+
* @since 3.4.0
|
425 |
+
*/
|
426 |
+
public static function gated_release( $threshold = 0 ) {
|
427 |
+
$gatekeeper = $threshold >= self::get_zuul();
|
428 |
+
$gatekeeper = apply_filters( 'ninja_forms_gatekeeper', $gatekeeper );
|
429 |
+
|
430 |
+
return $gatekeeper;
|
431 |
+
}
|
432 |
+
|
433 |
+
/**
|
434 |
+
* Is Maintenance
|
435 |
+
*
|
436 |
+
* Checks the upgrades table to see if the form the user is viewing
|
437 |
+
* is under maintenance mode.
|
438 |
+
*
|
439 |
+
* @since 3.4.0
|
440 |
+
*
|
441 |
+
* @param $form_id - The ID of the form we are checking.
|
442 |
+
*
|
443 |
+
* @return boolean
|
444 |
+
*/
|
445 |
+
public static function form_in_maintenance( $form_id ) {
|
446 |
+
global $wpdb;
|
447 |
+
|
448 |
+
// Get our maintenance value from the DB and return it at the zero position.
|
449 |
+
$maintenance = $wpdb->get_row(
|
450 |
+
"SELECT `maintenance` FROM `{$wpdb->prefix}nf3_upgrades` WHERE `id` = {$form_id}", 'ARRAY_A'
|
451 |
+
);
|
452 |
+
|
453 |
+
/*
|
454 |
+
* If maintenance isn't empty and basic on maintenance's value
|
455 |
+
* return a boolean value.
|
456 |
+
*/
|
457 |
+
if( ! empty( $maintenance ) && 1 == $maintenance[ 'maintenance' ] ) {
|
458 |
+
return true;
|
459 |
+
} else {
|
460 |
+
return false;
|
461 |
+
}
|
462 |
+
}
|
463 |
+
|
464 |
+
/**
|
465 |
+
* This function either put all forms in maintenance mode or remove maintenance
|
466 |
+
* mode for all forms. Depending on the input parameters
|
467 |
+
*
|
468 |
+
* @since 3.4.0
|
469 |
+
*
|
470 |
+
* @param $mode - Default 0 ( Take all forms out of maintenance mode )
|
471 |
+
*/
|
472 |
+
public static function set_forms_maintenance_mode( $mode = 0 ) {
|
473 |
+
global $wpdb;
|
474 |
+
|
475 |
+
// default is 0, so if we get passed bad data, just use 0
|
476 |
+
if( ! in_array( $mode, array( 0, 1 ) ) ) {
|
477 |
+
$mode = 0;
|
478 |
+
}
|
479 |
+
|
480 |
+
// set maintenance flag to $mode (0 or 1)
|
481 |
+
$sql = $wpdb->prepare( "UPDATE `{$wpdb->prefix}nf3_upgrades` SET "
|
482 |
+
. "maintenance = %d", intval( $mode ) );
|
483 |
+
|
484 |
+
$wpdb->query( $sql );
|
485 |
+
}
|
486 |
+
|
487 |
} // End Class WPN_Helper
|
includes/Templates/admin-menu-dashboard.html.php
CHANGED
@@ -233,6 +233,39 @@
|
|
233 |
?>
|
234 |
</script>
|
235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
<!-- Widget: Forms -->
|
237 |
<script id="tmpl-nf-widget-forms" type="text/template">
|
238 |
<header>
|
233 |
?>
|
234 |
</script>
|
235 |
|
236 |
+
<!-- Section: Required Updates -->
|
237 |
+
<script id="tmpl-nf-requiredUpdates" type="text/template">
|
238 |
+
<div>
|
239 |
+
<h1><?php _e( 'Required Updates', 'ninja-forms' ); ?></h1>
|
240 |
+
<div>
|
241 |
+
<p>
|
242 |
+
<?php _e( "Ninja Forms needs to run some updates on your installation before you can continue. You'll be able to create and edit forms after the updates listed below have completed.", 'ninja-forms' ); ?>
|
243 |
+
</p>
|
244 |
+
<p>
|
245 |
+
<?php _e( "Normally, users will still be able to view and submit forms while these updates take place. If an update needs to modify database information, we'll put the affected form in maintenance mode until we get done with that update.", 'ninja-forms' ); ?>
|
246 |
+
</p>
|
247 |
+
<p>
|
248 |
+
<?php _e( "It's always a good idea to have an up to date backup of your WordPress site on hand. That's especially true when you run plugin and theme updates. Luckily, there are plenty of good backup plugins available.", 'ninja-forms' ); ?>
|
249 |
+
</p>
|
250 |
+
<p>
|
251 |
+
<?php _e( "When you're ready, just click the \"Do Required Updates\" button below to get started. You'll be able to create and edit forms in no time.", 'ninja-forms' ); ?>
|
252 |
+
</p>
|
253 |
+
</div>
|
254 |
+
<div id="nfUpgradeApp">
|
255 |
+
<table id="nf-upgrades-table">
|
256 |
+
<thead>
|
257 |
+
</thead>
|
258 |
+
<tbody>
|
259 |
+
</tbody>
|
260 |
+
</table>
|
261 |
+
</div>
|
262 |
+
<div>
|
263 |
+
<input class="nf-required-update nf-update-button" type='button' id='nf-required-updates-btn' name='nf-required-updates-btn' value="<?php _e( 'Do Required Updates' ); ?>" />
|
264 |
+
</div>
|
265 |
+
<div class="nf-update-progress jBox-content" id="nf-required-updates-progress"></div>
|
266 |
+
</div>
|
267 |
+
</script>
|
268 |
+
|
269 |
<!-- Widget: Forms -->
|
270 |
<script id="tmpl-nf-widget-forms" type="text/template">
|
271 |
<header>
|
includes/Templates/admin-metabox-import-export-forms-import.html.php
CHANGED
@@ -1,44 +1,30 @@
|
|
1 |
<div class="wrap">
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
<tr id="row_nf_import_form">
|
9 |
<th scope="row">
|
10 |
-
<label for="
|
11 |
</th>
|
12 |
<td>
|
13 |
-
<input type="file"
|
14 |
</td>
|
15 |
</tr>
|
16 |
-
<tr id="
|
17 |
-
|
18 |
-
|
19 |
-
</th>
|
20 |
-
<td>
|
21 |
-
<input type="checkbox" name="nf_import_form_turn_off_encoding"
|
22 |
-
id="nf_import_form_turn_off_encoding">
|
23 |
-
<label style="color:red;font-style: italic;"
|
24 |
-
for="nf_import_form_turn_off_encoding">
|
25 |
-
If you are having trouble importing forms, please
|
26 |
-
click here to disable UTF-8 encoding
|
27 |
-
and try again.
|
28 |
-
</label>
|
29 |
-
</td>
|
30 |
</tr>
|
31 |
<tr id="row_nf_import_form_submit">
|
32 |
<th scope="row">
|
33 |
-
<label for="
|
34 |
</th>
|
35 |
<td>
|
36 |
-
<input type="
|
37 |
</td>
|
38 |
</tr>
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
</form>
|
43 |
-
|
44 |
</div>
|
1 |
<div class="wrap">
|
2 |
+
<table class="form-table">
|
3 |
+
<tbody>
|
4 |
+
<tr id="row-nf-import-response" style="display:none;background-color:#ffc;">
|
5 |
+
<th></th>
|
6 |
+
<td><?php printf( __( 'Form Imported Successfully. %sView Form%s', 'ninja-forms' ), '<a id="nf-import-url" href="#">', '</a>' ); ?></td>
|
7 |
+
</tr>
|
8 |
<tr id="row_nf_import_form">
|
9 |
<th scope="row">
|
10 |
+
<label for="nf-import-file"><?php echo __( 'Select a file', 'ninja-forms' ); ?></label>
|
11 |
</th>
|
12 |
<td>
|
13 |
+
<input type="file" id="nf-import-file" class="widefat">
|
14 |
</td>
|
15 |
</tr>
|
16 |
+
<tr id="row-nf-import-type-error" style="display:none;color:red;">
|
17 |
+
<th></th>
|
18 |
+
<td><?php printf( __( 'Please select a Ninja Forms export. %sMust be in .nff format%s.', 'ninja-forms' ), '<strong>', '</strong>' ); ?></td>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
</tr>
|
20 |
<tr id="row_nf_import_form_submit">
|
21 |
<th scope="row">
|
22 |
+
<label for="nf-import-form-submit"><?php _e( 'Import Form', 'ninja-forms' ); ?></label>
|
23 |
</th>
|
24 |
<td>
|
25 |
+
<input type="button" id="nf-import-form-submit" class="button-secondary" value="<?php echo __( 'Import Form', 'ninja-forms' ) ;?>">
|
26 |
</td>
|
27 |
</tr>
|
28 |
+
</tbody>
|
29 |
+
</table>
|
|
|
|
|
|
|
30 |
</div>
|
includes/Updates/CacheCollateActions.php
ADDED
@@ -0,0 +1,342 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class NF_Updates_CacheCollateActions
|
5 |
+
*
|
6 |
+
* This class manages the step process of running through the CacheCollateActions required update.
|
7 |
+
* It will define an object to pull data from (if necessary) to pick back up if exited early.
|
8 |
+
* It will run an upgrade function to alter the nf3_actions and nf3_action_meta tables.
|
9 |
+
* Then, it will step over each form on the site, following this process:
|
10 |
+
* - Actions that exist in the data tables but not in the cache will be deleted.
|
11 |
+
* - Actions that exist in the cache but not in the data tables will be inserted.
|
12 |
+
* - Actions that exist in the data tables but have an incorrect form ID will be inserted as a new ID and referenced from the cache.
|
13 |
+
* - Actions that exist in both will be updated from the cache to ensure the data is correct.
|
14 |
+
* After completing the above for every form on the site, it will remove the data object that manages its location.
|
15 |
+
*/
|
16 |
+
class NF_Updates_CacheCollateActions extends NF_Abstracts_RequiredUpdate
|
17 |
+
{
|
18 |
+
|
19 |
+
private $data = array();
|
20 |
+
|
21 |
+
private $running = array();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Stores information about the current form being processed.
|
25 |
+
* @var array
|
26 |
+
*/
|
27 |
+
private $form;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Stores the actions for the current form being processed.
|
31 |
+
* @var array
|
32 |
+
*/
|
33 |
+
private $actions;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Associative array of actions keyed by action id.
|
37 |
+
* @var array
|
38 |
+
*/
|
39 |
+
private $actions_by_id = array();
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Non-associative array of action ids.
|
43 |
+
* @var array
|
44 |
+
*/
|
45 |
+
private $action_ids = array();
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Hard limit for the number of querys we run during a single step.
|
49 |
+
* @var integer
|
50 |
+
*/
|
51 |
+
private $limit = 10;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Array of action ids that need an update.
|
55 |
+
* @var array
|
56 |
+
*/
|
57 |
+
private $update = array();
|
58 |
+
|
59 |
+
/**
|
60 |
+
* List of setting keys we don't want to save in the database.
|
61 |
+
* @var array
|
62 |
+
*/
|
63 |
+
private $blacklist = array(
|
64 |
+
'objectType',
|
65 |
+
'objectDomain',
|
66 |
+
'editActive',
|
67 |
+
'title',
|
68 |
+
'key',
|
69 |
+
);
|
70 |
+
|
71 |
+
/**
|
72 |
+
* The table names for our database queries.
|
73 |
+
*/
|
74 |
+
private $table;
|
75 |
+
private $meta_table;
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Constructor
|
79 |
+
*
|
80 |
+
* @param $data (Array) The data object passed in by the AJAX call.
|
81 |
+
* @param $running (Array) The array of required updates being run.
|
82 |
+
*
|
83 |
+
* @since 3.4.0
|
84 |
+
*/
|
85 |
+
public function __construct( $data = array(), $running )
|
86 |
+
{
|
87 |
+
// Build our arguments array.
|
88 |
+
$args = array(
|
89 |
+
'slug' => 'CacheCollateActions',
|
90 |
+
'class_name' => 'NF_Updates_CacheCollateActions',
|
91 |
+
'debug' => false,
|
92 |
+
);
|
93 |
+
$this->data = $data;
|
94 |
+
$this->running = $running;
|
95 |
+
|
96 |
+
// Call the parent constructor.
|
97 |
+
parent::__construct( $args );
|
98 |
+
|
99 |
+
// Set our table names.
|
100 |
+
$this->table = $this->db->prefix . 'nf3_actions';
|
101 |
+
$this->meta_table = $this->db->prefix . 'nf3_action_meta';
|
102 |
+
|
103 |
+
// Begin processing.
|
104 |
+
$this->process();
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Function to loop over the batch.
|
109 |
+
*
|
110 |
+
* @since 3.4.0
|
111 |
+
*/
|
112 |
+
public function process()
|
113 |
+
{
|
114 |
+
// If we've not already started...
|
115 |
+
if ( ! isset( $this->running[ 0 ][ 'running' ] ) ) {
|
116 |
+
// Run our startup method.
|
117 |
+
$this->startup();
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Get all of our database variables up and running.
|
122 |
+
* Sets up class vars that are used in subsequent methods.
|
123 |
+
*/
|
124 |
+
$this->setup_vars();
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Update action values and meta if necessary.
|
128 |
+
*/
|
129 |
+
$this->maybe_update_actions();
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Saves our current location, along with any processing data we may need for the next step.
|
133 |
+
* If we're done with our step, runs cleanup instead.
|
134 |
+
*/
|
135 |
+
$this->end_of_step();
|
136 |
+
|
137 |
+
// Respond to the AJAX call.
|
138 |
+
$this->respond();
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Function to run any setup steps necessary to begin processing.
|
143 |
+
*
|
144 |
+
* @since 3.4.0
|
145 |
+
*/
|
146 |
+
public function startup()
|
147 |
+
{
|
148 |
+
// Record that we're processing the update.
|
149 |
+
$this->running[ 0 ][ 'running' ] = true;
|
150 |
+
// If we're not debugging...
|
151 |
+
if ( ! $this->debug ) {
|
152 |
+
// Ensure that our data tables are updated.
|
153 |
+
$this->migrate( 'cache_collate_actions' );
|
154 |
+
}
|
155 |
+
// Get a list of our forms...
|
156 |
+
$sql = "SELECT ID FROM `{$this->db->prefix}nf3_forms`";
|
157 |
+
$forms = $this->db->get_results( $sql, 'ARRAY_A' );
|
158 |
+
$this->running[ 0 ][ 'forms' ] = $forms;
|
159 |
+
// Record the total number of steps in this batch.
|
160 |
+
$this->running[ 0 ][ 'steps' ] = count( $forms );
|
161 |
+
// Record our current step (defaulted to 0 here).
|
162 |
+
$this->running[ 0 ][ 'current' ] = 0;
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Setup our global variables used in other methods.
|
167 |
+
*
|
168 |
+
* @since 3.4.0
|
169 |
+
* @return void
|
170 |
+
*/
|
171 |
+
private function setup_vars()
|
172 |
+
{
|
173 |
+
// See which form we're currently working with.
|
174 |
+
$this->form = array_pop( $this->running[ 0 ][ 'forms' ] );
|
175 |
+
|
176 |
+
// Get the actions for that form.
|
177 |
+
$this->actions = Ninja_Forms()->form( $this->form[ 'ID' ] )->get_actions();
|
178 |
+
|
179 |
+
// For each action...
|
180 |
+
foreach ( $this->actions as $action ) {
|
181 |
+
// Add the ID to the list.
|
182 |
+
array_push( $this->action_ids, $action->get_id() );
|
183 |
+
$this->actions_by_id[ $action->get_id() ] = $action->get_settings();
|
184 |
+
}
|
185 |
+
|
186 |
+
// If we're continuing an old process...
|
187 |
+
if ( isset( $this->form[ 'update' ] ) ) {
|
188 |
+
// Fetch our remaining udpates.
|
189 |
+
$this->update = $this->form[ 'update' ];
|
190 |
+
} // Otherwise... (We're beginning a new process.)
|
191 |
+
else {
|
192 |
+
// Copy all IDs to our update list.
|
193 |
+
$this->update = $this->action_ids;
|
194 |
+
}
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Function to cleanup any lingering temporary elements of a required update after completion.
|
199 |
+
*
|
200 |
+
* @since 3.4.0
|
201 |
+
*/
|
202 |
+
public function cleanup()
|
203 |
+
{
|
204 |
+
// Remove the current process from the array.
|
205 |
+
array_shift( $this->running );
|
206 |
+
// Record to our updates setting that this update is complete.
|
207 |
+
$this->confirm_complete();
|
208 |
+
// If we have no updates left to process...
|
209 |
+
if ( empty( $this->running ) ) {
|
210 |
+
// Call the parent cleanup method.
|
211 |
+
parent::cleanup();
|
212 |
+
}
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Check to see if we've locked processing.
|
217 |
+
* If we have, then we need to run this process again.
|
218 |
+
*
|
219 |
+
* If we haven't locked processing, prepare to end this process.
|
220 |
+
*
|
221 |
+
* @since 3.4.0
|
222 |
+
* @return void
|
223 |
+
*/
|
224 |
+
private function end_of_step()
|
225 |
+
{
|
226 |
+
// If we have locked processing...
|
227 |
+
if ( $this->lock_process ) {
|
228 |
+
// Record that we have more to do.
|
229 |
+
$this->form[ 'update' ] = $this->update;
|
230 |
+
array_push( $this->running[ 0 ][ 'forms' ], $this->form );
|
231 |
+
} // Otherwise... (Processing isn't locked.)
|
232 |
+
else {
|
233 |
+
// If we have actions...
|
234 |
+
if ( ! empty( $this->action_ids ) ) {
|
235 |
+
// Update our meta keys.
|
236 |
+
$sql = "UPDATE `{$this->meta_table}` SET `meta_key` = `key` WHERE `parent_id` IN(" . implode( ',', $this->action_ids ) . ")";
|
237 |
+
$this->query( $sql );
|
238 |
+
}
|
239 |
+
/**
|
240 |
+
* Update our form cache with any action changes.
|
241 |
+
*/
|
242 |
+
$this->update_form_cache();
|
243 |
+
// Increment our step count.
|
244 |
+
$this->running[ 0 ][ 'current' ] = intval( $this->running[ 0 ][ 'current' ] ) +1;
|
245 |
+
}
|
246 |
+
|
247 |
+
|
248 |
+
// Prepare to output our number of steps and current step.
|
249 |
+
$this->response[ 'stepsTotal' ] = $this->running[ 0 ][ 'steps' ];
|
250 |
+
$this->response[ 'currentStep' ] = $this->running[ 0 ][ 'current' ];
|
251 |
+
|
252 |
+
// If we do not have locked processing...
|
253 |
+
if ( ! $this->lock_process ) {
|
254 |
+
// If all steps have been completed...
|
255 |
+
if ( empty( $this->running[ 0 ] [ 'forms' ] ) ) {
|
256 |
+
// Run our cleanup method.
|
257 |
+
$this->cleanup();
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
// Record our current location in the process.
|
262 |
+
update_option( 'ninja_forms_doing_required_updates', $this->running );
|
263 |
+
// Prepare to output the number of updates remaining.
|
264 |
+
$this->response[ 'updatesRemaining' ] = count( $this->running );
|
265 |
+
}
|
266 |
+
|
267 |
+
/**
|
268 |
+
* If we've made any changes to our form actions, update our form cache to match.
|
269 |
+
*
|
270 |
+
* @since 3.4.0
|
271 |
+
* @return void
|
272 |
+
*/
|
273 |
+
private function update_form_cache()
|
274 |
+
{
|
275 |
+
// Get the cache for that form.
|
276 |
+
$cache = WPN_Helper::get_nf_cache( $this->form[ 'ID' ] );
|
277 |
+
// Bust the cache.
|
278 |
+
$cache[ 'actions' ] = array();
|
279 |
+
// For each action...
|
280 |
+
foreach ( $this->actions_by_id as $id => $settings ) {
|
281 |
+
// Append the settings for that action to the cache.
|
282 |
+
$action = array();
|
283 |
+
$action[ 'settings' ] = $settings;
|
284 |
+
$action[ 'id' ] = $id;
|
285 |
+
array_push( $cache[ 'actions' ], $action );
|
286 |
+
}
|
287 |
+
// Save the cache, passing 2 as the current stage.
|
288 |
+
WPN_Helper::update_nf_cache( $this->form[ 'ID' ], $cache, 2 );
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Loop over all of our actions and update our database if necessary.
|
293 |
+
* Check each setting against $this->blacklist to make sure we want to insert that value.
|
294 |
+
*
|
295 |
+
* @since 3.4.0
|
296 |
+
* @return void
|
297 |
+
*/
|
298 |
+
private function maybe_update_actions()
|
299 |
+
{
|
300 |
+
// Declare placeholder values.
|
301 |
+
$sub_sql = array();
|
302 |
+
$meta_values = array();
|
303 |
+
|
304 |
+
// While we have actions to update...
|
305 |
+
while ( 0 < count( $this->update ) ) {
|
306 |
+
// If we have hit our limit...
|
307 |
+
if ( 1 > $this->limit ) {
|
308 |
+
// Lock processing.
|
309 |
+
$this->lock_process = true;
|
310 |
+
// Exit the loop.
|
311 |
+
break;
|
312 |
+
}
|
313 |
+
// Get our action to be updated.
|
314 |
+
$action = array_pop( $this->update );
|
315 |
+
// Get our settings.
|
316 |
+
$settings = $this->actions_by_id[ $action ];
|
317 |
+
// Update the new label column.
|
318 |
+
array_push( $sub_sql, "WHEN `id` = " . intval( $action ) . " THEN '" . $this->prepare( $settings[ 'label' ] ) . "'" );
|
319 |
+
// For each setting...
|
320 |
+
foreach ( $settings as $key => $setting ) {
|
321 |
+
// If the key is not blacklisted...
|
322 |
+
if ( ! in_array( $key, $this->blacklist ) ) {
|
323 |
+
// Add the value to be updated.
|
324 |
+
$action = intval( $action );
|
325 |
+
array_push( $meta_values, "WHEN `key` = '{$key}' AND `parent_id` = {$action} THEN '" . $this->prepare( $setting ) . "'" );
|
326 |
+
}
|
327 |
+
}
|
328 |
+
$this->limit--;
|
329 |
+
}
|
330 |
+
|
331 |
+
// If we've got updates to run...
|
332 |
+
if ( ! empty( $sub_sql ) ) {
|
333 |
+
// Update our actions table.
|
334 |
+
$sql = "UPDATE `{$this->table}` SET `label` = CASE " . implode ( ' ', $sub_sql ) . " ELSE `label` END;";
|
335 |
+
$this->query( $sql );
|
336 |
+
// Update our meta values.
|
337 |
+
$sql = "UPDATE `{$this->meta_table}` SET `meta_value` = CASE " . implode( ' ', $meta_values ) . " ELSE `meta_value` END;";
|
338 |
+
$this->query( $sql );
|
339 |
+
}
|
340 |
+
}
|
341 |
+
|
342 |
+
}
|
includes/Updates/CacheCollateCleanup.php
ADDED
@@ -0,0 +1,507 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class NF_Updates_CacheCollateCleanup
|
5 |
+
*
|
6 |
+
* This class manages the step process of running through the CacheCollateCleanup required update.
|
7 |
+
* It will define an object to pull data from (if necessary) to pick back up if exited early.
|
8 |
+
* It will then step over each table in our structure and ensure that orphan records are removed from storage.
|
9 |
+
* It will then step over all submissions, removing any orphans.
|
10 |
+
* It will then step over all submissions (by form), updating or removing any orphan field records.
|
11 |
+
* After completing the above for every form on the site, it will remove the data object that manages its location.
|
12 |
+
*/
|
13 |
+
class NF_Updates_CacheCollateCleanup extends NF_Abstracts_RequiredUpdate
|
14 |
+
{
|
15 |
+
|
16 |
+
private $data = array();
|
17 |
+
|
18 |
+
private $running = array();
|
19 |
+
|
20 |
+
/**
|
21 |
+
* The denominator object for calculating our steps.
|
22 |
+
* @var Integer
|
23 |
+
*/
|
24 |
+
private $divisor = 500;
|
25 |
+
|
26 |
+
private $stage;
|
27 |
+
|
28 |
+
private $stage_complete = false;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Constructor
|
32 |
+
*
|
33 |
+
* @param $data (Array) The data object passed in by the AJAX call.
|
34 |
+
* @param $running (Array) The array of required updates being run.
|
35 |
+
*
|
36 |
+
* @since 3.4.0
|
37 |
+
*/
|
38 |
+
public function __construct( $data = array(), $running )
|
39 |
+
{
|
40 |
+
// Build our arguments array.
|
41 |
+
$args = array(
|
42 |
+
'slug' => 'CacheCollateCleanup',
|
43 |
+
'class_name' => 'NF_Updates_CacheCollateCleanup',
|
44 |
+
'debug' => false,
|
45 |
+
);
|
46 |
+
$this->data = $data;
|
47 |
+
$this->running = $running;
|
48 |
+
|
49 |
+
// Call the parent constructor.
|
50 |
+
parent::__construct( $args );
|
51 |
+
|
52 |
+
// Begin processing.
|
53 |
+
$this->process();
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Function to loop over the batch.
|
58 |
+
*
|
59 |
+
* @since 3.4.0
|
60 |
+
*/
|
61 |
+
public function process()
|
62 |
+
{
|
63 |
+
// If we've not already started...
|
64 |
+
if ( ! isset( $this->running[ 0 ][ 'running' ] ) ) {
|
65 |
+
// Run our startup method.
|
66 |
+
$this->startup();
|
67 |
+
}
|
68 |
+
$this->stage = $this->running[ 0 ][ 'stages' ][ 0 ];
|
69 |
+
|
70 |
+
// Determine what process to run.
|
71 |
+
switch ( $this->stage[ 'table' ] ) {
|
72 |
+
case 'submissions':
|
73 |
+
// If we've cleaned out all orphan submissions...
|
74 |
+
if ( $this->stage[ 'purged' ] ) {
|
75 |
+
// Work on clearing out orphan field records.
|
76 |
+
$this->adopt_fields();
|
77 |
+
} // Otherwise... (We still have orphan submissions.)
|
78 |
+
else {
|
79 |
+
// Remove orphan submissions.
|
80 |
+
$this->adopt_subs();
|
81 |
+
}
|
82 |
+
break;
|
83 |
+
default:
|
84 |
+
// If we need to step over this process...
|
85 |
+
if ( $this->divisor < $this->stage[ 'parent_total' ] ) {
|
86 |
+
// Call stepped deletion.
|
87 |
+
$this->do_step_delete();
|
88 |
+
} // Otherwise... (We don't need to step over this.)
|
89 |
+
else {
|
90 |
+
// Call simple deletion.
|
91 |
+
$this->do_easy_delete();
|
92 |
+
}
|
93 |
+
// Increment our step count.
|
94 |
+
$this->running[ 0 ][ 'current' ] += 1;
|
95 |
+
break;
|
96 |
+
}
|
97 |
+
// If we have completed the current stage...
|
98 |
+
if ( $this->stage_complete ) {
|
99 |
+
// Remove it from our list.
|
100 |
+
array_shift( $this->running[ 0 ][ 'stages' ] );
|
101 |
+
} // Otherwise... (We have not completed the stage)
|
102 |
+
else {
|
103 |
+
// Record our changes.
|
104 |
+
$this->running[ 0 ][ 'stages' ][ 0 ] = $this->stage;
|
105 |
+
}
|
106 |
+
// Prepare to output our number of steps and current step.
|
107 |
+
$this->response[ 'stepsTotal' ] = $this->running[ 0 ][ 'steps' ];
|
108 |
+
$this->response[ 'currentStep' ] = $this->running[ 0 ][ 'current' ];
|
109 |
+
|
110 |
+
// If we have no stages left...
|
111 |
+
if ( empty( $this->running[ 0 ][ 'stages' ] ) ) {
|
112 |
+
// Run our cleanup method.
|
113 |
+
$this->cleanup();
|
114 |
+
}
|
115 |
+
|
116 |
+
// Prepare to output the number of updates remaining.
|
117 |
+
$this->response[ 'updatesRemaining' ] = count( $this->running );
|
118 |
+
|
119 |
+
// Record our current location in the process.
|
120 |
+
update_option( 'ninja_forms_doing_required_updates', $this->running );
|
121 |
+
|
122 |
+
// Respond to the AJAX call.
|
123 |
+
$this->respond();
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Function to run any setup steps necessary to begin processing.
|
128 |
+
*
|
129 |
+
* @since 3.4.0
|
130 |
+
*/
|
131 |
+
public function startup()
|
132 |
+
{
|
133 |
+
// Record that we're processing the update.
|
134 |
+
$this->running[ 0 ][ 'running' ] = true;
|
135 |
+
|
136 |
+
// Get the number of records in the forms table.
|
137 |
+
$form_count = $this->get_total( 'nf3_forms' );
|
138 |
+
// Get the number of records in the fields table.
|
139 |
+
$action_count = $this->get_total( 'nf3_actions' );
|
140 |
+
// Get the number of records in the actions table.
|
141 |
+
$field_count = $this->get_total( 'nf3_fields' );
|
142 |
+
// Get the number of records in the objects table.
|
143 |
+
$object_count = $this->get_total( 'nf3_objects' );
|
144 |
+
|
145 |
+
// Get all form_ids from the db for the submissions portion.
|
146 |
+
$sql = "SELECT `id` FROM `{$this->db->prefix}nf3_forms`";
|
147 |
+
$forms = $this->db->get_results( $sql, 'ARRAY_A' );
|
148 |
+
|
149 |
+
$stages = array(
|
150 |
+
array(
|
151 |
+
'table' => $this->db->prefix . 'nf3_form_meta',
|
152 |
+
'parent' => $this->db->prefix . 'nf3_forms',
|
153 |
+
'parent_total' => $form_count,
|
154 |
+
),
|
155 |
+
array(
|
156 |
+
'table' => $this->db->prefix . 'nf3_actions',
|
157 |
+
'parent' => $this->db->prefix . 'nf3_forms',
|
158 |
+
'parent_total' => $form_count,
|
159 |
+
),
|
160 |
+
array(
|
161 |
+
'table' => $this->db->prefix . 'nf3_action_meta',
|
162 |
+
'parent' => $this->db->prefix . 'nf3_actions',
|
163 |
+
'parent_total' => $action_count,
|
164 |
+
),
|
165 |
+
array(
|
166 |
+
'table' => $this->db->prefix . 'nf3_fields',
|
167 |
+
'parent' => $this->db->prefix . 'nf3_forms',
|
168 |
+
'parent_total' => $form_count,
|
169 |
+
),
|
170 |
+
array(
|
171 |
+
'table' => $this->db->prefix . 'nf3_field_meta',
|
172 |
+
'parent' => $this->db->prefix . 'nf3_fields',
|
173 |
+
'parent_total' => $field_count,
|
174 |
+
),
|
175 |
+
array(
|
176 |
+
'table' => $this->db->prefix . 'nf3_object_meta',
|
177 |
+
'parent' => $this->db->prefix . 'nf3_objects',
|
178 |
+
'parent_total' => $object_count,
|
179 |
+
),
|
180 |
+
array(
|
181 |
+
'table' => 'submissions',
|
182 |
+
'parent_total' => $form_count,
|
183 |
+
'purged' => false,
|
184 |
+
'forms' => $forms,
|
185 |
+
),
|
186 |
+
);
|
187 |
+
|
188 |
+
$add = 0;
|
189 |
+
// Set the steps for form meta (enforcing a minimum step count).
|
190 |
+
$add = ceil( $form_count / $this->divisor );
|
191 |
+
$steps = ( 0 == $add ) ? 1 : $add;
|
192 |
+
// Add actions and fields.
|
193 |
+
$steps *= 3;
|
194 |
+
// Add action meta (enforcing a minimum step count).
|
195 |
+
$add = ceil( $action_count / $this->divisor );
|
196 |
+
$add = ( 0 == $add ) ? 1 : $add;
|
197 |
+
$steps += $add;
|
198 |
+
// Add field meta (enforcing a minimum step count).
|
199 |
+
$add = ceil( $field_count / $this->divisor );
|
200 |
+
$add = ( 0 == $add ) ? 1 : $add;
|
201 |
+
$steps += $add;
|
202 |
+
// Add object meta (enforcing a minimum step count).
|
203 |
+
$add = ceil( $object_count / $this->divisor );
|
204 |
+
$add = ( 0 == $add ) ? 1 : $add;
|
205 |
+
$steps += $add;
|
206 |
+
// Add one plus the form count for submissions (enforcing a minimum step count).
|
207 |
+
$add = $form_count + 1;
|
208 |
+
$add = ( 1 == $add ) ? 2 : $add;
|
209 |
+
$steps += $add;
|
210 |
+
|
211 |
+
$this->running[ 0 ][ 'stages' ] = $stages;
|
212 |
+
|
213 |
+
// Record the total number of steps in this batch.
|
214 |
+
$this->running[ 0 ][ 'steps' ] = $steps;
|
215 |
+
// Record our current step (defaulted to 0 here).
|
216 |
+
$this->running[ 0 ][ 'current' ] = 0;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Function to cleanup any lingering temporary elements of a required update after completion.
|
221 |
+
*
|
222 |
+
* @since 3.4.0
|
223 |
+
*/
|
224 |
+
public function cleanup()
|
225 |
+
{
|
226 |
+
// Remove the current process from the array.
|
227 |
+
array_shift( $this->running );
|
228 |
+
// Record to our updates setting that this update is complete.
|
229 |
+
$this->confirm_complete();
|
230 |
+
// If we have no updates left to process...
|
231 |
+
if ( empty( $this->running ) ) {
|
232 |
+
// Call the parent cleanup method.
|
233 |
+
parent::cleanup();
|
234 |
+
}
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Function to get the number of objects in a table.
|
239 |
+
*
|
240 |
+
* @param $table (String) The name of the target table.
|
241 |
+
*
|
242 |
+
* @return (Int) The count of rows.
|
243 |
+
*
|
244 |
+
* @since 3.4.0
|
245 |
+
*/
|
246 |
+
public function get_total( $table )
|
247 |
+
{
|
248 |
+
$sql = "SELECT COUNT( `id` ) AS Total FROM `{$this->db->prefix}{$table}`;";
|
249 |
+
$result = $this->db->get_results( $sql, 'ARRAY_A' );
|
250 |
+
return intval( $result[ 0 ][ 'Total' ] );
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Function to perform a simple, single-step delete of orphan data.
|
255 |
+
*
|
256 |
+
* @since 3.4.0
|
257 |
+
*/
|
258 |
+
private function do_easy_delete()
|
259 |
+
{
|
260 |
+
// Remove the orphan records.
|
261 |
+
$sql = "DELETE FROM `{$this->stage[ 'table' ]}`
|
262 |
+
WHERE `parent_id` NOT IN(
|
263 |
+
SELECT `id` FROM `{$this->stage[ 'parent' ]}`
|
264 |
+
);";
|
265 |
+
$this->query( $sql );
|
266 |
+
// Confirm that this stage is complete.
|
267 |
+
$this->stage_complete = true;
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Function to perform a multi-step delete of orphan data.
|
272 |
+
*
|
273 |
+
* @since 3.4.0
|
274 |
+
*/
|
275 |
+
private function do_step_delete()
|
276 |
+
{
|
277 |
+
// Get records from our table.
|
278 |
+
$sub_sql = "SELECT DISTINCT( `parent_id` ) AS id FROM `{$this->stage[ 'table' ]}` ";
|
279 |
+
// If we have a previous last record...
|
280 |
+
if ( isset( $this->stage[ 'last' ] ) ) {
|
281 |
+
// Make sure we exclude anything before it from the result.
|
282 |
+
$sub_sql .= "WHERE `parent_id` > " . $this->stage[ 'last' ] . " ";
|
283 |
+
}
|
284 |
+
$sub_sql .= "ORDER BY `parent_id` ASC
|
285 |
+
LIMIT {$this->divisor};";
|
286 |
+
$result = $this->db->get_results( $sub_sql, 'ARRAY_A' );
|
287 |
+
// Get the last affected row.
|
288 |
+
$last = end( $result );
|
289 |
+
// Squash our results to get a non-associative array.
|
290 |
+
$result = $this->array_squash( $result );
|
291 |
+
$this->stage[ 'last' ] = intval( $last[ 'id' ] );
|
292 |
+
// Get records from the parent table.
|
293 |
+
$sql = "SELECT `id` FROM `{$this->stage[ 'parent' ]}`
|
294 |
+
WHERE `id` IN(" . implode( ', ', $result ) .
|
295 |
+
");";
|
296 |
+
$parent_result = $this->db->get_results( $sql, 'ARRAY_A' );
|
297 |
+
// If we didn't get the same number of results...
|
298 |
+
if ( count( $result ) !== count( $parent_result ) ) {
|
299 |
+
// Merge our results.
|
300 |
+
$result = array_merge( $result, $parent_result );
|
301 |
+
// Convert the array to something we can sort by duplicates.
|
302 |
+
$temp = array_count_values( array_column( $result, 'id' ) );
|
303 |
+
// Get rid of all values that had more than 1 result.
|
304 |
+
$temp = array_filter( $temp, array( $this, 'uniquify' ) );
|
305 |
+
// Schedule all of the single result values for deletion.
|
306 |
+
$delete = implode( ', ', array_keys( $temp ) );
|
307 |
+
$sql = "DELETE FROM `{$this->stage[ 'table' ]}`
|
308 |
+
WHERE `parent_id` IN( {$delete} );";
|
309 |
+
$this->query( $sql );
|
310 |
+
}
|
311 |
+
// If we've not already determined the limit of this table...
|
312 |
+
if ( ! isset( $this->stage[ 'max' ] ) ) {
|
313 |
+
// Fetch the maximum value.
|
314 |
+
$sql = "SELECT MAX( `parent_id` ) FROM `{$this->stage[ 'table' ]}`";
|
315 |
+
$result = $this->db->get_results( $sql, 'ARRAY_A' );
|
316 |
+
// Save a reference to it.
|
317 |
+
$this->stage[ 'max' ] = intval( $result[ 0 ][ 'parent_id' ] );
|
318 |
+
}
|
319 |
+
// If our last record is equal to our maximum record...
|
320 |
+
if ( $this->stage[ 'last' ] == $this->stage[ 'max' ] ) {
|
321 |
+
// Record that we're done with this stage.
|
322 |
+
$this->stage_complete = true;
|
323 |
+
}
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Function called by array_filter to remove ALL duplicate results.
|
328 |
+
*
|
329 |
+
* @param $v (Int) The number of results.
|
330 |
+
*
|
331 |
+
* @return (Boolean)
|
332 |
+
*
|
333 |
+
* @since 3.4.0
|
334 |
+
*/
|
335 |
+
private function uniquify( $v )
|
336 |
+
{
|
337 |
+
// If we have 1 result, keep it.
|
338 |
+
return $v == 1;
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Function to remove orphan submissions from the posts and postmeta tables.
|
343 |
+
*
|
344 |
+
* @since 3.4.0
|
345 |
+
*/
|
346 |
+
private function adopt_subs()
|
347 |
+
{
|
348 |
+
// Fetch a limited number of orphan subs to delete.
|
349 |
+
$sub_sql = "SELECT m.post_id AS id from `{$this->db->prefix}postmeta` AS m
|
350 |
+
LEFT OUTER JOIN `{$this->db->prefix}posts` AS p
|
351 |
+
ON m.post_id = p.id
|
352 |
+
WHERE m.meta_key = '_form_id'
|
353 |
+
AND p.post_type = 'nf_sub'
|
354 |
+
AND m.meta_value NOT IN(
|
355 |
+
SELECT `id` from `{$this->db->prefix}nf3_forms`
|
356 |
+
)
|
357 |
+
ORDER BY m.post_id ASC
|
358 |
+
LIMIT {$this->divisor};";
|
359 |
+
$result = $this->db->get_results( $sub_sql, 'ARRAY_A' );
|
360 |
+
// Count them.
|
361 |
+
$count = count( $result );
|
362 |
+
// Squash our results to get a non-associative array.
|
363 |
+
$result = $this->array_squash( $result );
|
364 |
+
// If we have records to be deleted...
|
365 |
+
if ( 0 < $count ) {
|
366 |
+
// Remove their postmeta.
|
367 |
+
$sql = "DELETE FROM `{$this->db->prefix}postmeta`
|
368 |
+
WHERE post_id IN(" . implode( ', ', $result ) . ");";
|
369 |
+
$this->query( $sql );
|
370 |
+
// Remove the posts.
|
371 |
+
$sql = "DELETE FROM `{$this->db->prefix}posts`
|
372 |
+
WHERE id IN(" . implode( ', ', $result ) . ");";
|
373 |
+
$this->query( $sql );
|
374 |
+
}
|
375 |
+
// If the number of affected rows was less than our divisor...
|
376 |
+
if ( $count < $this->divisor ) {
|
377 |
+
// Mark that we've completed the process.
|
378 |
+
$this->stage[ 'purged' ] = true;
|
379 |
+
// Increment our step count.
|
380 |
+
$this->running[ 0 ][ 'current' ] += 1;
|
381 |
+
}
|
382 |
+
}
|
383 |
+
|
384 |
+
/**
|
385 |
+
* Function to remove orphan field data that's still attached
|
386 |
+
* to valid submissions from the postmeta table.
|
387 |
+
*
|
388 |
+
* @since 3.4.0
|
389 |
+
*/
|
390 |
+
private function adopt_fields()
|
391 |
+
{
|
392 |
+
// Get the form to work with.
|
393 |
+
$form = array_pop( $this->stage[ 'forms' ] );
|
394 |
+
// Fetch meta rows that match our criteria.
|
395 |
+
$sql = "SELECT r.meta_id, r.meta_key AS field_id
|
396 |
+
FROM `{$this->db->prefix}posts` AS p
|
397 |
+
LEFT JOIN `{$this->db->prefix}postmeta` AS r
|
398 |
+
ON r.post_id = p.id
|
399 |
+
LEFT JOIN `{$this->db->prefix}postmeta` AS f
|
400 |
+
ON f.post_id = p.id
|
401 |
+
WHERE p.post_type = 'nf_sub'
|
402 |
+
AND f.meta_key = '_form_id'
|
403 |
+
AND f.meta_value = " . intval( $form[ 'id' ] ) . "
|
404 |
+
AND r.meta_key LIKE '_field_%' ";
|
405 |
+
// If last is set...
|
406 |
+
if ( isset( $form[ 'last' ] ) ) {
|
407 |
+
// Make sure we're getting new results instead of old ones.
|
408 |
+
$sql .= "AND r.meta_id > {$form[ 'last' ]} ";
|
409 |
+
}
|
410 |
+
$sql .= "ORDER BY r.meta_id ASC
|
411 |
+
LIMIT {$this->divisor};";
|
412 |
+
$results = $this->db->get_results( $sql, 'ARRAY_A' );
|
413 |
+
// Count them.
|
414 |
+
$count = count( $result );
|
415 |
+
// Get all fields associated with this form.
|
416 |
+
$sql = "SELECT id FROM `{$this->db->prefix}nf3_fields` WHERE parent_id = " . intval( $form[ 'id' ] ) . ";";
|
417 |
+
$fields = $this->db->get_results( $sql, 'ARRAY_A' );
|
418 |
+
// Squash our results to get a non-associative array.
|
419 |
+
$fields = $this->array_squash( $fields );
|
420 |
+
$bad_records = array();
|
421 |
+
// For each result...
|
422 |
+
foreach( $results as $result ) {
|
423 |
+
// Pull the text out of our meta.
|
424 |
+
$id = str_replace( '_field_', '', $result[ 'field_id' ] );
|
425 |
+
$id = intval( $id );
|
426 |
+
// If this field isn't on the form...
|
427 |
+
if ( ! in_array( $id, $fields ) ) {
|
428 |
+
// Add it to our list to check later.
|
429 |
+
$bad_records[ $id ][] = $result[ 'meta_id' ];
|
430 |
+
}
|
431 |
+
}
|
432 |
+
|
433 |
+
// Get a list of any old_field_ids from our field table update.
|
434 |
+
$sql = "SELECT f.id AS new_id, m.meta_value AS id
|
435 |
+
FROM `{$this->db->prefix}nf3_fields` AS f
|
436 |
+
LEFT JOIN `{$this->db->prefix}nf3_field_meta` AS m
|
437 |
+
ON f.id = m.parent_id
|
438 |
+
WHERE f.parent_id = " . intval( $form[ 'id' ] ) . "
|
439 |
+
AND m.meta_key = 'old_field_id';";
|
440 |
+
$old_ids = $this->db->get_results( $sql, 'ARRAY_A' );
|
441 |
+
// Squash our results to get an associative array.
|
442 |
+
$old_ids = $this->array_squash( $old_ids );
|
443 |
+
|
444 |
+
// For each id in the bad records list...
|
445 |
+
foreach ( $bad_records as $field => $meta ) {
|
446 |
+
// If we have a new ID for that record...
|
447 |
+
if ( isset( $old_ids[ $field ] ) ) {
|
448 |
+
// Update our submissions.
|
449 |
+
$sql = "UPDATE `{$this->db->prefix}postmeta`
|
450 |
+
SET `meta_key` = '_field_" . $old_ids[ $field ] . "'
|
451 |
+
WHERE `meta_id` IN(" . implode( ', ', $meta ) . ");";
|
452 |
+
$this->query( $sql );
|
453 |
+
} // Otherwise... (We don't have a new ID for it.)
|
454 |
+
else {
|
455 |
+
// Delete the orphan record.
|
456 |
+
$sql = "DELETE FROM `{$this->db->prefix}postmeta`
|
457 |
+
WHERE `meta_id` IN(" . implode( ', ', $meta ) . ");";
|
458 |
+
$this->query( $sql );
|
459 |
+
}
|
460 |
+
}
|
461 |
+
// If the number of affected rows was less than our divisor...
|
462 |
+
if ( $count < $this->divisor ) {
|
463 |
+
// Increment our step count.
|
464 |
+
$this->running[ 0 ][ 'current' ] += 1;
|
465 |
+
} // Otherwise... (We need to continue.)
|
466 |
+
else {
|
467 |
+
// Put our form back on the stack.
|
468 |
+
array_push( $this->stage[ 'forms' ], $form );
|
469 |
+
}
|
470 |
+
// If there are no forms left to process...
|
471 |
+
if ( empty( $this->stage[ 'forms' ] ) ) {
|
472 |
+
// Mark that this stage is done.
|
473 |
+
$this->stage_complete = true;
|
474 |
+
}
|
475 |
+
}
|
476 |
+
|
477 |
+
/**
|
478 |
+
* Function to compress our db results into a more useful format.
|
479 |
+
*
|
480 |
+
* @param $data (Array) The result to be compressed.
|
481 |
+
*
|
482 |
+
* @return (Array) Associative if our data was complex.
|
483 |
+
* Non-associative if our data was a single item.
|
484 |
+
*
|
485 |
+
* @since 3.4.0
|
486 |
+
*/
|
487 |
+
private function array_squash( $data )
|
488 |
+
{
|
489 |
+
$response = array();
|
490 |
+
// For each item in the array...
|
491 |
+
foreach ( $data as $row ) {
|
492 |
+
// If the item has more than 1 attribute...
|
493 |
+
if ( 1 < count( $row ) ) {
|
494 |
+
// Assign the data to an associated result.
|
495 |
+
$response[ $row[ 'id' ] ] = $row;
|
496 |
+
// Unset the id setting, as that will be the key.
|
497 |
+
unset( $response[ $row[ 'id' ] ][ 'id' ] );
|
498 |
+
} // Otherwise... (We only have 1 attribute.)
|
499 |
+
else {
|
500 |
+
// Add the id to the stack in a non-associated result.
|
501 |
+
$response[] = intval( $row[ 'id' ] );
|
502 |
+
}
|
503 |
+
}
|
504 |
+
return $response;
|
505 |
+
}
|
506 |
+
|
507 |
+
}
|
includes/Updates/CacheCollateFields.php
ADDED
@@ -0,0 +1,720 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class NF_Updates_CacheCollateFields
|
5 |
+
*
|
6 |
+
* This class manages the step process of running through the CacheCollateFields required update.
|
7 |
+
* It will define an object to pull data from (if necessary) to pick back up if exited early.
|
8 |
+
* It will run an upgrade function to alter the nf3_fields and nf3_field_meta tables.
|
9 |
+
* Then, it will step over each form on the site, following this process:
|
10 |
+
* - Fields that exist in the data tables but not in the cache will be deleted.
|
11 |
+
* - Fields that exist in the cache but not in the data tables will be inserted.
|
12 |
+
* - Fields that exist in the data tables but have an incorrect form ID will be inserted as a new ID and referenced from the cache.
|
13 |
+
* - Fields that exist in both will be updated from the cache to ensure the data is correct.
|
14 |
+
* After completing the above for every form on the site, it will remove the data object that manages its location.
|
15 |
+
*/
|
16 |
+
class NF_Updates_CacheCollateFields extends NF_Abstracts_RequiredUpdate
|
17 |
+
{
|
18 |
+
|
19 |
+
private $data = array();
|
20 |
+
|
21 |
+
private $running = array();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Non-associatve array of field ids from the cache.
|
25 |
+
* @var array
|
26 |
+
*/
|
27 |
+
private $field_ids = array();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Associative array of field ids from the cache, using the field id as the key.
|
31 |
+
* $fields_by_id[ field_id ] = $settings;
|
32 |
+
* @var array
|
33 |
+
*/
|
34 |
+
private $fields_by_id = array();
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Non-associative array that tracks what we should we insert because it exists in our cache but not in the Fields table.
|
38 |
+
* @var array
|
39 |
+
*/
|
40 |
+
private $insert = array();
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Non-associatve array that tracks field ids that should be deleted from fields DB table.
|
44 |
+
* @var array
|
45 |
+
*/
|
46 |
+
private $delete = array();
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Associative array that tracks field ids that have changed.
|
50 |
+
* $submission_updates[ old_field_id ] = new_field_id;
|
51 |
+
* @var array
|
52 |
+
*/
|
53 |
+
private $submission_updates = array();
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Associatve array that tracks newly inserted fields.
|
57 |
+
* $insert_ids[ field_id ] = field_id;
|
58 |
+
* @var array
|
59 |
+
*/
|
60 |
+
private $insert_ids = array();
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Hard limit for the number of querys we run during a single step.
|
64 |
+
* @var integer
|
65 |
+
*/
|
66 |
+
private $limit = 10;
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Stores information about the current form being processed.
|
70 |
+
* @var array
|
71 |
+
*/
|
72 |
+
private $form;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* The table names for our database queries.
|
76 |
+
*/
|
77 |
+
private $table;
|
78 |
+
private $meta_table;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Constructor
|
82 |
+
*
|
83 |
+
* @param $data (Array) The data object passed in by the AJAX call.
|
84 |
+
* @param $running (Array) The array of required updates being run.
|
85 |
+
*
|
86 |
+
* @since 3.4.0
|
87 |
+
*/
|
88 |
+
public function __construct( $data = array(), $running )
|
89 |
+
{
|
90 |
+
// Build our arguments array.
|
91 |
+
$args = array(
|
92 |
+
'slug' => 'CacheCollateFields',
|
93 |
+
'class_name' => 'NF_Updates_CacheCollateFields',
|
94 |
+
'debug' => false,
|
95 |
+
);
|
96 |
+
$this->data = $data;
|
97 |
+
$this->running = $running;
|
98 |
+
|
99 |
+
// Call the parent constructor.
|
100 |
+
parent::__construct( $args );
|
101 |
+
|
102 |
+
// Set our table names.
|
103 |
+
$this->table = $this->db->prefix . 'nf3_fields';
|
104 |
+
$this->meta_table = $this->db->prefix . 'nf3_field_meta';
|
105 |
+
|
106 |
+
// Begin processing.
|
107 |
+
$this->process();
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Function to loop over the batch.
|
112 |
+
*
|
113 |
+
* @since 3.4.0
|
114 |
+
*/
|
115 |
+
public function process()
|
116 |
+
{
|
117 |
+
// If we've not already started...
|
118 |
+
if ( ! isset( $this->running[ 0 ][ 'running' ] ) ) {
|
119 |
+
// Run our startup method.
|
120 |
+
$this->startup();
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Get all of our database variables up and running.
|
125 |
+
* Sets up class vars that are used in subsequent methods.
|
126 |
+
*/
|
127 |
+
$this->setup_vars();
|
128 |
+
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Run SQL queries to delete fields if necessary.
|
132 |
+
*/
|
133 |
+
$this->maybe_delete_fields();
|
134 |
+
/**
|
135 |
+
* Insert fields if necessary.
|
136 |
+
* Also sets up the class var $submission_updates with duplicate ids that need replaced.
|
137 |
+
*/
|
138 |
+
$this->maybe_insert_fields();
|
139 |
+
/**
|
140 |
+
* Update submission post meta if necessary.
|
141 |
+
* Uses the class var $submission_updates setup in the method above.
|
142 |
+
*/
|
143 |
+
$this->maybe_update_submissions();
|
144 |
+
/**
|
145 |
+
* If we have fields that exist in the DB for a form, update those with cache settings.
|
146 |
+
*/
|
147 |
+
$this->maybe_update_fields();
|
148 |
+
/**
|
149 |
+
* Update our form cache with any field id changes.
|
150 |
+
*/
|
151 |
+
$this->update_form_cache();
|
152 |
+
/**
|
153 |
+
* Saves our current location, along with any processing data we may need for the next step.
|
154 |
+
* If we're done with our step, runs cleanup instead.
|
155 |
+
*/
|
156 |
+
$this->end_of_step();
|
157 |
+
|
158 |
+
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Respond to the AJAX call.
|
162 |
+
*/
|
163 |
+
$this->respond();
|
164 |
+
}
|
165 |
+
|
166 |
+
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Function to run any setup steps necessary to begin processing.
|
170 |
+
*
|
171 |
+
* @since 3.4.0
|
172 |
+
*/
|
173 |
+
public function startup()
|
174 |
+
{
|
175 |
+
// Record that we're processing the update.
|
176 |
+
$this->running[ 0 ][ 'running' ] = true;
|
177 |
+
// If we're not debugging...
|
178 |
+
if ( ! $this->debug ) {
|
179 |
+
// Ensure that our data tables are updated.
|
180 |
+
$this->migrate( 'cache_collate_fields' );
|
181 |
+
}
|
182 |
+
// Get a list of our forms...
|
183 |
+
$sql = "SELECT ID FROM `{$this->db->prefix}nf3_forms`";
|
184 |
+
$forms = $this->db->get_results( $sql, 'ARRAY_A' );
|
185 |
+
$this->running[ 0 ][ 'forms' ] = $forms;
|
186 |
+
// Record the total number of steps in this batch.
|
187 |
+
$this->running[ 0 ][ 'steps' ] = count( $forms );
|
188 |
+
// Record our current step (defaulted to 0 here).
|
189 |
+
$this->running[ 0 ][ 'current' ] = 0;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Function to cleanup any lingering temporary elements of a required update after completion.
|
194 |
+
*
|
195 |
+
* @since 3.4.0
|
196 |
+
*/
|
197 |
+
public function cleanup()
|
198 |
+
{
|
199 |
+
// Remove the current process from the array.
|
200 |
+
array_shift( $this->running );
|
201 |
+
// Record to our updates setting that this update is complete.
|
202 |
+
$this->confirm_complete();
|
203 |
+
// If we have no updates left to process...
|
204 |
+
if ( empty( $this->running ) ) {
|
205 |
+
// Call the parent cleanup method.
|
206 |
+
parent::cleanup();
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Function to delete unncessary items from our existing tables.
|
212 |
+
*
|
213 |
+
* @param $items (Array) The list of ids to be deleted.
|
214 |
+
*
|
215 |
+
* @since 3.4.0
|
216 |
+
*/
|
217 |
+
public function maybe_delete_fields()
|
218 |
+
{
|
219 |
+
if ( empty( $this->delete ) ) {
|
220 |
+
return false;
|
221 |
+
}
|
222 |
+
|
223 |
+
// Delete all meta for those fields.
|
224 |
+
$sql = "DELETE FROM `{$this->meta_table}` WHERE parent_id IN(" . implode( ', ', $this->delete ) . ")";
|
225 |
+
$this->query( $sql );
|
226 |
+
// Delete the fields.
|
227 |
+
$sql = "DELETE FROM `{$this->table}` WHERE id IN(" . implode( ', ', $this->delete ) . ")";
|
228 |
+
$this->query( $sql );
|
229 |
+
|
230 |
+
$this->delete = array();
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Most of the methods in this class use class vars to access and store data.
|
235 |
+
*
|
236 |
+
* This method sets the initial state of these class vars.
|
237 |
+
* Class vars include:
|
238 |
+
* $form <- reference to the form currently being processed.
|
239 |
+
* $field_ids <- non-associatve array of field ids from the cache.
|
240 |
+
* $insert <- array that tracks what we should we insert because it exists in our cache but not in the Fields table.
|
241 |
+
* $submission_updates <- array that tracks fields that have had their id changed.
|
242 |
+
* $fields_by_id <- associative array of field ids from the cache, using the field id as the key.
|
243 |
+
*
|
244 |
+
* If we are not running a form for the first time,
|
245 |
+
* we set class vars based on what we have been passed.
|
246 |
+
* After setting those class vars, we bail early.
|
247 |
+
*
|
248 |
+
* If we are running for the first time, set have to hit the database to
|
249 |
+
* get the information for class vars.
|
250 |
+
*
|
251 |
+
* We need to compare the fields in our form cache to those in the fields table.
|
252 |
+
* Ultimately, we're trying to make sure that our fields table matches our form cache.
|
253 |
+
*
|
254 |
+
* Since we're treating the cache as the truth, we want to remove fields that don't exist in the cache.
|
255 |
+
* We also want to insert any fields that exist in the cache, but not in the fields table.
|
256 |
+
*
|
257 |
+
* This method doesn't perform those operations, but it sets the class vars that the appropriate
|
258 |
+
* methods use to figure out what to add and remove.
|
259 |
+
*
|
260 |
+
* @since 3.4.0
|
261 |
+
* @return void
|
262 |
+
*/
|
263 |
+
private function setup_vars()
|
264 |
+
{
|
265 |
+
// Set the form we're currently working with.
|
266 |
+
$this->form = array_pop( $this->running[ 0 ][ 'forms' ] );
|
267 |
+
// Enable maintenance mode on the front end when the fields start processing.
|
268 |
+
$this->enable_maintenance_mode( $this->db->prefix, $this->form[ 'ID' ] );
|
269 |
+
|
270 |
+
// Get the fields for our form from the cache.
|
271 |
+
$form_cache = WPN_Helper::get_nf_cache( $this->form[ 'ID' ] );
|
272 |
+
// Create an empty $fields array.
|
273 |
+
$fields = array();
|
274 |
+
/**
|
275 |
+
* Loop over our cached form fields and instantiate a model for each.
|
276 |
+
* Update its settings to match those in the cache.
|
277 |
+
* Add it to our $fields array.
|
278 |
+
*/
|
279 |
+
foreach( $form_cache[ 'fields' ] as $cached_field ){
|
280 |
+
// Create a new model for this field.
|
281 |
+
$field = new NF_Database_Models_Field( $this->db, $cached_field[ 'id' ], $this->form[ 'ID' ] );
|
282 |
+
// Update settings to match cache.
|
283 |
+
$field->update_settings( $cached_field[ 'settings' ] );
|
284 |
+
// Add this to our $fields array, using the field id as the key.
|
285 |
+
$fields[ $field->get_id() ] = $field;
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* For each field in our cache, add it to our class vars:
|
290 |
+
* field_ids <- non-associatve array of field ids from the cache.
|
291 |
+
* fields_by_id <- associative array of field ids from the cache, using the field id as the key.
|
292 |
+
*/
|
293 |
+
foreach ( $fields as $field ) {
|
294 |
+
array_push( $this->field_ids, $field->get_id() );
|
295 |
+
$this->fields_by_id[ $field->get_id() ] = $field->get_settings();
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* If we're continuing a process, set our class vars appropriately.
|
300 |
+
* Bail early so that nothing else fires.
|
301 |
+
*/
|
302 |
+
if ( isset( $this->form[ 'field_ids' ] ) ) {
|
303 |
+
$this->field_ids = $this->form[ 'field_ids' ];
|
304 |
+
$this->insert = $this->form[ 'insert' ];
|
305 |
+
$this->submission_updates = $this->form[ 'submission_updates' ];
|
306 |
+
return false;
|
307 |
+
}
|
308 |
+
/**
|
309 |
+
* We need to cross reference the Fields table to see if these ids exist for this form.
|
310 |
+
* If they exist in the table, we don't need to insert them.
|
311 |
+
*/
|
312 |
+
$sql = "SELECT id FROM `{$this->table}` WHERE parent_id = {$this->form[ 'ID' ]}";
|
313 |
+
$db_fields = $this->db->get_results( $sql, 'ARRAY_A' );
|
314 |
+
$db_field_ids = array();
|
315 |
+
/**
|
316 |
+
* Loop over every field that exists in the table:
|
317 |
+
* If it doesn't exist in the cache, add it to our delete class var so that it is deleted later.
|
318 |
+
* If it does exist in both, add it to our $db_field_ids array for later comparison.
|
319 |
+
*/
|
320 |
+
foreach ( $db_fields as $field ) {
|
321 |
+
// If we have no reference to it in the cache...
|
322 |
+
if ( ! in_array( $field[ 'id' ], $this->field_ids ) ) {
|
323 |
+
// Schedule it for deletion.
|
324 |
+
array_push( $this->delete, $field[ 'id' ] );
|
325 |
+
} else { // Push the id onto our comparison array.
|
326 |
+
array_push( $db_field_ids, $field[ 'id' ] );
|
327 |
+
}
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* Loop over every field that exists in our form cache to see if we need to insert it.
|
332 |
+
*/
|
333 |
+
foreach ( $this->field_ids as $field ) {
|
334 |
+
// If we have no reference to it in the fields table...
|
335 |
+
if ( ! in_array( $field, $db_field_ids ) ) {
|
336 |
+
// Schedule it for insertion.
|
337 |
+
array_push( $this->insert, $field );
|
338 |
+
}
|
339 |
+
}
|
340 |
+
/**
|
341 |
+
* Cross reference the Fields table to see if these ids exist on other Forms.
|
342 |
+
* If an id exists on another form, then we need to change the current field's id and add that field to our submission_updates class var.
|
343 |
+
*/
|
344 |
+
if ( ! empty( $this->field_ids ) ) {
|
345 |
+
$sql = "SELECT id FROM `{$this->table}` WHERE id IN(" . implode( ', ', $this->field_ids ) . ") AND parent_id <> {$this->form[ 'ID' ]}";
|
346 |
+
$duplicates = $this->db->get_results( $sql, 'ARRAY_A' );
|
347 |
+
} else {
|
348 |
+
$duplicates = array();
|
349 |
+
}
|
350 |
+
/**
|
351 |
+
* If we got something back, there were duplicates.
|
352 |
+
*/
|
353 |
+
if ( ! empty( $duplicates ) ) {
|
354 |
+
/**
|
355 |
+
* Loop over our duplicates and add it to our insert class var if it isn't already there.
|
356 |
+
* Also, add this field to our submission_updates class var so that we can handle the id change later.
|
357 |
+
*/
|
358 |
+
foreach ( $duplicates as $duplicate ) {
|
359 |
+
if ( ! in_array( $duplicate[ 'id' ], $this->insert ) ) {
|
360 |
+
array_push( $this->insert, $duplicate[ 'id' ] );
|
361 |
+
}
|
362 |
+
|
363 |
+
$this->submission_updates[ $duplicate[ 'id' ] ] = true;
|
364 |
+
}
|
365 |
+
}
|
366 |
+
}
|
367 |
+
|
368 |
+
/**
|
369 |
+
* Our setup_vars method adds fields to the insert class var.
|
370 |
+
* Any fields that are in this array need to be inserted into our database.
|
371 |
+
*
|
372 |
+
* This is the first insert/update method to run, so it doesn't check lock_process.
|
373 |
+
* If the insert class var is empty, then we bail early.
|
374 |
+
*
|
375 |
+
* @since 3.4.0
|
376 |
+
* @return void
|
377 |
+
*/
|
378 |
+
private function maybe_insert_fields()
|
379 |
+
{
|
380 |
+
// If we don't have any items to insert, bail early.
|
381 |
+
if ( empty( $this->insert ) ) {
|
382 |
+
return false;
|
383 |
+
}
|
384 |
+
|
385 |
+
// Store the meta items outside the loop for faster insertion.
|
386 |
+
$meta_items = array();
|
387 |
+
$flush_ids = array();
|
388 |
+
// While we still have items to insert...
|
389 |
+
while ( 0 < count( $this->insert ) ) {
|
390 |
+
// If we have hit our limit...
|
391 |
+
if ( 1 > $this->limit ) {
|
392 |
+
// Lock processing.
|
393 |
+
$this->lock_process = true;
|
394 |
+
// Exit the loop.
|
395 |
+
break;
|
396 |
+
}
|
397 |
+
// Get our item to be inserted.
|
398 |
+
$inserting = array_pop( $this->insert );
|
399 |
+
$settings = $this->fields_by_id[ $inserting ];
|
400 |
+
|
401 |
+
/*
|
402 |
+
* We want to preserve the field ids from the cache if we can.
|
403 |
+
* To do this, we check our $this->submission_updates array for this current field.
|
404 |
+
* If it doesn't exist in the array, we can trust the cached field id.
|
405 |
+
* If it exists in that array, then this is a duplicate.
|
406 |
+
*/
|
407 |
+
if ( ! isset( $this->submission_updates[ $inserting ] ) ) {
|
408 |
+
$maybe_field_id = intval( $inserting ); // Use the cached field id.
|
409 |
+
} else {
|
410 |
+
$maybe_field_id = 'NULL'; // Setting 'NULL' uses SQL auto-increment.
|
411 |
+
}
|
412 |
+
|
413 |
+
// Insert into the fields table.
|
414 |
+
$sql = "INSERT INTO `{$this->table}` ( `id`, label, `key`, `type`, parent_id, field_label, field_key, `order`, required, default_value, label_pos, personally_identifiable ) VALUES ( " .
|
415 |
+
$maybe_field_id . ", '" .
|
416 |
+
$this->prepare( $settings[ 'label' ] ) . "', '".
|
417 |
+
$this->prepare( $settings[ 'key' ] ) . "', '" .
|
418 |
+
$this->prepare( $settings[ 'type' ] ) . "', " .
|
419 |
+
intval( $this->form[ 'ID' ] ) . ", '" .
|
420 |
+
$this->prepare( $settings[ 'label' ] ) . "', '" .
|
421 |
+
$this->prepare( $settings[ 'key' ] ) . "', " .
|
422 |
+
intval( $settings[ 'order' ] ) . ", " .
|
423 |
+
intval( $settings[ 'required' ] ) . ", '" .
|
424 |
+
$this->prepare( $settings[ 'default_value' ] ) . "', '" .
|
425 |
+
$this->prepare( $settings[ 'label_pos' ] ) . "', " .
|
426 |
+
intval( $settings[ 'personally_identifiable' ] ) . " )";
|
427 |
+
|
428 |
+
$this->query( $sql );
|
429 |
+
|
430 |
+
// Set a default new_id for debugging.
|
431 |
+
$new_id = 0;
|
432 |
+
// If we're not in debug mode...
|
433 |
+
if ( ! $this->debug ) {
|
434 |
+
// Get the ID of the new field.
|
435 |
+
$new_id = $this->db->insert_id;
|
436 |
+
$settings[ 'old_field_id' ] = $inserting;
|
437 |
+
}
|
438 |
+
// Save a reference to this insertion.
|
439 |
+
$this->insert_ids[ $inserting ] = $new_id;
|
440 |
+
|
441 |
+
// Update our submission_updates array with the new ID of this field so that we can use it later.
|
442 |
+
if ( isset ( $this->submission_updates[ $inserting ] ) ) {
|
443 |
+
$this->submission_updates[ $inserting ] = $new_id;
|
444 |
+
}
|
445 |
+
|
446 |
+
// Push the new ID onto our list of IDs to flush.
|
447 |
+
array_push( $flush_ids, $new_id );
|
448 |
+
|
449 |
+
// For each meta of the field...
|
450 |
+
foreach ( $settings as $meta => $value ) {
|
451 |
+
// If it's not empty...
|
452 |
+
if ( ( ! empty( $value ) || '0' == $value ) ) {
|
453 |
+
// Add the data to the list.
|
454 |
+
array_push( $meta_items, "( " . intval( $new_id ) . ", '" . $meta . "', '" . $this->prepare( $value ) . "', '" . $meta . "', '" . $this->prepare( $value ) . "' )" );
|
455 |
+
}
|
456 |
+
}
|
457 |
+
// Remove the item from the list of fields.
|
458 |
+
unset( $this->fields_by_id[ $inserting ] );
|
459 |
+
$field_index = array_search( $inserting, $this->field_ids );
|
460 |
+
unset( $this->field_ids[ $field_index ] );
|
461 |
+
// Reduce the limit.
|
462 |
+
$this->limit--;
|
463 |
+
}
|
464 |
+
|
465 |
+
if ( ! empty ( $flush_ids ) ) {
|
466 |
+
// Flush our existing meta.
|
467 |
+
$sql = "DELETE FROM `{$this->meta_table}` WHERE parent_id IN(" . implode( ', ', $flush_ids ) . ")";
|
468 |
+
$this->query( $sql );
|
469 |
+
}
|
470 |
+
|
471 |
+
// Insert our meta.
|
472 |
+
$sql = "INSERT INTO `{$this->meta_table}` ( parent_id, `key`, value, meta_key, meta_value ) VALUES " . implode( ', ', $meta_items );
|
473 |
+
$this->query( $sql );
|
474 |
+
}
|
475 |
+
|
476 |
+
/**
|
477 |
+
* If we have any duplicate field ids, we need to update any existing submissions with the new field ID.
|
478 |
+
*
|
479 |
+
* The $this->submission_updates array will look like:
|
480 |
+
*
|
481 |
+
* $this->submission_updates[ original_id ] = new_id;
|
482 |
+
*
|
483 |
+
* This method:
|
484 |
+
* Checks to see if we have any fields in our $this->submission_updates array (have a changed ID)
|
485 |
+
* Makes sure that processing isn't locked
|
486 |
+
* Loops over fields in our $this->submission_updates array
|
487 |
+
* Fetches submission post meta for the specific form ID and _field_OLDID
|
488 |
+
* Uses a SQL UPDATE statement to replace _field_OLDID with _field_NEWID
|
489 |
+
*
|
490 |
+
* @since 3.4.0
|
491 |
+
* @return void
|
492 |
+
*/
|
493 |
+
private function maybe_update_submissions()
|
494 |
+
{
|
495 |
+
// If we don't have any submissions to update OR the lock_process is true, bail early.
|
496 |
+
if ( empty ( $this->submission_updates ) || $this->lock_process ) {
|
497 |
+
return false;
|
498 |
+
}
|
499 |
+
|
500 |
+
/*
|
501 |
+
* Keep track of old field ids we've used.
|
502 |
+
* Initially, we set our record array to our current submission updates array.
|
503 |
+
* When we finish updating an old field, we remove it from the record array.
|
504 |
+
* When we're done with all fields, we set the submission updates array to the record array.
|
505 |
+
*/
|
506 |
+
$submission_updates_record = $this->submission_updates;
|
507 |
+
// Meta key update limit; How many meta keys do we want to update at a time?
|
508 |
+
$meta_key_limit = 200;
|
509 |
+
// Loop through submission updates and query the postmeta table for any meta_key values of _field_{old_id}.
|
510 |
+
foreach ( $this->submission_updates as $old_id => $new_id ) {
|
511 |
+
// Make sure that we haven't reached our query limit.
|
512 |
+
if ( 1 > $this->limit ) {
|
513 |
+
// Lock processing.
|
514 |
+
$this->lock_process = true;
|
515 |
+
// Exit the loop.
|
516 |
+
break;
|
517 |
+
}
|
518 |
+
|
519 |
+
// This sql is designed to grab our old _field_X post meta keys so that we can replace them with new _field_X meta keys.
|
520 |
+
$sql = "SELECT
|
521 |
+
old_field_id.meta_id
|
522 |
+
FROM
|
523 |
+
`{$this->db->prefix}posts` p
|
524 |
+
INNER JOIN `{$this->db->prefix}postmeta` old_field_id ON old_field_id.post_id = p.ID
|
525 |
+
AND old_field_id.meta_key = '_field_{$old_id}'
|
526 |
+
INNER JOIN `{$this->db->prefix}postmeta` form_id ON form_id.post_id = p.ID
|
527 |
+
AND form_id.meta_key = '_form_id'
|
528 |
+
|
529 |
+
WHERE old_field_id.meta_key = '_field_{$old_id}'
|
530 |
+
AND form_id.meta_value = {$this->form[ 'ID' ]}
|
531 |
+
AND p.post_type = 'nf_sub'
|
532 |
+
LIMIT {$meta_key_limit}";
|
533 |
+
// Fetch our sql results.
|
534 |
+
$meta_ids = $this->db->get_results( $sql, 'ARRAY_N' );
|
535 |
+
if ( ! empty( $meta_ids ) ) {
|
536 |
+
// Implode our meta ids so that we can use the result in our update sql.
|
537 |
+
$imploded_ids = implode( ',', call_user_func_array( 'array_merge', $meta_ids ) );
|
538 |
+
// Update all our fetched meta ids with the new _field_ meta key.
|
539 |
+
$sql = "UPDATE `{$this->db->prefix}postmeta`
|
540 |
+
SET meta_key = '_field_{$new_id}'
|
541 |
+
WHERE meta_id IN ( {$imploded_ids} )";
|
542 |
+
|
543 |
+
$this->query( $sql );
|
544 |
+
}
|
545 |
+
|
546 |
+
/*
|
547 |
+
* Let's make sure that we're done processing all post meta for this old field ID.
|
548 |
+
*
|
549 |
+
* If the number of meta rows retrieved equals our limit:
|
550 |
+
* lock processing
|
551 |
+
* break out of this loop
|
552 |
+
* Else
|
553 |
+
* we're done with this old field, remove it from our list
|
554 |
+
* subtract from our $this->limit var
|
555 |
+
*/
|
556 |
+
if ( $meta_key_limit === count( $meta_ids ) ) {
|
557 |
+
// Keep anything else from processing.
|
558 |
+
$this->lock_process = true;
|
559 |
+
// Exit this foreach loop.
|
560 |
+
break;
|
561 |
+
} else { // We're done with this old field.
|
562 |
+
// Remove the field ID from our submission array.
|
563 |
+
unset( $submission_updates_record[ $old_id ] );
|
564 |
+
// Decrement our query limit.
|
565 |
+
$this->limit--;
|
566 |
+
}
|
567 |
+
|
568 |
+
} // End foreach
|
569 |
+
// Set our submission updates array to our record array so that we remove any completed old ids.
|
570 |
+
$this->submission_updates = $submission_updates_record;
|
571 |
+
}
|
572 |
+
|
573 |
+
/**
|
574 |
+
* If we still have field_ids in our class var, then we need to update the field table.
|
575 |
+
*
|
576 |
+
* If lock_process is true or we have no field_ids, we bail early.
|
577 |
+
*
|
578 |
+
* @since 3.4.0
|
579 |
+
* @return void
|
580 |
+
*/
|
581 |
+
private function maybe_update_fields()
|
582 |
+
{
|
583 |
+
// If we have no fields to insert OR lock_process is true, bail early.
|
584 |
+
if ( empty ( $this->field_ids ) || $this->lock_process ) {
|
585 |
+
return false;
|
586 |
+
}
|
587 |
+
|
588 |
+
// Store the meta items outside the loop for faster insertion.
|
589 |
+
$meta_items = array();
|
590 |
+
$flush_ids = array();
|
591 |
+
// While we still have items to update...
|
592 |
+
while ( 0 < count( $this->field_ids ) ) {
|
593 |
+
// If we have hit our limit...
|
594 |
+
if ( 1 > $this->limit ) {
|
595 |
+
// Lock processing.
|
596 |
+
$this->lock_process = true;
|
597 |
+
// Exit the loop.
|
598 |
+
break;
|
599 |
+
}
|
600 |
+
// Get our item to be updated.
|
601 |
+
$updating = array_pop( $this->field_ids );
|
602 |
+
array_push( $flush_ids, $updating );
|
603 |
+
$settings = $this->fields_by_id[ $updating ];
|
604 |
+
// Update the fields table.
|
605 |
+
$sql = "UPDATE `{$this->table}` SET label = '"
|
606 |
+
. $this->prepare( $settings[ 'label' ] )
|
607 |
+
. "', `key` = '" . $this->prepare( $settings[ 'key' ] )
|
608 |
+
. "', `type` = '" . $this->prepare( $settings[ 'type' ] )
|
609 |
+
. "', field_label = '" . $this->prepare( $settings[ 'label' ] )
|
610 |
+
. "', field_key = '" . $this->prepare( $settings[ 'key' ] )
|
611 |
+
. "', `order` = " . intval( $settings[ 'order' ] )
|
612 |
+
. ", required = " . intval( $settings[ 'required' ] )
|
613 |
+
. ", default_value = '" . $this->prepare( $settings[ 'default_value' ] )
|
614 |
+
. "', label_pos = '" . $this->prepare( $settings[ 'label_pos' ] )
|
615 |
+
. "', personally_identifiable = " . intval( $settings[ 'personally_identifiable' ] )
|
616 |
+
. " WHERE id = " . intval( $updating );
|
617 |
+
$this->query( $sql );
|
618 |
+
// For each meta of the field...
|
619 |
+
foreach ( $settings as $meta => $value ) {
|
620 |
+
// If it's not empty...
|
621 |
+
if ( ( ! empty( $value ) || '0' == $value ) ) {
|
622 |
+
// Add the data to the list.
|
623 |
+
array_push( $meta_items, "( " . intval( $updating ) . ", '" . $meta . "', '" . $this->prepare( $value ) . "', '" . $meta . "', '" . $this->prepare( $value ) . "' )" );
|
624 |
+
}
|
625 |
+
}
|
626 |
+
// Remove the item from the list of fields.
|
627 |
+
unset( $this->fields_by_id[ $updating ] );
|
628 |
+
// Reduce the limit.
|
629 |
+
$this->limit--;
|
630 |
+
}
|
631 |
+
if ( ! empty ( $flush_ids ) ) {
|
632 |
+
// Flush our existing meta.
|
633 |
+
$sql = "DELETE FROM `{$this->meta_table}` WHERE parent_id IN(" . implode( ', ', $flush_ids ) . ")";
|
634 |
+
$this->query( $sql );
|
635 |
+
}
|
636 |
+
|
637 |
+
// Insert our updated meta.
|
638 |
+
$sql = "INSERT INTO `{$this->meta_table}` ( parent_id, `key`, value, meta_key, meta_value ) VALUES " . implode( ', ', $meta_items );
|
639 |
+
$this->query( $sql );
|
640 |
+
}
|
641 |
+
|
642 |
+
/**
|
643 |
+
* If we've inserted any fields that have changed ids, we want to update those ids in our cache.
|
644 |
+
* This method grabs the cache, updates any field ids, then updates the cache.
|
645 |
+
*
|
646 |
+
* @since 3.4.0
|
647 |
+
* @return void
|
648 |
+
*/
|
649 |
+
private function update_form_cache()
|
650 |
+
{
|
651 |
+
// Get a copy of the cache.
|
652 |
+
$cache = WPN_Helper::get_nf_cache($this->form[ 'ID' ] );
|
653 |
+
// For each field in the cache...
|
654 |
+
foreach( $cache[ 'fields' ] as &$field ) {
|
655 |
+
// If we have a new ID for this field...
|
656 |
+
if ( isset( $this->insert_ids[ $field[ 'id' ] ] ) ) {
|
657 |
+
// Update it.
|
658 |
+
$field[ 'id' ] = intval( $this->insert_ids[ $field[ 'id' ] ] );
|
659 |
+
}
|
660 |
+
// TODO: Might also need to append some new settings here (Label)?
|
661 |
+
}
|
662 |
+
// Save the cache, passing 3 as the current stage.
|
663 |
+
WPN_Helper::update_nf_cache( $this->form[ 'ID' ], $cache, 3 );
|
664 |
+
}
|
665 |
+
|
666 |
+
/**
|
667 |
+
* After we've done our processing, but before we get to step cleanup, we need to store process information.
|
668 |
+
*
|
669 |
+
* This method updates our form class var so that it can be passed to the next step.
|
670 |
+
* If we've completed this step, it calls the cleanup method.
|
671 |
+
*
|
672 |
+
* @since 3.4.0
|
673 |
+
* @return void
|
674 |
+
*/
|
675 |
+
private function end_of_step()
|
676 |
+
{
|
677 |
+
// If we have locked processing...
|
678 |
+
if ( $this->lock_process ) {
|
679 |
+
// If we're continuing a process...
|
680 |
+
if ( isset( $this->form[ 'field_ids' ] ) ) {
|
681 |
+
// Reset the field_ids array.
|
682 |
+
$this->field_ids = array();
|
683 |
+
// For each field left to process...
|
684 |
+
foreach ( $this->fields_by_id as $id => $field ) {
|
685 |
+
// If we've not already processed this field...
|
686 |
+
if ( in_array( $id, $this->form[ 'field_ids' ] ) ) {
|
687 |
+
// Save a reference to its ID.
|
688 |
+
array_push( $this->field_ids, $id );
|
689 |
+
}
|
690 |
+
}
|
691 |
+
}
|
692 |
+
// Store our current data location.
|
693 |
+
$this->form[ 'insert' ] = $this->insert;
|
694 |
+
$this->form[ 'field_ids' ] = $this->field_ids;
|
695 |
+
$this->form[ 'submission_updates' ] = $this->submission_updates;
|
696 |
+
array_push( $this->running[ 0 ][ 'forms' ], $this->form );
|
697 |
+
} else { // Otherwise... (The step is complete.)
|
698 |
+
// Increment our step count.
|
699 |
+
$this->running[ 0 ][ 'current' ] = intval( $this->running[ 0 ][ 'current' ] ) + 1;
|
700 |
+
// Disable maintenance mode on the front end of the site.
|
701 |
+
$this->disable_maintenance_mode( $this->db->prefix, $this->form[ 'ID' ] );
|
702 |
+
}
|
703 |
+
|
704 |
+
// Prepare to output our number of steps and current step.
|
705 |
+
$this->response[ 'stepsTotal' ] = $this->running[ 0 ][ 'steps' ];
|
706 |
+
$this->response[ 'currentStep' ] = $this->running[ 0 ][ 'current' ];
|
707 |
+
|
708 |
+
// If all steps have been completed...
|
709 |
+
if ( empty( $this->running[ 0 ][ 'forms' ] ) ) {
|
710 |
+
// Run our cleanup method.
|
711 |
+
$this->cleanup();
|
712 |
+
}
|
713 |
+
|
714 |
+
// Record our current location in the process.
|
715 |
+
update_option( 'ninja_forms_doing_required_updates', $this->running );
|
716 |
+
// Prepare to output the number of updates remaining.
|
717 |
+
$this->response[ 'updatesRemaining' ] = count( $this->running );
|
718 |
+
}
|
719 |
+
|
720 |
+
}
|
includes/Updates/CacheCollateForms.php
ADDED
@@ -0,0 +1,243 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class NF_Updates_CacheCollateForms
|
5 |
+
*
|
6 |
+
* This class manages the step process of running through the CacheCollateForms required update.
|
7 |
+
* It will define an object to pull data from (if necessary) to pick back up if exited early.
|
8 |
+
* It will run an upgrade function to alter the nf3_forms and nf3_form_meta tables.
|
9 |
+
* Then, it will step over each form on the site, following this process:
|
10 |
+
* - New columns in the nf3_forms table will be populated with data from the cache.
|
11 |
+
* - New and existing columns in the nf3_form_meta tables will be populated from the cache.
|
12 |
+
* - A new record of the cache will be saved to the nf3_upgrades table (if it does not already exist).
|
13 |
+
* After completing the above for every form on the site, it will remove the data object that manages its location.
|
14 |
+
*/
|
15 |
+
class NF_Updates_CacheCollateForms extends NF_Abstracts_RequiredUpdate
|
16 |
+
{
|
17 |
+
|
18 |
+
private $data = array();
|
19 |
+
|
20 |
+
private $running = array();
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Stores information about the current form being processed.
|
24 |
+
* @var array
|
25 |
+
*/
|
26 |
+
private $form;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Declare a blacklist for settings to not be inserted.
|
30 |
+
* @var array
|
31 |
+
*/
|
32 |
+
private $blacklist = array(
|
33 |
+
'title',
|
34 |
+
'objectType',
|
35 |
+
'editActive',
|
36 |
+
);
|
37 |
+
|
38 |
+
/**
|
39 |
+
* The table names for our database queries.
|
40 |
+
*/
|
41 |
+
private $table;
|
42 |
+
private $meta_table;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Constructor
|
46 |
+
*
|
47 |
+
* @param $data (Array) The data object passed in by the AJAX call.
|
48 |
+
* @param $running (Array) The array of required updates being run.
|
49 |
+
*
|
50 |
+
* @since 3.4.0
|
51 |
+
*/
|
52 |
+
public function __construct( $data = array(), $running )
|
53 |
+
{
|
54 |
+
// Build our arguments array.
|
55 |
+
$args = array(
|
56 |
+
'slug' => 'CacheCollateForms',
|
57 |
+
'class_name' => 'NF_Updates_CacheCollateForms',
|
58 |
+
'debug' => false,
|
59 |
+
);
|
60 |
+
$this->data = $data;
|
61 |
+
$this->running = $running;
|
62 |
+
|
63 |
+
// Call the parent constructor.
|
64 |
+
parent::__construct( $args );
|
65 |
+
|
66 |
+
// Set our table names.
|
67 |
+
$this->table = $this->db->prefix . 'nf3_forms';
|
68 |
+
$this->meta_table = $this->db->prefix . 'nf3_form_meta';
|
69 |
+
|
70 |
+
// Begin processing.
|
71 |
+
$this->process();
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Function to loop over the batch.
|
76 |
+
*
|
77 |
+
* @since 3.4.0
|
78 |
+
*/
|
79 |
+
public function process()
|
80 |
+
{
|
81 |
+
// If we've not already started...
|
82 |
+
if ( ! isset( $this->running[ 0 ][ 'running' ] ) ) {
|
83 |
+
// Run our startup method.
|
84 |
+
$this->startup();
|
85 |
+
}
|
86 |
+
|
87 |
+
// See which form we're currently working with.
|
88 |
+
$this->form = array_pop( $this->running[ 0 ][ 'forms' ] );
|
89 |
+
|
90 |
+
/**
|
91 |
+
* If we don't have a cache for this form, we need to add one for later processing.
|
92 |
+
* We're going to check that the cache exists and create one if we don't have one.
|
93 |
+
*/
|
94 |
+
$cache = WPN_Helper::get_nf_cache( $this->form[ 'ID' ] );
|
95 |
+
|
96 |
+
if ( empty ( $cache ) ) { // No cache exists.
|
97 |
+
// Call our build_nf_cache static method.
|
98 |
+
$form_cache = WPN_Helper::build_nf_cache( $this->form[ 'ID' ] );
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Update our form table with the appropriate form settings.
|
103 |
+
*/
|
104 |
+
$this->update_form();
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Check to see if we're done with processing this form and prepare to respond.
|
108 |
+
*/
|
109 |
+
$this->end_of_step();
|
110 |
+
|
111 |
+
// Respond to the AJAX call.
|
112 |
+
$this->respond();
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Function to run any setup steps necessary to begin processing.
|
117 |
+
*
|
118 |
+
* @since 3.4.0
|
119 |
+
*/
|
120 |
+
public function startup()
|
121 |
+
{
|
122 |
+
// Record that we're processing the update.
|
123 |
+
$this->running[ 0 ][ 'running' ] = true;
|
124 |
+
// If we're not debugging...
|
125 |
+
if ( ! $this->debug ) {
|
126 |
+
// Ensure that our data tables are updated.
|
127 |
+
$this->migrate( 'cache_collate_forms' );
|
128 |
+
}
|
129 |
+
// Get a list of our forms...
|
130 |
+
$sql = "SELECT ID FROM `{$this->table}`";
|
131 |
+
$forms = $this->db->get_results( $sql, 'ARRAY_A' );
|
132 |
+
$this->running[ 0 ][ 'forms' ] = $forms;
|
133 |
+
// Record the total number of steps in this batch.
|
134 |
+
$this->running[ 0 ][ 'steps' ] = count( $forms );
|
135 |
+
// Record our current step (defaulted to 0 here).
|
136 |
+
$this->running[ 0 ][ 'current' ] = 0;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Function to cleanup any lingering temporary elements of a required update after completion.
|
141 |
+
*
|
142 |
+
* @since 3.4.0
|
143 |
+
*/
|
144 |
+
public function cleanup()
|
145 |
+
{
|
146 |
+
// Remove the current process from the array.
|
147 |
+
array_shift( $this->running );
|
148 |
+
// Record to our updates setting that this update is complete.
|
149 |
+
$this->confirm_complete();
|
150 |
+
// If we have no updates left to process...
|
151 |
+
if ( empty( $this->running ) ) {
|
152 |
+
// Call the parent cleanup method.
|
153 |
+
parent::cleanup();
|
154 |
+
}
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
*
|
159 |
+
* @since 3.4.0
|
160 |
+
* @return void
|
161 |
+
*/
|
162 |
+
private function end_of_step()
|
163 |
+
{
|
164 |
+
// Update the upgrades table, passing in 1 for the current stage.
|
165 |
+
$cache = WPN_Helper::get_nf_cache( $this->form[ 'ID' ] );
|
166 |
+
WPN_Helper::update_nf_cache( $this->form[ 'ID' ], $cache, 1 );
|
167 |
+
|
168 |
+
// Increment our step count.
|
169 |
+
$this->running[ 0 ][ 'current' ] = intval( $this->running[ 0 ][ 'current' ] ) + 1;
|
170 |
+
|
171 |
+
// Prepare to output our number of steps and current step.
|
172 |
+
$this->response[ 'stepsTotal' ] = $this->running[ 0 ][ 'steps' ];
|
173 |
+
$this->response[ 'currentStep' ] = $this->running[ 0 ][ 'current' ];
|
174 |
+
|
175 |
+
// If all steps have been completed...
|
176 |
+
if ( empty( $this->running[ 0 ][ 'forms' ] ) ) {
|
177 |
+
// Run our cleanup method.
|
178 |
+
$this->cleanup();
|
179 |
+
}
|
180 |
+
|
181 |
+
// Record our current location in the process.
|
182 |
+
update_option( 'ninja_forms_doing_required_updates', $this->running );
|
183 |
+
// Prepare to output the number of updates remaining.
|
184 |
+
$this->response[ 'updatesRemaining' ] = count( $this->running );
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Update our form table for the current form.
|
189 |
+
* We have new table columns, so we want to make sure that those are populated properly.
|
190 |
+
*
|
191 |
+
* Also checks meta values against our $this->blacklist.
|
192 |
+
*
|
193 |
+
* @since 3.4.0
|
194 |
+
* @return [type] [description]
|
195 |
+
*/
|
196 |
+
private function update_form()
|
197 |
+
{
|
198 |
+
// Get the settings for that form.
|
199 |
+
$settings = Ninja_Forms()->form( $this->form[ 'ID' ] )->get()->get_settings();
|
200 |
+
|
201 |
+
// Get our seq_number from meta.
|
202 |
+
$sql = "SELECT `value` FROM `{$this->meta_table}` WHERE `key` = '_seq_num' AND `parent_id` = " . intval( $this->form[ 'ID' ] );
|
203 |
+
$result = $this->db->query( $sql, 'ARRAY_A' );
|
204 |
+
// Default to 1.
|
205 |
+
$seq_num = 1;
|
206 |
+
if ( ! empty( $result[ 0 ][ 'value' ] ) ) {
|
207 |
+
// If we got back something, set it to the proper value.
|
208 |
+
$seq_num = intval( $result[ 0 ][ 'value' ] );
|
209 |
+
}
|
210 |
+
|
211 |
+
// If logged in is false...
|
212 |
+
if ( ! $settings[ 'logged_in' ] || 'false' === $settings[ 'logged_in' ] ) {
|
213 |
+
$logged_in = 0;
|
214 |
+
} // Otherwise... (logged in is true.)
|
215 |
+
else {
|
216 |
+
$logged_in = 1;
|
217 |
+
}
|
218 |
+
|
219 |
+
// Save the new columns to the forms table.
|
220 |
+
$sql = "UPDATE `{$this->table}` SET form_title = '" . $this->prepare( $settings[ 'title' ] ) . "', default_label_pos = '" . $settings[ 'default_label_pos' ] . "', show_title = " . intval( $settings[ 'show_title' ] ) . ", clear_complete = " . intval( $settings[ 'clear_complete' ] ) . ", hide_complete = " . intval( $settings[ 'hide_complete' ] ) . ", logged_in = {$logged_in}, seq_num = {$seq_num} WHERE id = " . intval( $this->form[ 'ID' ] ) . ";";
|
221 |
+
$this->query( $sql );
|
222 |
+
|
223 |
+
// Remove the existing meta from the form_meta table.
|
224 |
+
$sql = "DELETE FROM `{$this->meta_table}` WHERE parent_id = " . intval( $this->form[ 'ID' ] );
|
225 |
+
$this->query( $sql );
|
226 |
+
|
227 |
+
$insert_items = array();
|
228 |
+
// Add _seq_num since it's protected and won't be a setting.
|
229 |
+
array_push( $insert_items, "( " . intval( $this->form[ 'ID' ] ) . ", '_seq_num', '{$seq_num}', '_seq_num', '{$seq_num}' )" );
|
230 |
+
// For each form setting...
|
231 |
+
foreach ( $settings as $key => $setting ) {
|
232 |
+
// If it's not a restricted setting...
|
233 |
+
if ( ! in_array( $key, $this->blacklist ) ) {
|
234 |
+
// Add it to the stack.
|
235 |
+
array_push( $insert_items, "( " . intval( $this->form[ 'ID' ] ) . ", '{$key}', '" . $this->prepare( $setting ) . "', '{$key}', '" . $this->prepare( $setting ) . "' )" );
|
236 |
+
}
|
237 |
+
}
|
238 |
+
// Insert the new meta values.
|
239 |
+
$sql = "INSERT INTO `{$this->meta_table}` ( parent_id, `key`, `value`, meta_key, meta_value ) VALUES " . implode( ', ', $insert_items );
|
240 |
+
$this->query( $sql );
|
241 |
+
}
|
242 |
+
|
243 |
+
}
|
includes/Updates/CacheCollateObjects.php
ADDED
@@ -0,0 +1,298 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class NF_Updates_CacheCollateForms
|
5 |
+
*
|
6 |
+
* This class manages the step process of running through the CacheCollateObjects required update.
|
7 |
+
* It will define an object to pull data from (if necessary) to pick back up if exited early.
|
8 |
+
* It will run an upgrade function to alter the nf3_objects and nf3_object_meta tables.
|
9 |
+
* Then, it will step over each object in the db, following this process:
|
10 |
+
* - Append the object_title
|
11 |
+
* Then, it will step over each object_meta in the db, following this process:
|
12 |
+
* - Copy over the meta_key
|
13 |
+
* - Append the meta_value
|
14 |
+
* After completing the above for every form on the site, it will remove the data object that manages its location.
|
15 |
+
*/
|
16 |
+
class NF_Updates_CacheCollateObjects extends NF_Abstracts_RequiredUpdate
|
17 |
+
{
|
18 |
+
|
19 |
+
private $data = array();
|
20 |
+
|
21 |
+
private $running = array();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* The table names for our database queries.
|
25 |
+
*/
|
26 |
+
private $table;
|
27 |
+
private $meta_table;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* The row counts of our database tables.
|
31 |
+
*/
|
32 |
+
private $table_rows = 0;
|
33 |
+
private $meta_rows = 0;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* The denominator object for calculating our steps.
|
37 |
+
* @var Integer
|
38 |
+
*/
|
39 |
+
private $divisor = 500;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Constructor
|
43 |
+
*
|
44 |
+
* @param $data (Array) The data object passed in by the AJAX call.
|
45 |
+
* @param $running (Array) The array of required updates being run.
|
46 |
+
*
|
47 |
+
* @since 3.4.0
|
48 |
+
*/
|
49 |
+
public function __construct( $data = array(), $running )
|
50 |
+
{
|
51 |
+
// Build our arguments array.
|
52 |
+
$args = array(
|
53 |
+
'slug' => 'CacheCollateObjects',
|
54 |
+
'class_name' => 'NF_Updates_CacheCollateObjects',
|
55 |
+
'debug' => false,
|
56 |
+
);
|
57 |
+
$this->data = $data;
|
58 |
+
$this->running = $running;
|
59 |
+
|
60 |
+
// Call the parent constructor.
|
61 |
+
parent::__construct( $args );
|
62 |
+
|
63 |
+
// Set our table names.
|
64 |
+
$this->table = $this->db->prefix . 'nf3_objects';
|
65 |
+
$this->meta_table = $this->db->prefix . 'nf3_object_meta';
|
66 |
+
|
67 |
+
// Begin processing.
|
68 |
+
$this->process();
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Function to loop over the batch.
|
73 |
+
*
|
74 |
+
* @since 3.4.0
|
75 |
+
*/
|
76 |
+
public function process()
|
77 |
+
{
|
78 |
+
// If we've not already started...
|
79 |
+
if ( ! isset( $this->running[ 0 ][ 'running' ] ) ) {
|
80 |
+
// Run our startup method.
|
81 |
+
$this->startup();
|
82 |
+
} // Otherwise... (We're picking up an old process.)
|
83 |
+
else {
|
84 |
+
// Get our number of remaining table rows.
|
85 |
+
if ( isset( $this->running[ 0 ][ 'table_rows' ] ) ) {
|
86 |
+
$this->table_rows = intval( $this->running[ 0 ][ 'table_rows' ] );
|
87 |
+
}
|
88 |
+
// Get our number of remaining meta rows.
|
89 |
+
if ( isset( $this->running[ 0 ][ 'meta_rows' ] ) ) {
|
90 |
+
$this->meta_rows = intval( $this->running[ 0 ][ 'meta_rows' ] );
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
// Update values in the objects table.
|
95 |
+
$this->maybe_update_objects();
|
96 |
+
|
97 |
+
// Update values in the object_meta table.
|
98 |
+
$this->maybe_update_object_meta();
|
99 |
+
|
100 |
+
// Increment our step count.
|
101 |
+
$this->running[ 0 ][ 'current' ] += 1;
|
102 |
+
// Prepare to output our number of steps and current step.
|
103 |
+
$this->response[ 'stepsTotal' ] = $this->running[ 0 ][ 'steps' ];
|
104 |
+
$this->response[ 'currentStep' ] = $this->running[ 0 ][ 'current' ];
|
105 |
+
$this->running[ 0 ][ 'table_rows' ] = $this->table_rows;
|
106 |
+
$this->running[ 0 ][ 'meta_rows' ] = $this->meta_rows;
|
107 |
+
// If we have no meta left to update at this point...
|
108 |
+
if ( 0 >= $this->table_rows && 0 >= $this->meta_rows ) {
|
109 |
+
// Run our cleanup process.
|
110 |
+
$this->cleanup();
|
111 |
+
}
|
112 |
+
// Prepare to output the number of updates remaining.
|
113 |
+
$this->response[ 'updatesRemaining' ] = count( $this->running );
|
114 |
+
|
115 |
+
// Record our current location in the process.
|
116 |
+
update_option( 'ninja_forms_doing_required_updates', $this->running );
|
117 |
+
|
118 |
+
// Respond to the AJAX call.
|
119 |
+
$this->respond();
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Function to run any setup steps necessary to begin processing.
|
124 |
+
*
|
125 |
+
* @since 3.4.0
|
126 |
+
*/
|
127 |
+
public function startup()
|
128 |
+
{
|
129 |
+
// Record that we're processing the update.
|
130 |
+
$this->running[ 0 ][ 'running' ] = true;
|
131 |
+
// If we're not debugging...
|
132 |
+
if ( ! $this->debug ) {
|
133 |
+
// Ensure that our data tables are updated.
|
134 |
+
$this->migrate( 'cache_collate_objects' );
|
135 |
+
}
|
136 |
+
// Get the number of rows in the objects table.
|
137 |
+
$sql = "SELECT COUNT( `id` ) as Total FROM `{$this->table}`";
|
138 |
+
$result = $this->db->get_results( $sql, 'ARRAY_A' );
|
139 |
+
// If we got something back...
|
140 |
+
if ( ! empty( $result ) ) {
|
141 |
+
// Record the total.
|
142 |
+
$this->table_rows = intval( $result[ 0 ][ 'Total' ] );
|
143 |
+
}
|
144 |
+
// If the table was empty...
|
145 |
+
if ( 0 == $this->table_rows ) {
|
146 |
+
/**
|
147 |
+
* Clean out the object_meta table.
|
148 |
+
* It should contain nothing if there is nothing in the objects table.
|
149 |
+
*/
|
150 |
+
$sql = "DELETE FROM `{$this->meta_table}`";
|
151 |
+
$this->query( $sql );
|
152 |
+
// Lock processing.
|
153 |
+
$this->lock_process = true;
|
154 |
+
}
|
155 |
+
// If processing is locked...
|
156 |
+
if ( $this->lock_process ) {
|
157 |
+
// Prepare to output our number of steps and current step.
|
158 |
+
$this->response[ 'stepsTotal' ] = 1;
|
159 |
+
$this->response[ 'currentStep' ] = 1;
|
160 |
+
// Skip straight to our cleanup method.
|
161 |
+
$this->cleanup();
|
162 |
+
// Prepare to output the number of updates remaining.
|
163 |
+
$this->response[ 'updatesRemaining' ] = count( $this->running );
|
164 |
+
// Record our current location in the process.
|
165 |
+
update_option( 'ninja_forms_doing_required_updates', $this->running );
|
166 |
+
$this->respond();
|
167 |
+
}
|
168 |
+
// Get the number of rows in the object_meta table.
|
169 |
+
$sql = "SELECT COUNT( `id` ) as Total FROM `{$this->meta_table}`";
|
170 |
+
$result = $this->db->get_results( $sql, 'ARRAY_A' );
|
171 |
+
// If we got something back...
|
172 |
+
if ( ! empty( $result ) ) {
|
173 |
+
// Record the total.
|
174 |
+
$this->meta_rows = intval( $result[ 0 ][ 'Total' ] );
|
175 |
+
}
|
176 |
+
$steps = ceil( $this->table_rows / $this->divisor );
|
177 |
+
$steps += ceil( $this->meta_rows / $this->divisor );
|
178 |
+
|
179 |
+
// Record the total number of steps in this batch.
|
180 |
+
$this->running[ 0 ][ 'steps' ] = $steps;
|
181 |
+
// Record our current step (defaulted to 0 here).
|
182 |
+
$this->running[ 0 ][ 'current' ] = 0;
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Function to cleanup any lingering temporary elements of a required update after completion.
|
187 |
+
*
|
188 |
+
* @since 3.4.0
|
189 |
+
*/
|
190 |
+
public function cleanup()
|
191 |
+
{
|
192 |
+
// Remove the current process from the array.
|
193 |
+
array_shift( $this->running );
|
194 |
+
// Record to our updates setting that this update is complete.
|
195 |
+
$this->confirm_complete();
|
196 |
+
// If we have no updates left to process...
|
197 |
+
if ( empty( $this->running ) ) {
|
198 |
+
// Call the parent cleanup method.
|
199 |
+
parent::cleanup();
|
200 |
+
}
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Function to manage the updating of our objects table.
|
205 |
+
*
|
206 |
+
* @return Void
|
207 |
+
*
|
208 |
+
* @since 3.4.0
|
209 |
+
*/
|
210 |
+
private function maybe_update_objects()
|
211 |
+
{
|
212 |
+
// If we have no table rows left to process, exit early.
|
213 |
+
if ( 0 >= $this->table_rows ) return false;
|
214 |
+
// Compile our query.
|
215 |
+
$sql = "SELECT `id`, `title` FROM `{$this->table}` ";
|
216 |
+
// If we are picking up an old process...
|
217 |
+
if ( isset( $this->running[ 0 ][ 'last_updated' ] ) ) {
|
218 |
+
// Make sure we don't fetch old values.
|
219 |
+
$sql .= "WHERE `id` > " . intval( $this->running[ 0 ][ 'last_updated' ] ) . " ";
|
220 |
+
}
|
221 |
+
// Ensure that we gate the number of records that we fetch.
|
222 |
+
$sql .= "ORDER BY `id` ASC LIMIT {$this->divisor}";
|
223 |
+
$result = $this->db->get_results( $sql, 'ARRAY_A' );
|
224 |
+
// Build our Update query.
|
225 |
+
$sub_sql = array();
|
226 |
+
foreach ( $result as $object ) {
|
227 |
+
array_push( $sub_sql, "WHEN `id` = " . intval( $object[ 'id' ] ) . " THEN '" . $this->prepare( $object[ 'title' ] ) . "'" );
|
228 |
+
}
|
229 |
+
// If we have values to update...
|
230 |
+
if ( ! empty( $sub_sql ) ) {
|
231 |
+
// Run the update.
|
232 |
+
$sql = "UPDATE `{$this->table}` SET `object_title` = CASE " . implode( ' ', $sub_sql ) . " ELSE `object_title` END;";
|
233 |
+
$this->query( $sql );
|
234 |
+
// Get the last item updated.
|
235 |
+
$last = array_pop( $result );
|
236 |
+
// Record it to our process object.
|
237 |
+
$this->running[ 0 ][ 'last_updated' ] = $result[ 'id' ];
|
238 |
+
// Also record that we ran the update on this table.
|
239 |
+
$this->running[ 0 ][ 'updating_table' ] = $this->table;
|
240 |
+
// Reduce our table rows by the divisor.
|
241 |
+
$this->table_rows = $this->table_rows - $this->divisor;
|
242 |
+
// Lock processing.
|
243 |
+
$this->lock_process = true;
|
244 |
+
}
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Function to manage the updating of our object_meta table.
|
249 |
+
*
|
250 |
+
* @return Void
|
251 |
+
*
|
252 |
+
* @since 3.4.0
|
253 |
+
*/
|
254 |
+
private function maybe_update_object_meta()
|
255 |
+
{
|
256 |
+
// If we've locked processing, exit early.
|
257 |
+
if ( $this->lock_process ) return false;
|
258 |
+
// If we have no meta rows left to process, exit early.
|
259 |
+
if ( 0 >= $this->meta_rows ) return false;
|
260 |
+
// Compile our query.
|
261 |
+
$sql = "SELECT `id`, `key`, `value` FROM `{$this->meta_table}` ";
|
262 |
+
// If we are picking up an old process...
|
263 |
+
if ( $this->meta_table == $this->running[ 0 ][ 'updating_table' ] ) {
|
264 |
+
// Make sure we don't fetch old values.
|
265 |
+
$sql .= "WHERE `id` > " . intval( $this->running[ 0 ][ 'last_updated' ] ) . " ";
|
266 |
+
}
|
267 |
+
// Ensure that we gate the number of records that we fetch.
|
268 |
+
$sql .= "ORDER BY `id` ASC LIMIT {$this->divisor}";
|
269 |
+
$result = $this->db->get_results( $sql, 'ARRAY_A' );
|
270 |
+
// Build our Update query.
|
271 |
+
$sub_sql = array();
|
272 |
+
$meta_ids = array();
|
273 |
+
foreach ( $result as $object ) {
|
274 |
+
array_push( $sub_sql, "WHEN `id` = " . intval( $object[ 'id' ] ) . " THEN '" . $this->prepare( $object[ 'value' ] ) . "'" );
|
275 |
+
array_push( $meta_ids, $object[ 'id' ] );
|
276 |
+
}
|
277 |
+
// If we have values to update...
|
278 |
+
if ( ! empty( $sub_sql ) ) {
|
279 |
+
// Run the update on the meta_key column.
|
280 |
+
$sql = "UPDATE `{$this->meta_table}` SET `meta_key` = `key` WHERE `id` IN(" . implode( ', ', $meta_ids ) . ");";
|
281 |
+
$this->query( $sql );
|
282 |
+
// Run the update on the meta_value column.
|
283 |
+
$sql = "UPDATE `{$this->meta_table}` SET `meta_value` = CASE " . implode( ' ', $sub_sql ) . " ELSE `meta_value` END;";
|
284 |
+
$this->query( $sql );
|
285 |
+
// Get the last item updated.
|
286 |
+
$last = array_pop( $result );
|
287 |
+
// Record it to our process object.
|
288 |
+
$this->running[ 0 ][ 'last_updated' ] = $result[ 'id' ];
|
289 |
+
// Also record that we ran the update on this table.
|
290 |
+
$this->running[ 0 ][ 'updating_table' ] = $this->meta_table;
|
291 |
+
// Reduce our meta rows by the divisor.
|
292 |
+
$this->meta_rows -= $this->divisor;
|
293 |
+
// Lock processing.
|
294 |
+
$this->lock_process = true;
|
295 |
+
}
|
296 |
+
}
|
297 |
+
|
298 |
+
}
|
lib/NF_Upgrade.php
CHANGED
@@ -12,6 +12,7 @@ function ninja_forms_ajax_migrate_database(){
|
|
12 |
$nuke_multisite = false;
|
13 |
$migrations->nuke( $sure, $really_sure, $nuke_multisite );
|
14 |
$migrations->migrate();
|
|
|
15 |
echo json_encode( array( 'migrate' => 'true' ) );
|
16 |
wp_die();
|
17 |
}
|
12 |
$nuke_multisite = false;
|
13 |
$migrations->nuke( $sure, $really_sure, $nuke_multisite );
|
14 |
$migrations->migrate();
|
15 |
+
delete_option( 'ninja_forms_required_updates' );
|
16 |
echo json_encode( array( 'migrate' => 'true' ) );
|
17 |
wp_die();
|
18 |
}
|
ninja-forms.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Ninja Forms
|
4 |
Plugin URI: http://ninjaforms.com/
|
5 |
Description: Ninja Forms is a webform builder with unparalleled ease of use and features.
|
6 |
-
Version: 3.
|
7 |
Author: The WP Ninjas
|
8 |
Author URI: http://ninjaforms.com
|
9 |
Text Domain: ninja-forms
|
@@ -57,7 +57,13 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
|
|
57 |
/**
|
58 |
* @since 3.0
|
59 |
*/
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
|
62 |
const WP_MIN_VERSION = '4.8';
|
63 |
|
@@ -74,6 +80,16 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
|
|
74 |
* @var string $dir
|
75 |
*/
|
76 |
public static $dir = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
/**
|
79 |
* Plugin URL
|
@@ -204,11 +220,6 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
|
|
204 |
}
|
205 |
|
206 |
$saved_version = get_option( 'ninja_forms_version' );
|
207 |
-
// If this is a fresh install... (The version has never been saved.)
|
208 |
-
if ( ! $saved_version ) {
|
209 |
-
// Assume we have clean data.
|
210 |
-
update_option( 'ninja_forms_data_is_clean', 'true' );
|
211 |
-
}
|
212 |
// If we have a recorded version...
|
213 |
// AND that version is less than our current version...
|
214 |
if ( $saved_version && version_compare( $saved_version, self::VERSION, '<' ) ) {
|
@@ -230,12 +241,28 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
|
|
230 |
if ( $saved_version && version_compare( $saved_version, '3.3.0', '<' ) ) {
|
231 |
// Set it to the baseline (1.0) so that our upgrade process will run properly.
|
232 |
add_option( 'ninja_forms_db_version', '1.0', '', 'no' );
|
233 |
-
}
|
|
|
|
|
|
|
|
|
234 |
else {
|
235 |
-
// Set it to
|
236 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
}
|
238 |
}
|
|
|
|
|
239 |
|
240 |
/*
|
241 |
* Register our autoloader
|
@@ -263,6 +290,7 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
|
|
263 |
self::$instance->controllers[ 'form' ] = new NF_AJAX_Controllers_Form();
|
264 |
self::$instance->controllers[ 'fields' ] = new NF_AJAX_Controllers_Fields();
|
265 |
self::$instance->controllers[ 'batch_process' ] = new NF_AJAX_REST_BatchProcess();
|
|
|
266 |
self::$instance->controllers[ 'preview' ] = new NF_AJAX_Controllers_Preview();
|
267 |
self::$instance->controllers[ 'submission' ] = new NF_AJAX_Controllers_Submission();
|
268 |
self::$instance->controllers[ 'savedfields' ] = new NF_AJAX_Controllers_SavedFields();
|
@@ -414,27 +442,6 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
|
|
414 |
// Ensure all of our tables have been defined.
|
415 |
$migrations = new NF_Database_Migrations();
|
416 |
$migrations->migrate();
|
417 |
-
// If our db version is below 1.1...
|
418 |
-
if ( version_compare( get_option( 'ninja_forms_db_version' ), '1.1', '<' ) ) {
|
419 |
-
// Do our stage 1 updates.
|
420 |
-
$migrations->do_stage_one();
|
421 |
-
// Update our db version.
|
422 |
-
update_option( 'ninja_forms_db_version', '1.1' );
|
423 |
-
}
|
424 |
-
// Fix for legacy versions that upgraded without a set DB version.
|
425 |
-
// If our version is exactly 1.1...
|
426 |
-
if ( version_compare( get_option( 'ninja_forms_db_version' ), '1.1', '==' ) ) {
|
427 |
-
global $wpdb;
|
428 |
-
// Fetch the form_title column from the fields table.
|
429 |
-
$sql = "SHOW FULL COLUMNS FROM `{$wpdb->prefix}nf3_forms` WHERE Field = 'form_title'";
|
430 |
-
$result = $wpdb->get_results( $sql, 'ARRAY_A' );
|
431 |
-
// If we didn't get a result...
|
432 |
-
if ( empty( $result ) ) {
|
433 |
-
// Do our stage 1 updates, even though they should have already run.
|
434 |
-
$migrations->do_stage_one();
|
435 |
-
}
|
436 |
-
}
|
437 |
-
|
438 |
}
|
439 |
}
|
440 |
|
@@ -472,11 +479,30 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
|
|
472 |
}
|
473 |
|
474 |
add_filter( 'ninja_forms_dashboard_menu_items', array( $this, 'maybe_hide_dashboard_items' ) );
|
|
|
|
|
|
|
|
|
475 |
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
480 |
}
|
481 |
}
|
482 |
|
@@ -553,6 +579,14 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
|
|
553 |
$items[ 'services' ]
|
554 |
);
|
555 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
556 |
return $items;
|
557 |
}
|
558 |
|
@@ -866,8 +900,9 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
|
|
866 |
|
867 |
if( Ninja_Forms()->form()->get_forms() ) return;
|
868 |
|
869 |
-
//
|
870 |
-
|
|
|
871 |
$form = Ninja_Forms::template( 'formtemplate-contactform.nff', array(), TRUE );
|
872 |
Ninja_Forms()->form()->import_form( $form );
|
873 |
}
|
@@ -901,24 +936,101 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
|
|
901 |
}
|
902 |
}
|
903 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
904 |
|
905 |
/**
|
906 |
-
* Function to
|
907 |
-
*
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
|
|
912 |
*/
|
913 |
-
public function
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
)
|
921 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
922 |
}
|
923 |
|
924 |
} // End Class Ninja_Forms
|
3 |
Plugin Name: Ninja Forms
|
4 |
Plugin URI: http://ninjaforms.com/
|
5 |
Description: Ninja Forms is a webform builder with unparalleled ease of use and features.
|
6 |
+
Version: 3.4.0
|
7 |
Author: The WP Ninjas
|
8 |
Author URI: http://ninjaforms.com
|
9 |
Text Domain: ninja-forms
|
57 |
/**
|
58 |
* @since 3.0
|
59 |
*/
|
60 |
+
|
61 |
+
const VERSION = '3.4.0';
|
62 |
+
|
63 |
+
/**
|
64 |
+
* @since 3.4.0
|
65 |
+
*/
|
66 |
+
const DB_VERSION = '1.4';
|
67 |
|
68 |
const WP_MIN_VERSION = '4.8';
|
69 |
|
80 |
* @var string $dir
|
81 |
*/
|
82 |
public static $dir = '';
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Plugin Database Version
|
86 |
+
*
|
87 |
+
* This may be overwritten at a later point in this file.
|
88 |
+
*
|
89 |
+
* @since 3.4.0
|
90 |
+
* @var string $db_version
|
91 |
+
*/
|
92 |
+
public static $db_version = self::DB_VERSION;
|
93 |
|
94 |
/**
|
95 |
* Plugin URL
|
220 |
}
|
221 |
|
222 |
$saved_version = get_option( 'ninja_forms_version' );
|
|
|
|
|
|
|
|
|
|
|
223 |
// If we have a recorded version...
|
224 |
// AND that version is less than our current version...
|
225 |
if ( $saved_version && version_compare( $saved_version, self::VERSION, '<' ) ) {
|
241 |
if ( $saved_version && version_compare( $saved_version, '3.3.0', '<' ) ) {
|
242 |
// Set it to the baseline (1.0) so that our upgrade process will run properly.
|
243 |
add_option( 'ninja_forms_db_version', '1.0', '', 'no' );
|
244 |
+
} // OR If this isn't a fresh install...
|
245 |
+
elseif ( $saved_version ) {
|
246 |
+
// Set it to the expected (1.1) so that our upgrade process will handle that.
|
247 |
+
add_option( 'ninja_forms_db_version', '1.1', '', 'no' );
|
248 |
+
} // Otherwise... (This is a fresh install.)
|
249 |
else {
|
250 |
+
// Set it to the current DB version.
|
251 |
+
add_option( 'ninja_forms_db_version', self::DB_VERSION, '', 'no' );
|
252 |
+
// Establish that our upgrades don't need to take place.
|
253 |
+
$required_updates = Ninja_Forms()->config( 'RequiredUpdates' );
|
254 |
+
$updated = array();
|
255 |
+
// Get a timestamp.
|
256 |
+
date_default_timezone_set( 'UTC' );
|
257 |
+
$now = date( "Y-m-d H:i:s" );
|
258 |
+
foreach( $required_updates as $slug => $update ) {
|
259 |
+
$updated[ $slug ] = $now;
|
260 |
+
}
|
261 |
+
update_option( 'ninja_forms_required_updates', $updated );
|
262 |
}
|
263 |
}
|
264 |
+
// Set our static db version.
|
265 |
+
self::$db_version = get_option( 'ninja_forms_db_version', self::$db_version );
|
266 |
|
267 |
/*
|
268 |
* Register our autoloader
|
290 |
self::$instance->controllers[ 'form' ] = new NF_AJAX_Controllers_Form();
|
291 |
self::$instance->controllers[ 'fields' ] = new NF_AJAX_Controllers_Fields();
|
292 |
self::$instance->controllers[ 'batch_process' ] = new NF_AJAX_REST_BatchProcess();
|
293 |
+
self::$instance->controllers[ 'required_updates' ] = new NF_AJAX_REST_RequiredUpdate();
|
294 |
self::$instance->controllers[ 'preview' ] = new NF_AJAX_Controllers_Preview();
|
295 |
self::$instance->controllers[ 'submission' ] = new NF_AJAX_Controllers_Submission();
|
296 |
self::$instance->controllers[ 'savedfields' ] = new NF_AJAX_Controllers_SavedFields();
|
442 |
// Ensure all of our tables have been defined.
|
443 |
$migrations = new NF_Database_Migrations();
|
444 |
$migrations->migrate();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
445 |
}
|
446 |
}
|
447 |
|
479 |
}
|
480 |
|
481 |
add_filter( 'ninja_forms_dashboard_menu_items', array( $this, 'maybe_hide_dashboard_items' ) );
|
482 |
+
|
483 |
+
// Remove already completed updates from our filtered list of required updates.
|
484 |
+
add_filter( 'ninja_forms_required_updates', array( $this, 'remove_completed_updates' ), 99 );
|
485 |
+
add_filter( 'ninja_forms_required_updates', array( $this, 'remove_bad_updates' ), 99 );
|
486 |
|
487 |
+
|
488 |
+
// Get our list of required updates.
|
489 |
+
$required_updates = Ninja_Forms()->config( 'RequiredUpdates' );
|
490 |
+
global $wpdb;
|
491 |
+
$sql = "SELECT COUNT( `id` ) AS total FROM `{$wpdb->prefix}nf3_forms`;";
|
492 |
+
$result = $wpdb->get_results( $sql, 'ARRAY_A' );
|
493 |
+
$threshold = 5; // Threshold percentage for our required updates.
|
494 |
+
// If we got back a list of updates...
|
495 |
+
// AND If we have any forms on the site...
|
496 |
+
// AND If the gate is open...
|
497 |
+
if ( ! empty( $required_updates )
|
498 |
+
&& 0 < $result[ 0 ][ 'total' ]
|
499 |
+
&& WPN_Helper::gated_release( $threshold ) ) {
|
500 |
+
// Record that we have updates to run.
|
501 |
+
update_option( 'ninja_forms_needs_updates', 1 );
|
502 |
+
} // Otherwise... (Sanity check)
|
503 |
+
else {
|
504 |
+
// Record that there are no required updates.
|
505 |
+
update_option( 'ninja_forms_needs_updates', 0 );
|
506 |
}
|
507 |
}
|
508 |
|
579 |
$items[ 'services' ]
|
580 |
);
|
581 |
}
|
582 |
+
if ( 1 == get_option( 'ninja_forms_needs_updates' ) ) {
|
583 |
+
unset(
|
584 |
+
$items[ 'widgets' ],
|
585 |
+
$items[ 'apps' ],
|
586 |
+
$items[ 'memberships' ],
|
587 |
+
$items[ 'services' ]
|
588 |
+
);
|
589 |
+
}
|
590 |
return $items;
|
591 |
}
|
592 |
|
900 |
|
901 |
if( Ninja_Forms()->form()->get_forms() ) return;
|
902 |
|
903 |
+
// Go ahead and create our randomn number for gated releases in the future
|
904 |
+
$zuul = WPN_Helper::get_zuul();
|
905 |
+
|
906 |
$form = Ninja_Forms::template( 'formtemplate-contactform.nff', array(), TRUE );
|
907 |
Ninja_Forms()->form()->import_form( $form );
|
908 |
}
|
936 |
}
|
937 |
}
|
938 |
}
|
939 |
+
|
940 |
+
/**
|
941 |
+
* Function to deregister already completed updates from the list of required updates.
|
942 |
+
*
|
943 |
+
* @since 3.3.14
|
944 |
+
*
|
945 |
+
* @param $updates (Array) Our array of required updates.
|
946 |
+
* @return $updates (Array) Our array of required updates.
|
947 |
+
*/
|
948 |
+
public function remove_completed_updates( $updates ) {
|
949 |
+
$processed = get_option( 'ninja_forms_required_updates', array() );
|
950 |
+
// For each update in our list...
|
951 |
+
foreach ( $updates as $slug => $update ) {
|
952 |
+
// If we have already processed it...
|
953 |
+
if ( isset( $processed[ $slug ] ) ) {
|
954 |
+
// Remove it from the list.
|
955 |
+
unset( $updates[ $slug ] );
|
956 |
+
}
|
957 |
+
}
|
958 |
+
return $updates;
|
959 |
+
}
|
960 |
|
961 |
/**
|
962 |
+
* Function to deregister updates that have required updates that either
|
963 |
+
* don't exist, or are malformed
|
964 |
+
*
|
965 |
+
* @since UPDATE_TO_LATEST version
|
966 |
+
*
|
967 |
+
* @param $updates (Array) Our array of required updates.
|
968 |
+
* @return $updates (Array) Our array of required updates.
|
969 |
*/
|
970 |
+
public function remove_bad_updates( $updates ) {
|
971 |
+
|
972 |
+
$processed = get_option( 'ninja_forms_required_updates', array() );
|
973 |
+
|
974 |
+
$sorted = array();
|
975 |
+
$queue = array();
|
976 |
+
// While we have not finished removing bad updates...
|
977 |
+
while ( count( $sorted ) < count( $updates ) ) {
|
978 |
+
// For each update we wish to run...
|
979 |
+
foreach ( $updates as $slug => $update ) {
|
980 |
+
// Migrate the slug to a property.
|
981 |
+
$update[ 'slug' ] = $slug;
|
982 |
+
// If we've not already added this to the sorted list...
|
983 |
+
if ( ! in_array( $update, $sorted ) ) {
|
984 |
+
// If it has requirements...
|
985 |
+
if ( ! empty( $update[ 'requires' ] ) ) {
|
986 |
+
$enqueued = 0;
|
987 |
+
// For each requirement...
|
988 |
+
foreach ( $update[ 'requires' ] as $requirement ) {
|
989 |
+
// If the requirement doesn't exist...
|
990 |
+
if ( ! isset( $updates[ $requirement ] ) ) {
|
991 |
+
// unset the update b/c we are missing requirements
|
992 |
+
unset( $updates[ $slug ] );
|
993 |
+
|
994 |
+
$nf_bad_update_transient = get_transient( 'nf_bad_update_requirement' );
|
995 |
+
|
996 |
+
if( ! $nf_bad_update_transient ) {
|
997 |
+
// send telemetry so we can keep up with these
|
998 |
+
Ninja_Forms()->dispatcher()->send( 'incomplete_update',
|
999 |
+
array(
|
1000 |
+
'update' => $slug,
|
1001 |
+
'missing_requirement' => $requirement
|
1002 |
+
)
|
1003 |
+
);
|
1004 |
+
|
1005 |
+
set_transient( 'nf_bad_update_requirement', $requirement, 30 * 3600 );
|
1006 |
+
}
|
1007 |
+
}
|
1008 |
+
// If the requirement has already been added to the stack...
|
1009 |
+
if ( in_array( $requirement, $queue ) ) {
|
1010 |
+
$enqueued++;
|
1011 |
+
} // OR If the requirement has already been processed...
|
1012 |
+
elseif ( isset( $processed[ $requirement ] ) ) {
|
1013 |
+
$enqueued++;
|
1014 |
+
}
|
1015 |
+
}
|
1016 |
+
// If all requirement are met...
|
1017 |
+
if ( $enqueued == count( $update[ 'requires' ] ) ) {
|
1018 |
+
// Add it to the list.
|
1019 |
+
array_push( $sorted, $update );
|
1020 |
+
// Record that we enqueued it.
|
1021 |
+
array_push( $queue, $slug );
|
1022 |
+
}
|
1023 |
+
} // Otherwise... (It has no requirements.)
|
1024 |
+
else {
|
1025 |
+
// Add it to the list.
|
1026 |
+
array_push( $sorted, $update );
|
1027 |
+
// Record that we enqueued it.
|
1028 |
+
array_push( $queue, $slug );
|
1029 |
+
}
|
1030 |
+
}
|
1031 |
+
}
|
1032 |
+
}
|
1033 |
+
return $sorted;
|
1034 |
}
|
1035 |
|
1036 |
} // End Class Ninja_Forms
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: wpninjasllc, kstover, jameslaws, kbjohnson90, klhall1987, krmoorho
|
|
3 |
Tags: form, forms, contact form, custom form, form builder, form creator, form manager, form creation, contact forms, custom forms, forms builder, forms creator, forms manager, forms creation, form administration,
|
4 |
Requires at least: 4.8
|
5 |
Tested up to: 5.0
|
6 |
-
Stable tag: 3.
|
7 |
License: GPLv2 or later
|
8 |
|
9 |
Drag and drop fields in an intuitive UI to create contact forms, email subscription forms, order forms, payment forms, send emails and more!
|
@@ -111,14 +111,22 @@ For help and video tutorials, please visit our website: [Ninja Forms Documentati
|
|
111 |
|
112 |
== Upgrade Notice ==
|
113 |
|
114 |
-
= 3.
|
115 |
|
116 |
-
*
|
117 |
|
118 |
-
*
|
|
|
119 |
|
120 |
== Changelog ==
|
121 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
= 3.3.21.3 (10 January 2019) =
|
123 |
|
124 |
*Security:*
|
3 |
Tags: form, forms, contact form, custom form, form builder, form creator, form manager, form creation, contact forms, custom forms, forms builder, forms creator, forms manager, forms creation, form administration,
|
4 |
Requires at least: 4.8
|
5 |
Tested up to: 5.0
|
6 |
+
Stable tag: 3.4.0
|
7 |
License: GPLv2 or later
|
8 |
|
9 |
Drag and drop fields in an intuitive UI to create contact forms, email subscription forms, order forms, payment forms, send emails and more!
|
111 |
|
112 |
== Upgrade Notice ==
|
113 |
|
114 |
+
= 3.4.0 (14 January 2019) =
|
115 |
|
116 |
+
*Changes:*
|
117 |
|
118 |
+
* Implemented a new import process, which should be more reliable with large form imports.
|
119 |
+
* Upgraded our data structure to reduce loading times for forms and the form builder.
|
120 |
|
121 |
== Changelog ==
|
122 |
|
123 |
+
= 3.4.0 (14 January 2019) =
|
124 |
+
|
125 |
+
*Changes:*
|
126 |
+
|
127 |
+
* Implemented a new import process, which should be more reliable with large form imports.
|
128 |
+
* Upgraded our data structure to reduce loading times for forms and the form builder.
|
129 |
+
|
130 |
= 3.3.21.3 (10 January 2019) =
|
131 |
|
132 |
*Security:*
|