fix
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
* Themeisle factory build
|
||||
*
|
||||
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Themeisle <wordpress.webraftic@gmail.com>
|
||||
* Site: https://themeisle.com
|
||||
* Support: https://themeisle.com/contact-us/
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .factory-accordion{margin:0 0 30px;border-top:1px solid #DDD;border-right:1px solid #DDD;border-left:1px solid #DDD;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.factory-bootstrap-500 .factory-accordion>h3{border-bottom:1px solid #DDD;cursor:pointer;padding:8px 15px;margin:0}.factory-bootstrap-500 .factory-accordion>div{display:none;margin:0;border-bottom:1px solid #DDD}.factory-bootstrap-500 .factory-accordion-item{display:none}.factory-bootstrap-500 .inner-factory-accordion-item{padding:10px 0}.factory-bootstrap-500 .factory-accordion>h3.active:hover{cursor:default}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .btn-primary{background:#e1a948;border-color:#d39323;color:#fff;-webkit-box-shadow:inset 0 1px 0 #ecc88a,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #ecc88a,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:focus,.factory-bootstrap-500 .btn-primary:hover{background:#db9825;border-color:#bd831f;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8be74,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8be74,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:active{background:#db9825;border-color:#bd831f;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-500 .btn-primary:disabled,.factory-bootstrap-500 .btn-primary[disabled]{color:#d1cdc7!important;background:#db9825!important;border-color:#bd831f!important;text-shadow:none!important}.factory-bootstrap-500 .btn-group .btn.active.value{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.factory-bootstrap-500 .pagination>.active>a,.factory-bootstrap-500 .pagination>.active>a:focus,.factory-bootstrap-500 .pagination>.active>a:hover,.factory-bootstrap-500 .pagination>.active>span,.factory-bootstrap-500 .pagination>.active>span:focus,.factory-bootstrap-500 .pagination>.active>span:hover{background-color:#e1a948;border-color:#d39323}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .btn-primary{background:#c7a589;border-color:#b78a66;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e0cdbd,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e0cdbd,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:focus,.factory-bootstrap-500 .btn-primary:hover{background:#ba906d;border-color:#ae7d55;color:#fff;-webkit-box-shadow:inset 0 1px 0 #d7bfac,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #d7bfac,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:active{background:#ba906d;border-color:#ae7d55;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-500 .btn-primary:disabled,.factory-bootstrap-500 .btn-primary[disabled]{color:#d1cbc7!important;background:#ba906d!important;border-color:#ae7d55!important;text-shadow:none!important}.factory-bootstrap-500 .btn-group .btn.active.value{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.factory-bootstrap-500 .pagination>.active>a,.factory-bootstrap-500 .pagination>.active>a:focus,.factory-bootstrap-500 .pagination>.active>a:hover,.factory-bootstrap-500 .pagination>.active>span,.factory-bootstrap-500 .pagination>.active>span:focus,.factory-bootstrap-500 .pagination>.active>span:hover{background-color:#c7a589;border-color:#b78a66}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .btn-primary{background:#a3b745;border-color:#839237;color:#fff;-webkit-box-shadow:inset 0 1px 0 #c0cd7b,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #c0cd7b,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:focus,.factory-bootstrap-500 .btn-primary:hover{background:#89993a;border-color:#727f30;color:#fff;-webkit-box-shadow:inset 0 1px 0 #b7c669,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #b7c669,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:active{background:#89993a;border-color:#727f30;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-500 .btn-primary:disabled,.factory-bootstrap-500 .btn-primary[disabled]{color:#cfd1c7!important;background:#89993a!important;border-color:#727f30!important;text-shadow:none!important}.factory-bootstrap-500 .btn-group .btn.active.value{background-color:#a3b745;-webkit-box-shadow:inset 0 1px 2px #839237;box-shadow:inset 0 1px 2px #839237;border-top:1px solid #839237;border-bottom:1px solid #839237;border-left:1px solid #839237}.factory-bootstrap-500 .pagination>.active>a,.factory-bootstrap-500 .pagination>.active>a:focus,.factory-bootstrap-500 .pagination>.active>a:hover,.factory-bootstrap-500 .pagination>.active>span,.factory-bootstrap-500 .pagination>.active>span:focus,.factory-bootstrap-500 .pagination>.active>span:hover{background-color:#a3b745;border-color:#839237}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .factory-form-group .factory-legend{padding:9px 12px;background-color:#f9f9f9}.factory-bootstrap-500 .factory-form-group .factory-title{font-weight:700;font-size:14px;line-height:14px;color:#555;margin:0}.factory-bootstrap-500 .factory-form-group .factory-hint-icon{display:block;width:16px;height:16px;line-height:13px;padding:0;font-size:11px;text-align:center;position:absolute;top:-5px;right:-3px;color:#fff;background:#E91E63;border-radius:3px}.factory-bootstrap-500 .factory-form-group .factory-hint-icon.factory-hint-icon-green{background:#8bc34a}.factory-bootstrap-500 .factory-form-group .factory-hint-icon.factory-hint-icon-grey{background:#9e9e9e}.factory-bootstrap-500 .factory-form-group .factory-hint-icon.factory-hint-icon-red{background:#E91E63}.factory-bootstrap-500 .factory-form-group .factory-hint{margin:0;font-size:12px;line-height:16px;margin-top:6px}.factory-bootstrap-500 .factory-form-group+.factory-form-group{margin-top:30px}.factory-bootstrap-500 .factory-form-group legend+.control-group{margin-top:0}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .btn-primary{background:#04a4cc;border-color:#037c9a;color:#fff;-webkit-box-shadow:inset 0 1px 0 #22cffb,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #22cffb,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:focus,.factory-bootstrap-500 .btn-primary:hover{background:#0384a4;border-color:#036881;color:#fff;-webkit-box-shadow:inset 0 1px 0 #09cafa,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #09cafa,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:active{background:#0384a4;border-color:#036881;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-500 .btn-primary:disabled,.factory-bootstrap-500 .btn-primary[disabled]{color:#c7cfd1!important;background:#0384a4!important;border-color:#036881!important;text-shadow:none!important}.factory-bootstrap-500 .btn-group .btn.active.value{background-color:#04a4cc;-webkit-box-shadow:inset 0 1px 2px #037c9a;box-shadow:inset 0 1px 2px #037c9a;border-top:1px solid #037c9a;border-bottom:1px solid #037c9a;border-left:1px solid #037c9a}.factory-bootstrap-500 .pagination>.active>a,.factory-bootstrap-500 .pagination>.active>a:focus,.factory-bootstrap-500 .pagination>.active>a:hover,.factory-bootstrap-500 .pagination>.active>span,.factory-bootstrap-500 .pagination>.active>span:focus,.factory-bootstrap-500 .pagination>.active>span:hover{background-color:#04a4cc;border-color:#037c9a}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .btn-primary{background:#e14d43;border-color:#d02a21;color:#fff;-webkit-box-shadow:inset 0 1px 0 #ec8a85,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #ec8a85,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:focus,.factory-bootstrap-500 .btn-primary:hover{background:#d92c23;border-color:#ba251e;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8756f,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8756f,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:active{background:#d92c23;border-color:#ba251e;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-500 .btn-primary:disabled,.factory-bootstrap-500 .btn-primary[disabled]{color:#d1c7c7!important;background:#d92c23!important;border-color:#ba251e!important;text-shadow:none!important}.factory-bootstrap-500 .btn-group .btn.active.value{background-color:#e14d43;-webkit-box-shadow:inset 0 1px 2px #d02a21;box-shadow:inset 0 1px 2px #d02a21;border-top:1px solid #d02a21;border-bottom:1px solid #d02a21;border-left:1px solid #d02a21}.factory-bootstrap-500 .pagination>.active>a,.factory-bootstrap-500 .pagination>.active>a:focus,.factory-bootstrap-500 .pagination>.active>a:hover,.factory-bootstrap-500 .pagination>.active>span,.factory-bootstrap-500 .pagination>.active>span:focus,.factory-bootstrap-500 .pagination>.active>span:hover{background-color:#e14d43;border-color:#d02a21}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .btn-primary{background:#9ebaa0;border-color:#80a583;color:#fff;-webkit-box-shadow:inset 0 1px 0 #cbdacc,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #cbdacc,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:focus,.factory-bootstrap-500 .btn-primary:hover{background:#86a988;border-color:#719a74;color:#fff;-webkit-box-shadow:inset 0 1px 0 #bccfbd,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #bccfbd,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:active{background:#86a988;border-color:#719a74;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-500 .btn-primary:disabled,.factory-bootstrap-500 .btn-primary[disabled]{color:#c7d1c8!important;background:#86a988!important;border-color:#719a74!important;text-shadow:none!important}.factory-bootstrap-500 .btn-group .btn.active.value{background-color:#9ebaa0;-webkit-box-shadow:inset 0 1px 2px #80a583;box-shadow:inset 0 1px 2px #80a583;border-top:1px solid #80a583;border-bottom:1px solid #80a583;border-left:1px solid #80a583}.factory-bootstrap-500 .pagination>.active>a,.factory-bootstrap-500 .pagination>.active>a:focus,.factory-bootstrap-500 .pagination>.active>a:hover,.factory-bootstrap-500 .pagination>.active>span,.factory-bootstrap-500 .pagination>.active>span:focus,.factory-bootstrap-500 .pagination>.active>span:hover{background-color:#9ebaa0;border-color:#80a583}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .factory-separator{border-bottom:1px solid #f9f9f9;border-top:1px solid #d1d1d1;margin-bottom:25px}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .btn-primary{background:#dd823b;border-color:#c36822;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8ab7c,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8ab7c,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:focus,.factory-bootstrap-500 .btn-primary:hover{background:#cc6c23;border-color:#ad5c1e;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e59d66,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e59d66,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-500 .btn-primary:active{background:#cc6c23;border-color:#ad5c1e;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-500 .btn-primary:disabled,.factory-bootstrap-500 .btn-primary[disabled]{color:#d1cbc7!important;background:#cc6c23!important;border-color:#ad5c1e!important;text-shadow:none!important}.factory-bootstrap-500 .btn-group .btn.active.value{background-color:#dd823b;-webkit-box-shadow:inset 0 1px 2px #c36822;box-shadow:inset 0 1px 2px #c36822;border-top:1px solid #c36822;border-bottom:1px solid #c36822;border-left:1px solid #c36822}.factory-bootstrap-500 .pagination>.active>a,.factory-bootstrap-500 .pagination>.active>a:focus,.factory-bootstrap-500 .pagination>.active>a:hover,.factory-bootstrap-500 .pagination>.active>span,.factory-bootstrap-500 .pagination>.active>span:focus,.factory-bootstrap-500 .pagination>.active>span:hover{background-color:#dd823b;border-color:#c36822}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
#side-sortables .factory-bootstrap-500 .factory-buttons-way{float:right;position:relative;top:-25px;left:5px;border:3px solid #f9f9f9;border-radius:4px}.factory-bootstrap-500 .factory-checkbox-disabled button,.factory-bootstrap-500 .factory-checkbox-disabled input{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-500 .factory-buttons-way{border:3px solid #f9f9f9;border-radius:4px}.factory-bootstrap-500 .factory-buttons-way button{padding-left:10px;padding-right:10px}.factory-bootstrap-500 .factory-buttons-way .factory-on.active{text-shadow:none;color:#fff;background-color:#33aad5;-webkit-box-shadow:inset 0 1px 1px #0074a2;box-shadow:inset 0 1px 3px #0074a2;border-top:1px solid #0074a2;border-bottom:1px solid #0074a2;border-left:1px solid #0074a2}.factory-bootstrap-500 .factory-checkbox-tumbler-hint{margin-top:5px}.factory-bootstrap-500 .factory-checkbox-tumbler-hint .factory-tumbler-content{display:inline-block;background-color:#ffd;padding:1px 5px}.admin-color-light .factory-bootstrap-500 .factory-buttons-way .factory-on.active{background-color:#04a4cc;-webkit-box-shadow:inset 0 1px 2px #037c9a;box-shadow:inset 0 1px 2px #037c9a;border-top:1px solid #037c9a;border-bottom:1px solid #037c9a;border-left:1px solid #037c9a}.admin-color-blue .factory-bootstrap-500 .factory-buttons-way .factory-on.active{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.admin-color-coffee .factory-bootstrap-500 .factory-buttons-way .factory-on.active{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.admin-color-ectoplasm .factory-bootstrap-500 .factory-buttons-way .factory-on.active{background-color:#a3b745;-webkit-box-shadow:inset 0 1px 2px #839237;box-shadow:inset 0 1px 2px #839237;border-top:1px solid #839237;border-bottom:1px solid #839237;border-left:1px solid #839237}.admin-color-midnight .factory-bootstrap-500 .factory-buttons-way .factory-on.active{background-color:#e14d43;-webkit-box-shadow:inset 0 1px 2px #d02a21;box-shadow:inset 0 1px 2px #d02a21;border-top:1px solid #d02a21;border-bottom:1px solid #d02a21;border-left:1px solid #d02a21}.admin-color-ocean .factory-bootstrap-500 .factory-buttons-way .factory-on.active{background-color:#9ebaa0;-webkit-box-shadow:inset 0 1px 2px #80a583;box-shadow:inset 0 1px 2px #80a583;border-top:1px solid #80a583;border-bottom:1px solid #80a583;border-left:1px solid #80a583}.admin-color-sunrise .factory-bootstrap-500 .factory-buttons-way .factory-on.active{background-color:#dd823b;-webkit-box-shadow:inset 0 1px 2px #c36822;box-shadow:inset 0 1px 2px #c36822;border-top:1px solid #c36822;border-bottom:1px solid #c36822;border-left:1px solid #c36822}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .factory-dropdown.factory-buttons-way .fa{margin-right:6px;position:relative}.factory-bootstrap-500 .factory-dropdown.factory-buttons-way{border:0;border-radius:0}.factory-bootstrap-500 .factory-hints .factory-hint{margin-top:5px;display:inline-block;background-color:#ffd;padding:8px 10px;}.admin-color-light .factory-bootstrap-500 .factory-dropdown.factory-buttons-way .active{background-color:#04a4cc;-webkit-box-shadow:inset 0 1px 2px #037c9a;box-shadow:inset 0 1px 2px #037c9a;border-top:1px solid #037c9a;border-bottom:1px solid #037c9a;border-left:1px solid #037c9a}.admin-color-blue .factory-bootstrap-500 .factory-dropdown.factory-buttons-way .active{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.admin-color-coffee .factory-bootstrap-500 .factory-dropdown.factory-buttons-way .active{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.admin-color-ectoplasm .factory-bootstrap-500 .factory-dropdown.factory-buttons-way .active{background-color:#a3b745;-webkit-box-shadow:inset 0 1px 2px #839237;box-shadow:inset 0 1px 2px #839237;border-top:1px solid #839237;border-bottom:1px solid #839237;border-left:1px solid #839237}.admin-color-midnight .factory-bootstrap-500 .factory-dropdown.factory-buttons-way .active{background-color:#e14d43;-webkit-box-shadow:inset 0 1px 2px #d02a21;box-shadow:inset 0 1px 2px #d02a21;border-top:1px solid #d02a21;border-bottom:1px solid #d02a21;border-left:1px solid #d02a21}.admin-color-ocean .factory-bootstrap-500 .factory-dropdown.factory-buttons-way .active{background-color:#9ebaa0;-webkit-box-shadow:inset 0 1px 2px #80a583;box-shadow:inset 0 1px 2px #80a583;border-top:1px solid #80a583;border-bottom:1px solid #80a583;border-left:1px solid #80a583}.admin-color-sunrise .factory-bootstrap-500 .factory-dropdown.factory-buttons-way .active{background-color:#dd823b;-webkit-box-shadow:inset 0 1px 2px #c36822;box-shadow:inset 0 1px 2px #c36822;border-top:1px solid #c36822;border-bottom:1px solid #c36822;border-left:1px solid #c36822}.factory-bootstrap-500 .factory-dropdown.factory-ddslick-way .dd-select{background-color:#fff!important}.factory-bootstrap-500 .factory-dropdown.factory-ddslick-way label{margin-bottom:1px}.factory-bootstrap-500 .factory-dropdown.factory-ddslick-way .dd-option,.factory-bootstrap-500 .factory-dropdown.factory-ddslick-way .dd-selected{padding:8px 12px 8px 11px!important}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .factory-mtextbox-item{position:relative;margin-bottom:5px}.factory-bootstrap-500 .factory-mtextbox-item input,.factory-mtextbox-remove-item{display:inline-block}.factory-bootstrap-500 .factory-mtextbox-item .factory-mtextbox-remove-item{position:absolute;top:0;right:0;bottom:0;width:40px;border-radius:0 3px 3px 0;outline:0}.factory-bootstrap-500 .factory-mtextbox-item .factory-mtextbox-remove-item:focus,.factory-bootstrap-500 .factory-mtextbox-item .factory-mtextbox-remove-item:hover{box-shadow:none;outline:0}.factory-bootstrap-500 .factory-mtextbox-add-item{display:block;margin-top:10px}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
|
||||
.factory-bootstrap-500 .factory-more-link-content{border-top:1px dashed #DDD;padding-top:25px;width:100%;padding-right:20px;position:relative}.factory-bootstrap-500 .factory-tab .factory-more-link-show{display:inline-block;text-decoration:none;border-bottom:1px dotted #21759b;position:relative}.factory-bootstrap-500 .factory-tab .factory-more-link-show:hover{border-color:#d54e21}.factory-bootstrap-500 .factory-tab .factory-more-link-hide{position:absolute;margin-top:-35px;background-color:#fff;padding:0 5px;right:20px;color:#bbb;text-decoration:none}.factory-bootstrap-500 .factory-tab .factory-more-link-hide:hover{color:#999}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=factory-dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i<h.length-1&&i++,~i||(i=0),h.eq(i).focus()}}}},a.fn.factoryBootstrap500_dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.factoryBootstrap500_dropdown.Constructor=f,a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu]",f.prototype.keydown)}(jQuery);
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
!function(a){var b=function(b){var c=this;this.$element=a(b),this.$result=this.$element.find(".factory-result"),this.$on=this.$element.find(".factory-on"),this.$off=this.$element.find(".factory-off");var d=this.$element.is(".factory-tumbler"),e=this.$element.is(".factory-has-tumbler-hint"),f=this.$element.data("tumbler-function"),g=this.$element.data("tumbler-delay");g||(g=3e3),this.callByPath=function(a,b){for(var c=a.split("."),d=window,e=0;e<c.length;e++)d=d[c[e]];d.apply(d,b)},this.$on.click(function(){return c.$off.removeClass("active"),c.$on.addClass("active"),d?setTimeout(function(){c.$on.removeClass("active"),c.$off.addClass("active");var a=e?c.$element.next():null;f?c.callByPath(f,[c.$element,a]):e&&(c.$element.next().fadeIn(300),setTimeout(function(){c.$element.next().fadeOut(500)},g))},300):(c.$result.prop("checked",!0),c.$result.val(1),c.$result.trigger("change")),!1}),this.$off.click(function(){return c.$on.removeClass("active"),c.$off.addClass("active"),d?setTimeout(function(){c.$off.removeClass("active"),c.$on.addClass("active");var a=e?c.$element.next():null;f?c.callByPath(f,[c.$element,a]):e&&(c.$element.next().fadeIn(300),setTimeout(function(){c.$element.next().fadeOut(500)},g))},300):(c.$result.prop("checked",!1),c.$result.val(0),c.$result.trigger("change")),!1}),this.hashCode=function(a){var b=0;if(!a||0===a.length)return b;for(var c=0;c<a.length;c++){var d=a.charCodeAt(c);b=(b<<5)-b+d,b&=b}return b=b.toString(16),b=b.replace("-","")},this.executeEvents=function(a){(void 0!==window.__factory_checkbox_control_events_off_data||void 0!==window.__factory_checkbox_control_events_on_data)&&(a.change(function(){c.eventsProcess(a)}),c.eventsProcess(a))},this.eventsProcess=function(b){var d=b.attr("name"),e=b.prop("checked"),f=window.__factory_checkbox_control_events_on_data[d],g=window.__factory_checkbox_control_events_off_data[d];if(f||g){var h,i;void 0===window.__factory_checkbox_control_detach_elements&&(window.__factory_checkbox_control_detach_elements={}),h=window.__factory_checkbox_control_detach_elements,i=e?f:g;for(var j in i)if(i.hasOwnProperty(j)){var k,l=i[j];a.isArray(l)||(k=c.hashCode(d+l));var m;switch(j){case"hide":"string"==typeof l&&a(l).hide(0);break;case"show":"string"==typeof l&&a(l).fadeIn(200);break;case"detach":"string"==typeof l&&a(l).each(function(b){h[k]||(h[k]={}),h[k][b]||(h[k][b]={}),h[k][b].recovery_contanier=a(this).parent(),h[k][b].element=a(this).clone(!0),a(this).remove()});break;case"recovery":if(h[k]){for(var n in h[k])h[k].hasOwnProperty(n)&&h[k][n].recovery_contanier&&h[k][n].element&&h[k][n].recovery_contanier.append(h[k][n].element);delete h[k]}break;case"removeClasses":if("object"==typeof l)for(m in l)l.hasOwnProperty(m)&&l[m]&&a(m).removeClass(l[m]);break;case"addClasses":if("object"==typeof l)for(m in l)l.hasOwnProperty(m)&&l[m]&&a(m).addClass(l[m]);break;case"setValue":if("object"==typeof l)for(m in l)l.hasOwnProperty(m)&&void 0!==l[m]&&null!==l[m]&&a(m).val(l[m])}}}},this.executeEvents(this.$result)};a.fn.factoryBootstrap500_checkboxControl=function(c){if("string"==typeof c){var d=a(this).data("factory.checkbox.control");return d?d[c]():null}return this.each(function(){var c=a(this),d=c.data("factory.checkbox.control");d||c.data("factory.checkbox.control",d=new b(this))})},a.fn.factoryBootstrap500_checkboxControl.Constructor=b,a(function(){a(".factory-bootstrap-500 .factory-checkbox.factory-buttons-way").factoryBootstrap500_checkboxControl(),a(".factory-bootstrap-500 .factory-checkbox").not(".factory-buttons-way").click(function(){a(this).prop("checked")?a(this).val(1):a(this).val(0)})})}(jQuery);
|
||||
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
!function(a){var b=function(b){var c=this;if(this.$element=a(b),this.way=this.$element.data("way"),this.name=this.$element.data("name")||this.$element.attr("name"),this.hashCode=function(a){var b=0;if(!a||0===a.length)return b;for(var c=0;c<a.length;c++){var d=a.charCodeAt(c);b=(b<<5)-b+d,b&=b}return b=b.toString(16),b=b.replace("-","")},this.executeEvents=function(a){void 0!==window.factory_dropdown_control_events_data&&(a.change(function(){c.eventsProcess(a)}),c.eventsProcess(a))},this.eventsProcess=function(b){var d=b.attr("name"),e=b.val(),f=window.factory_dropdown_control_events_data[d];if(f&&f[e]){var g;void 0===window.__factory_dropdown_control_detach_elements&&(window.__factory_dropdown_control_detach_elements={}),g=window.__factory_dropdown_control_detach_elements;for(var h in f[e])if(f[e].hasOwnProperty(h)){var i,j=f[e][h];switch(a.isArray(j)||(i=c.hashCode(d+j)),h){case"hide":"string"==typeof j&&a(j).hide(0);break;case"show":"string"==typeof j&&a(j).fadeIn(200);break;case"detach":"string"==typeof j&&a(j).each(function(b){g[i]||(g[i]={}),g[i][b]||(g[i][b]={}),g[i][b].recovery_contanier=a(this).parent(),g[i][b].element=a(this).clone(!0),a(this).remove()});break;case"recovery":if(g[i]){for(var k in g[i])g[i].hasOwnProperty(k)&&g[i][k].recovery_contanier&&g[i][k].element&&g[i][k].recovery_contanier.append(g[i][k].element);delete g[i]}break;case"removeClasses":if("object"==typeof j)for(var l in j)j.hasOwnProperty(l)&&j[l]&&a(l).removeClass(j[l]);break;case"addClasses":if("object"==typeof j)for(var l in j)j.hasOwnProperty(l)&&j[l]&&a(l).addClass(j[l])}}}},"buttons"===this.way)this.$result=this.$element.find(".factory-result"),this.$hints=this.$element.find(".factory-hints"),this.$buttons=this.$element.find(".btn"),c.executeEvents(this.$result),this.$buttons.click(function(){var b=a(this).data("value");return c.$buttons.removeClass("active"),a(this).addClass("active"),c.$hints.find(".factory-hint").hide(),c.$hints.find(".factory-hint-"+b).fadeIn(),c.$result.val(b),c.$result.trigger("change"),!1});else if("ddslick"===this.way){c.executeEvents(c.$element.find(".factory-result"));var d=window["factory_"+this.name+"_data"],e=this.$element.find(".factory-ddslick"),f=this.$element.data("width")||300,g=this.$element.data("align")||"right";a(d).each(function(){return this.imageHoverSrc?void(a("<img/>")[0].src=this.imageHoverSrc):!0}),e.ddslick({data:d,width:f,imagePosition:g,selectText:"- select -",onSelected:function(a){a.selectedData.imageHoverSrc&&c.$element.find(".dd-selected-image").attr("src",a.selectedData.imageHoverSrc);var b=c.$element.find(".factory-result").val(a.selectedData.value);b.change()}})}else{c.executeEvents(this.$element),this.$hints=this.$element.next(),this.$hints.hasClass("factory-hints")&&(this.$element.change(function(){return c.updateHints(),!1}),this.updateHints=function(){var a=c.$element.val();c.$hints.find(".factory-hint").hide(),c.$hints.find(".factory-hint-"+a).show()},c.updateHints()),this.getAjaxData=function(){var a=c.$element.data("ajax-data-id");return window[a]},this.loadData=function(){var b=c.getAjaxData();a.ajax({url:b.url,data:b.data,dataType:"json",success:function(a){return a.error?c.showError(a.error):void c.fill(a.items)},error:function(a){console&&console.log&&console.log(a.responseText),c.showError("Unexpected error occurred during the ajax request.")},complete:function(){c.removeLoader()}})},this.fill=function(a){this.clearList();var b=c.getAjaxData();if(a&&a.length)for(var d in a){var e=a[d];c.addListItem(e)}else this.$element.append("<option>"+b.emptyList+"</li>");this.$element.trigger("factory-loaded")},this.clearList=function(){this.$element.html("")},this.addListItem=function(b){var d=a("<option />").attr("value",b.value).text(b.title).appendTo(this.$element),e=c.getAjaxData();e.selected&&e.selected==b.value&&d.attr("selected","selected")},this.showError=function(b){this.clearList();var d=a("<div class='factory-control-error'></div>").append(a("<i class='fa fa-exclamation-triangle'></i>")).append(b),e=c.getAjaxData();this.$element.append("<option>"+e.emptyList+"</li>"),this.$element.after(d),this.$element.addClass("factory-has-error")},this.removeLoader=function(){this.$element.removeClass("factory-hidden");var b=c.getAjaxData();a(b.loader).remove()};var h=this.$element.data("ajax");h&&this.loadData()}};a.fn.factoryBootstrap500_dropdownControl=function(c){if("string"==typeof c){var d=a(this).data("factory.dropdown.control");return d?d[c]():null}return this.each(function(){var c=a(this),d=c.data("factory.dropdown.control");d||c.data("factory.dropdown.control",d=new b(this))})},a.fn.factoryBootstrap500_dropdownControl.Constructor=b,a(function(){a(".factory-bootstrap-500 .factory-dropdown").factoryBootstrap500_dropdownControl()})}(jQuery);
|
||||
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
!function(a){var b=function(b){var c=this;if(this.$element=a(b),this.way=this.$element.data("way"),this.name=this.$element.data("name"),"checklist"===this.way){this.getAjaxData=function(){var a=c.$element.data("ajax-data-id");return window[a]},this.loadData=function(){var b=c.getAjaxData();a.ajax({url:b.url,data:b.data,dataType:"json",success:function(a){return a.error?c.showError(a.error):void c.fill(a.items)},error:function(){c.showError("Unexpected error occurred during the ajax request.")},complete:function(){c.removeLoader()}})},this.fill=function(a){this.clearList();var b=c.getAjaxData();if(a&&a.length){this.$element.removeClass("factory-empty");for(var d in a){var e=a[d];c.addListItem(e)}}else this.$element.addClass("factory-empty"),this.$element.append("<li>"+b.emptyList+"</li>")},this.clearList=function(){this.$element.html("")},this.addListItem=function(b){var d=a("<li>"),e=a("<label>").attr("for","factory-checklist-"+c.name+"-"+b.value).appendTo(d),f=a("<span>").appendTo(e),g=a("<input />").attr("type","checkbox").attr("name",c.name+"[]").val(b.value).attr("id","factory-checklist-"+c.name+"-"+b.value).appendTo(f),h=(a("<span>"+b.title+"</span>").appendTo(e),c.getAjaxData());h.selected.length&&a.inArray(b.value,h.selected)>=0&&g.attr("checked","checked"),this.$element.append(d)},this.showError=function(b){this.$element.html("").append(a("<i class='fa fa-exclamation-triangle'></i>")).append(b),this.$element.addClass("factory-list-error")},this.removeLoader=function(){this.$element.removeClass("factory-hidden");var b=c.getAjaxData();a(b.loader).remove()};var d=this.$element.data("ajax");d&&this.loadData()}};a.fn.factoryBootstrap500_listControl=function(c){if("string"==typeof c){var d=a(this).data("factory.list.control");return d?d[c]():null}return this.each(function(){var c=a(this),d=c.data("factory.list.control");d||c.data("factory.list.control",d=new b(this))})},a.fn.factoryBootstrap500_listControl.Constructor=b,a(function(){a(".factory-bootstrap-500 .factory-list").factoryBootstrap500_listControl()})}(jQuery);
|
||||
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* Bootstrap generator - v1.0.1, 2021-11-19
|
||||
*/
|
||||
|
||||
!function(a){"use strict";var b=function(b){this.$element=a(b);var c=a(".factory-mtextbox-item",this.$element).eq(0).clone(!0);a(".factory-mtextbox-add-item",this.$element).on("click",function(){var b=a(this).closest(".factory-multiple-textbox-group").find(".factory-mtextbox-items"),d=c.clone(!0),e=a('<button class="btn btn-default btn-small factory-mtextbox-remove-item"><i class="fa fa-times" aria-hidden="true"></i></button>');return b.append(d.append(e)),d.find('input[type="text"]').val("").focus(),!1}),a(document).on("click",".factory-mtextbox-remove-item",function(){return a(this).closest(".factory-mtextbox-item").remove(),!1})};a.fn.factoryBootstrap500_MultipleTextboxControl=function(){return this.each(function(){new b(this)})},a(function(){a(".factory-bootstrap-500 .factory-multiple-textbox-group").factoryBootstrap500_MultipleTextboxControl()})}(jQuery);
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* Factory Bootstrap
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package factory-bootstrap
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// module provides function only for the admin area
|
||||
if ( ! is_admin() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( defined( 'FACTORY_BOOTSTRAP_500_LOADED' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
define( 'FACTORY_BOOTSTRAP_500_VERSION', '5.0.2' );
|
||||
|
||||
define( 'FACTORY_BOOTSTRAP_500_LOADED', true );
|
||||
|
||||
if ( ! defined( 'FACTORY_FLAT_ADMIN' ) ) {
|
||||
define( 'FACTORY_FLAT_ADMIN', true );
|
||||
}
|
||||
|
||||
define( 'FACTORY_BOOTSTRAP_500_DIR', __DIR__ );
|
||||
define( 'FACTORY_BOOTSTRAP_500_URL', plugins_url( '', __FILE__ ) );
|
||||
|
||||
require_once FACTORY_BOOTSTRAP_500_DIR . '/includes/functions.php';
|
||||
|
||||
/**
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
*/
|
||||
add_action(
|
||||
'wbcr_factory_bootstrap_500_plugin_created',
|
||||
function ( $plugin ) {
|
||||
$manager = new Wbcr_FactoryBootstrap500_Manager( $plugin );
|
||||
$plugin->setBootstap( $manager );
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
/**
|
||||
* This file manages assets of the Factory Bootstap.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package factory-bootstrap
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Bootstrap Manager class.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
class Wbcr_FactoryBootstrap500_Manager {
|
||||
|
||||
/**
|
||||
* A plugin for which the manager was created.
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @var Wbcr_Factory600_Plugin
|
||||
*/
|
||||
public $plugin;
|
||||
|
||||
/**
|
||||
* Contains scripts to include.
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @var string[]
|
||||
*/
|
||||
public $scripts = [];
|
||||
|
||||
/**
|
||||
* Contains styles to include.
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @var string[]
|
||||
*/
|
||||
public $styles = [];
|
||||
|
||||
/**
|
||||
* Createas a new instance of the license api for a given plugin.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin ) {
|
||||
$this->plugin = $plugin;
|
||||
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'loadAssets' ] );
|
||||
add_filter( 'admin_body_class', [ $this, 'adminBodyClass' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the Bootstrap scripts.
|
||||
*
|
||||
* @param array|string $scripts
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function enqueueScript( $scripts ) {
|
||||
if ( is_array( $scripts ) ) {
|
||||
foreach ( $scripts as $script ) {
|
||||
if ( ! in_array( $script, $this->scripts ) ) {
|
||||
$this->scripts[] = $script;
|
||||
}
|
||||
}
|
||||
} elseif ( ! in_array( $scripts, $this->scripts ) ) {
|
||||
$this->scripts[] = $scripts;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * Includes the Bootstrap styles.
|
||||
*
|
||||
* @param array|string $styles
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function enqueueStyle( $styles ) {
|
||||
|
||||
if ( is_array( $styles ) ) {
|
||||
foreach ( $styles as $style ) {
|
||||
if ( ! in_array( $style, $this->styles ) ) {
|
||||
$this->styles[] = $style;
|
||||
}
|
||||
}
|
||||
} elseif ( ! in_array( $styles, $this->styles ) ) {
|
||||
$this->styles[] = $styles;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads Bootstrap assets.
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
* @see admin_enqueue_scripts
|
||||
*/
|
||||
public function loadAssets( $hook ) {
|
||||
|
||||
do_action( 'wbcr_factory_600_bootstrap_enqueue_scripts', $hook );
|
||||
do_action( 'wbcr_factory_600_bootstrap_enqueue_scripts_' . $this->plugin->getPluginName(), $hook );
|
||||
|
||||
$dependencies = [];
|
||||
if ( ! empty( $this->scripts ) ) {
|
||||
$dependencies[] = 'jquery';
|
||||
$dependencies[] = 'jquery-ui-core';
|
||||
$dependencies[] = 'jquery-ui-widget';
|
||||
}
|
||||
|
||||
foreach ( $this->scripts as $script ) {
|
||||
switch ( $script ) {
|
||||
case 'plugin.iris':
|
||||
$dependencies[] = 'jquery-ui-widget';
|
||||
$dependencies[] = 'jquery-ui-slider';
|
||||
$dependencies[] = 'jquery-ui-draggable';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $this->scripts ) ) {
|
||||
$this->enqueueScripts( $this->scripts, 'js', $dependencies );
|
||||
}
|
||||
if ( ! empty( $this->styles ) ) {
|
||||
$this->enqueueScripts( $this->styles, 'css', $dependencies );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $scripts
|
||||
* @param string $type
|
||||
* @param array $dependencies
|
||||
*/
|
||||
protected function enqueueScripts( array $scripts, $type, array $dependencies ) {
|
||||
|
||||
$is_first = true;
|
||||
|
||||
/**
|
||||
* Sets permission for file caching and combining into one file.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
$cache_enable = apply_filters( 'wbcr/factory/bootstrap/cache_enable', true );
|
||||
|
||||
$cache_id = md5( implode( ',', $scripts ) . $type . $this->plugin->getPluginVersion() );
|
||||
$cache_dir_path = FACTORY_BOOTSTRAP_500_DIR . '/assets/cache/';
|
||||
$cache_dir_url = FACTORY_BOOTSTRAP_500_URL . '/assets/cache/';
|
||||
|
||||
$cache_filepath = $cache_dir_path . $cache_id . '.min.' . $type;
|
||||
$cache_fileurl = $cache_dir_url . $cache_id . '.min.' . $type;
|
||||
|
||||
if ( $cache_enable && file_exists( $cache_filepath ) ) {
|
||||
if ( $type == 'js' ) {
|
||||
wp_enqueue_script( 'wbcr-factory-bootstrap-cached', $cache_fileurl, $dependencies, $this->plugin->getPluginVersion() );
|
||||
} else {
|
||||
wp_enqueue_style( 'wbcr-factory-bootstrap-cached', $cache_fileurl, [], $this->plugin->getPluginVersion() );
|
||||
}
|
||||
} else {
|
||||
$cache_dir_exists = false;
|
||||
if ( ! file_exists( $cache_dir_path ) ) {
|
||||
if ( @mkdir( $cache_dir_path, 0755 ) && wp_is_writable( $cache_dir_path ) ) {
|
||||
$cache_dir_exists = true;
|
||||
}
|
||||
} elseif ( wp_is_writable( $cache_dir_path ) ) {
|
||||
$cache_dir_exists = true;
|
||||
}
|
||||
|
||||
$concat_files = [];
|
||||
foreach ( $scripts as $script_to_load ) {
|
||||
$script_to_load = sanitize_text_field( $script_to_load );
|
||||
if ( $cache_enable && $cache_dir_exists ) {
|
||||
$fname = FACTORY_BOOTSTRAP_500_DIR . "/assets/$type-min/$script_to_load.min." . $type;
|
||||
if ( file_exists( $fname ) ) {
|
||||
$f = @fopen( $fname, 'r' );
|
||||
$concat_files[] = @fread( $f, filesize( $fname ) );
|
||||
@fclose( $f );
|
||||
}
|
||||
} else {
|
||||
if ( $type == 'js' ) {
|
||||
wp_enqueue_script( md5( $script_to_load ), FACTORY_BOOTSTRAP_500_URL . "/assets/$type-min/$script_to_load.min." . $type, $is_first ? $dependencies : false, $this->plugin->getPluginVersion() );
|
||||
} else {
|
||||
wp_enqueue_style( md5( $script_to_load ), FACTORY_BOOTSTRAP_500_URL . "/assets/$type-min/$script_to_load.min." . $type, [], $this->plugin->getPluginVersion() );
|
||||
}
|
||||
$is_first = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $cache_enable && $cache_dir_exists && ! empty( $concat_files ) ) {
|
||||
|
||||
$cf = @fopen( $cache_filepath, 'w' );
|
||||
$write_content = implode( PHP_EOL, $concat_files );
|
||||
@fwrite( $cf, $write_content );
|
||||
@fclose( $cf );
|
||||
chmod( $cache_filepath, 0755 );
|
||||
|
||||
if ( file_exists( $cache_filepath ) ) {
|
||||
if ( $type == 'js' ) {
|
||||
wp_enqueue_script( 'wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, $dependencies, $this->plugin->getPluginVersion() );
|
||||
} else {
|
||||
wp_enqueue_style( 'wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, [], $this->plugin->getPluginVersion() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the body classes: 'factory-flat or 'factory-volumetric'.
|
||||
*
|
||||
* @param string $classes
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function adminBodyClass( $classes ) {
|
||||
$classes .= FACTORY_FLAT_ADMIN ? ' factory-flat ' : ' factory-volumetric ';
|
||||
|
||||
return $classes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
/**
|
||||
* Ajax plugin configuration
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
function wfactory_600_install_components( $plugin_instance ) {
|
||||
check_ajax_referer( 'updates' );
|
||||
|
||||
$slug = $plugin_instance->request->post( 'plugin', null, true );
|
||||
$action = $plugin_instance->request->post( 'plugin_action', null, true );
|
||||
$storage = $plugin_instance->request->post( 'storage', null, true );
|
||||
|
||||
if ( ! current_user_can( 'update_plugins' ) ) {
|
||||
wp_die( __( 'You don\'t have permission to perform this action.', 'robin-image-optimizer' ), __( 'Something went wrong. Please refresh and try again.', 'robin-image-optimizer' ), 403 );
|
||||
}
|
||||
|
||||
if ( empty( $slug ) || empty( $action ) ) {
|
||||
wp_send_json_error( [ 'error_message' => __( 'Required attributes are not passed or empty.', 'robin-image-optimizer' ) ] );
|
||||
}
|
||||
$success = false;
|
||||
$send_data = [];
|
||||
|
||||
if ( $storage == 'internal' ) {
|
||||
if ( $action == 'activate' ) {
|
||||
if ( $plugin_instance->activateComponent( $slug ) ) {
|
||||
$success = true;
|
||||
}
|
||||
} elseif ( $action == 'deactivate' ) {
|
||||
|
||||
if ( $plugin_instance->deactivateComponent( $slug ) ) {
|
||||
$success = true;
|
||||
}
|
||||
} else {
|
||||
wp_send_json_error( [ 'error_message' => __( 'You are trying to perform an invalid action.', 'robin-image-optimizer' ) ] );
|
||||
}
|
||||
} elseif ( $storage == 'WordPress' || $storage == 'creativemotion' ) {
|
||||
if ( ! empty( $slug ) ) {
|
||||
$network_wide = $plugin_instance->isNetworkActive();
|
||||
|
||||
if ( $action == 'activate' ) {
|
||||
$result = activate_plugin( $slug, '', $network_wide );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
wp_send_json_error( [ 'error_message' => $result->get_error_message() ] );
|
||||
}
|
||||
} elseif ( $action == 'deactivate' ) {
|
||||
deactivate_plugins( $slug, false, $network_wide );
|
||||
}
|
||||
|
||||
$success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $action == 'install' || $action == 'deactivate' ) {
|
||||
try {
|
||||
// Delete button
|
||||
$delete_button = $plugin_instance->get_delete_component_button( $storage, $slug );
|
||||
$send_data['delete_button'] = $delete_button->get_button();
|
||||
} catch ( Exception $e ) {
|
||||
wp_send_json_error( [ 'error_message' => $e->getMessage() ] );
|
||||
}
|
||||
}
|
||||
|
||||
// Если требуется обновить постоянные ссылки, даем сигнал, что пользователю, нужно показать
|
||||
// всплывающее уведомление.
|
||||
// todo: сделать более красивое решение с передачей текстовых сообщений
|
||||
/*
|
||||
if ( $action == 'deactivate' ) {
|
||||
$is_need_rewrite_rules = $plugin_instance->getPopulateOption( 'need_rewrite_rules' );
|
||||
if ( $is_need_rewrite_rules ) {
|
||||
$send_data['need_rewrite_rules'] = sprintf( '<span class="wbcr-clr-need-rewrite-rules-message">' . __( 'When you deactivate some components, permanent links may work incorrectly. If this happens, please, <a href="%s">update the permalinks</a>, so you could complete the deactivation.', 'wbcr_factory_600' ), admin_url( 'options-permalink.php' ) . '</span>' );
|
||||
}
|
||||
}*/
|
||||
|
||||
if ( $success ) {
|
||||
if ( 'wbcr_clearfy' === $plugin_instance->getPluginName() ) {
|
||||
do_action( 'wbcr_clearfy_update_component', $slug, $action, $storage );
|
||||
}
|
||||
do_action( "wfactory/updated_{$plugin_instance->getPluginName()}_component", $slug, $action, $storage );
|
||||
|
||||
wp_send_json_success( $send_data );
|
||||
}
|
||||
|
||||
wp_send_json_error( [ 'error_message' => __( 'An unknown error occurred during the activation of the component.', 'robin-image-optimizer' ) ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax event that calls the wbcr/clearfy/activated_component action,
|
||||
* to get the component to work. Usually this is a call to the installation functions,
|
||||
* but in some cases, overwriting permanent references or compatibility checks.
|
||||
*/
|
||||
function wfactory_600_prepare_component( $plugin_instance ) {
|
||||
check_ajax_referer( 'updates' );
|
||||
|
||||
$component_name = $plugin_instance->request->post( 'plugin', null, true );
|
||||
|
||||
if ( ! current_user_can( 'update_plugins' ) ) {
|
||||
wp_send_json_error( [ 'error_message' => __( 'You don\'t have permission to perform this action.', 'robin-image-optimizer' ) ], 403 );
|
||||
}
|
||||
|
||||
if ( empty( $component_name ) ) {
|
||||
wp_send_json_error( [ 'error_message' => __( 'Required attribute [component_name] is empty.', 'robin-image-optimizer' ) ] );
|
||||
}
|
||||
if ( 'wbcr_clearfy' === $plugin_instance->getPluginName() ) {
|
||||
do_action( 'wbcr/clearfy/activated_component', $component_name );
|
||||
}
|
||||
do_action( "wfactory/activated_{$plugin_instance->getPluginName()}_component", $component_name );
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax handler for installing a plugin.
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @see Plugin_Upgrader
|
||||
*
|
||||
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
|
||||
*/
|
||||
function wfactory_600_creativemotion_install_plugin( $plugin_instance ) {
|
||||
check_ajax_referer( 'updates' );
|
||||
|
||||
if ( empty( $_POST['slug'] ) ) {
|
||||
wp_send_json_error(
|
||||
[
|
||||
'slug' => '',
|
||||
'errorCode' => 'no_plugin_specified',
|
||||
'errorMessage' => __( 'No plugin specified.', 'robin-image-optimizer' ),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$status = [
|
||||
'install' => 'plugin',
|
||||
'slug' => sanitize_key( wp_unslash( $_POST['slug'] ) ),
|
||||
];
|
||||
|
||||
if ( ! current_user_can( 'install_plugins' ) ) {
|
||||
$status['errorMessage'] = __( 'Sorry, you are not allowed to install plugins on this site.', 'robin-image-optimizer' );
|
||||
wp_send_json_error( $status );
|
||||
}
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
||||
include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
|
||||
|
||||
$api = plugins_api(
|
||||
'plugin_information',
|
||||
[
|
||||
'slug' => sanitize_key( wp_unslash( $_POST['slug'] ) ),
|
||||
'fields' => [
|
||||
'sections' => false,
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
if ( is_wp_error( $api ) ) {
|
||||
$status['errorMessage'] = $api->get_error_message();
|
||||
wp_send_json_error( $status );
|
||||
}
|
||||
|
||||
$status['pluginName'] = $api->name;
|
||||
|
||||
$skin = new WP_Ajax_Upgrader_Skin();
|
||||
$upgrader = new Plugin_Upgrader( $skin );
|
||||
// $result = $upgrader->install($api->download_link);
|
||||
$result = $upgrader->install( 'https://clearfy.pro/components/download.php' );
|
||||
|
||||
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||
$status['debug'] = $skin->get_upgrade_messages();
|
||||
}
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
$status['errorCode'] = $result->get_error_code();
|
||||
$status['errorMessage'] = $result->get_error_message();
|
||||
wp_send_json_error( $status );
|
||||
} elseif ( is_wp_error( $skin->result ) ) {
|
||||
$status['errorCode'] = $skin->result->get_error_code();
|
||||
$status['errorMessage'] = $skin->result->get_error_message();
|
||||
wp_send_json_error( $status );
|
||||
} elseif ( $skin->get_errors()->has_errors() ) {
|
||||
$status['errorMessage'] = $skin->get_error_messages();
|
||||
wp_send_json_error( $status );
|
||||
} elseif ( is_null( $result ) ) {
|
||||
global $wp_filesystem;
|
||||
|
||||
$status['errorCode'] = 'unable_to_connect_to_filesystem';
|
||||
$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.', 'robin-image-optimizer' );
|
||||
|
||||
// Pass through the error from WP_Filesystem if one was raised.
|
||||
if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
|
||||
$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
|
||||
}
|
||||
|
||||
wp_send_json_error( $status );
|
||||
}
|
||||
|
||||
$install_status = install_plugin_install_status( $api );
|
||||
$pagenow = isset( $_POST['pagenow'] ) ? sanitize_key( $_POST['pagenow'] ) : '';
|
||||
|
||||
// If installation request is coming from import page, do not return network activation link.
|
||||
$plugins_url = ( 'import' === $pagenow ) ? admin_url( 'plugins.php' ) : network_admin_url( 'plugins.php' );
|
||||
|
||||
if ( current_user_can( 'activate_plugin', $install_status['file'] ) && is_plugin_inactive( $install_status['file'] ) ) {
|
||||
$status['activateUrl'] = add_query_arg(
|
||||
[
|
||||
'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $install_status['file'] ),
|
||||
'action' => 'activate',
|
||||
'plugin' => $install_status['file'],
|
||||
],
|
||||
$plugins_url
|
||||
);
|
||||
}
|
||||
|
||||
if ( is_multisite() && current_user_can( 'manage_network_plugins' ) && 'import' !== $pagenow ) {
|
||||
$status['activateUrl'] = add_query_arg( [ 'networkwide' => 1 ], $status['activateUrl'] );
|
||||
}
|
||||
|
||||
wp_send_json_success( $status );
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
var externalAddon = {
|
||||
init: function() {
|
||||
this.events();
|
||||
},
|
||||
events: function() {
|
||||
var self = this;
|
||||
|
||||
/**
|
||||
* This event is intended for installation, removal, activation, deactivation of external add-ons
|
||||
*/
|
||||
|
||||
$(document).on('click', '.wfactory-600-process-button', function() {
|
||||
var $this = $(this),
|
||||
button_i18n = $(this).data('i18n'),
|
||||
plugin_slug = $(this).data('slug'),
|
||||
plugin_action = $(this).data('plugin-action'),
|
||||
plugin = $(this).data('plugin'),
|
||||
storage = $(this).data('storage'),
|
||||
wpnonce = $(this).data('wpnonce');
|
||||
|
||||
var action = ('creativemotion' === storage)
|
||||
? 'wfactory-600-creativemotion-install-plugin'
|
||||
: 'install-plugin';
|
||||
|
||||
if( storage === 'freemius' || ((storage === 'wordpress' || storage === 'creativemotion' || storage === 'internal') && (plugin_action === 'activate' || plugin_action === 'deactivate')) ) {
|
||||
action = 'wfactory-600-intall-component';
|
||||
} else if( storage === 'wordpress' && plugin_action === 'delete' ) {
|
||||
action = 'delete-plugin';
|
||||
}
|
||||
|
||||
var data = {
|
||||
action: action,
|
||||
slug: plugin_slug,
|
||||
storage: storage,
|
||||
plugin: plugin,
|
||||
plugin_action: plugin_action,
|
||||
_wpnonce: wpnonce
|
||||
};
|
||||
|
||||
if( plugin_action === 'install' ) {
|
||||
$this.addClass('updating-message');
|
||||
}
|
||||
|
||||
$this.addClass('disabled').text(button_i18n.loading);
|
||||
|
||||
$.wfactory_600.hooks.run('core/components/pre_update', [$this, data]);
|
||||
|
||||
self.sendRequest(data, function(response) {
|
||||
if( !response || !response.success ) {
|
||||
$.wfactory_600.hooks.run('core/components/update_error', [
|
||||
$this,
|
||||
data,
|
||||
response
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( response.success ) {
|
||||
$this.removeClass('disabled').removeClass('updating-message');
|
||||
|
||||
if( plugin_action === 'install' ) {
|
||||
|
||||
plugin_action = 'activate';
|
||||
$this.data('plugin-action', 'activate');
|
||||
$this.attr('data-plugin-action', 'activate');
|
||||
|
||||
if( $this.hasClass('button') ) {
|
||||
$this.removeClass('button-default').addClass('button-primary');
|
||||
}
|
||||
|
||||
$.wfactory_600.hooks.run('core/components/installed', [
|
||||
$this,
|
||||
data,
|
||||
response
|
||||
]);
|
||||
|
||||
} else if( plugin_action === 'activate' ) {
|
||||
|
||||
plugin_action = 'deactivate';
|
||||
$this.data('plugin-action', 'deactivate');
|
||||
$this.attr('data-plugin-action', 'deactivate');
|
||||
|
||||
if( $this.hasClass('button') ) {
|
||||
$this.removeClass('button-primary').addClass('button-default');
|
||||
}
|
||||
|
||||
$.wfactory_600.hooks.run('core/components/pre_activate', [
|
||||
$this,
|
||||
data,
|
||||
response
|
||||
]);
|
||||
|
||||
/**
|
||||
* Send an additional request for activation of the component, during activation
|
||||
* perform the action wbcr/clearfy/activated_component.
|
||||
*
|
||||
* Basically, this is necessary to prepare the plugin to work, write the necessary rows and
|
||||
* tables in the database, rewriting permalinks, checking conflicts, etc.
|
||||
*/
|
||||
if( storage === 'freemius' || storage === 'internal' ) {
|
||||
self.sendRequestToComponentActivationPrepare($this, data, button_i18n);
|
||||
return;
|
||||
}
|
||||
|
||||
} else if( plugin_action === 'deactivate' ) {
|
||||
|
||||
plugin_action = 'activate';
|
||||
$this.data('plugin-action', 'activate');
|
||||
$this.attr('data-plugin-action', 'activate');
|
||||
|
||||
if( $this.hasClass('button') ) {
|
||||
$this.removeClass('button-default').addClass('button-primary');
|
||||
}
|
||||
|
||||
$.wfactory_600.hooks.run('core/components/deactivated', [
|
||||
$this,
|
||||
data,
|
||||
response
|
||||
]);
|
||||
|
||||
} else if( plugin_action === 'delete' ) {
|
||||
|
||||
plugin_action = 'install';
|
||||
|
||||
$.wfactory_600.hooks.run('core/components/deleted', [$this, data, response]);
|
||||
}
|
||||
} else {
|
||||
if( plugin_action === 'install' ) {
|
||||
$this.removeClass('updating-message');
|
||||
}
|
||||
}
|
||||
|
||||
$this.text(button_i18n[plugin_action]);
|
||||
|
||||
$.wfactory_600.hooks.run('core/components/updated', [$this, data, response]);
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Отправляет дополнительный запрос на активацию компонента, во время активации
|
||||
* выполняет хук wbcr/clearfy/activated_component.
|
||||
*
|
||||
* В принципе, это необходимо для подготовки плагина к работе, записи необходимых строк и таблиц в
|
||||
* базу данных, перепись постоянных ссылок, проверка конфликтов и т.д.
|
||||
*
|
||||
* @param {object} componentButton
|
||||
* @param {object} sendData
|
||||
* @param {object} button_i18n
|
||||
*/
|
||||
sendRequestToComponentActivationPrepare: function(componentButton, sendData, button_i18n) {
|
||||
var self = this;
|
||||
|
||||
componentButton.addClass('button-primary')
|
||||
.addClass('disabled')
|
||||
.text(button_i18n.preparation);
|
||||
|
||||
sendData.action = 'wfactory-600-prepare-component';
|
||||
|
||||
this.sendRequest(sendData, function(response) {
|
||||
componentButton.removeClass('disabled');
|
||||
|
||||
if( !response || !response.success ) {
|
||||
componentButton.text(button_i18n['activate']);
|
||||
|
||||
$.wfactory_600.hooks.run('core/components/activation_error', [
|
||||
componentButton,
|
||||
sendData,
|
||||
response
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
componentButton.removeClass('button-primary').text(button_i18n['deactivate']);
|
||||
|
||||
$.wfactory_600.hooks.run('core/components/activated', [
|
||||
componentButton,
|
||||
sendData,
|
||||
response
|
||||
]);
|
||||
});
|
||||
},
|
||||
|
||||
sendRequest: function(data, callback) {
|
||||
var self = this;
|
||||
|
||||
$.ajax(ajaxurl, {
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
data: data,
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
callback && callback(data);
|
||||
},
|
||||
error: function(xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(xhr.responseText);
|
||||
console.log(thrownError);
|
||||
|
||||
$.wfactory_600.hooks.run('core/components/ajax_error', [
|
||||
xhr,
|
||||
ajaxOptions,
|
||||
thrownError
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
externalAddon.init();
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
if( !$.wfactory_600 ) {
|
||||
$.wfactory_600 = {};
|
||||
}
|
||||
|
||||
$.wfactory_600.filters = $.wfactory_600.filters || {
|
||||
|
||||
/**
|
||||
* A set of registered filters.
|
||||
*/
|
||||
_items: {},
|
||||
|
||||
/**
|
||||
* A set of priorities of registered filters.
|
||||
*/
|
||||
_priorities: {},
|
||||
|
||||
/**
|
||||
* Applies filters to a given input value.
|
||||
*/
|
||||
run: function(filterName, args) {
|
||||
var input = args && args.length > 0 ? args[0] : null;
|
||||
if( !this._items[filterName] ) {
|
||||
return input;
|
||||
}
|
||||
|
||||
for( var i in this._priorities[filterName] ) {
|
||||
if( !this._priorities[filterName].hasOwnProperty(i) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var priority = this._priorities[filterName][i];
|
||||
|
||||
for( var k = 0; k < this._items[filterName][priority].length; k++ ) {
|
||||
var f = this._items[filterName][priority][k];
|
||||
input = f.apply(f, args);
|
||||
}
|
||||
}
|
||||
|
||||
return input;
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers a new filter.
|
||||
*/
|
||||
add: function(filterName, callback, priority) {
|
||||
|
||||
if( !priority ) {
|
||||
priority = 10;
|
||||
}
|
||||
|
||||
if( !this._items[filterName] ) {
|
||||
this._items[filterName] = {};
|
||||
}
|
||||
if( !this._items[filterName][priority] ) {
|
||||
this._items[filterName][priority] = [];
|
||||
}
|
||||
this._items[filterName][priority].push(callback);
|
||||
|
||||
if( !this._priorities[filterName] ) {
|
||||
this._priorities[filterName] = [];
|
||||
}
|
||||
if( $.inArray(priority, this._priorities[filterName]) === -1 ) {
|
||||
this._priorities[filterName].push(priority);
|
||||
}
|
||||
|
||||
this._priorities[filterName].sort(function(a, b) {
|
||||
return a - b;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$.wfactory_600.hooks = $.wfactory_600.hooks || {
|
||||
|
||||
/**
|
||||
* Applies filters to a given input value.
|
||||
*/
|
||||
run: function(filterName, args) {
|
||||
$.wfactory_600.filters.run(filterName, args);
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers a new filter.
|
||||
*/
|
||||
add: function(filterName, callback, priority) {
|
||||
$.wfactory_600.filters.add(filterName, callback, priority);
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* Factory Plugin
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package core
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( defined( 'FACTORY_600_LOADED' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
define( 'FACTORY_600_LOADED', true );
|
||||
|
||||
define( 'FACTORY_600_VERSION', '6.0.0' );
|
||||
|
||||
define( 'FACTORY_600_DIR', __DIR__ );
|
||||
define( 'FACTORY_600_URL', plugins_url( '', __FILE__ ) );
|
||||
|
||||
add_action(
|
||||
'init',
|
||||
function () {
|
||||
load_plugin_textdomain( 'robin-image-optimizer', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
|
||||
}
|
||||
);
|
||||
|
||||
// comp merge
|
||||
require_once FACTORY_600_DIR . '/includes/functions.php';
|
||||
|
||||
require_once FACTORY_600_DIR . '/includes/entities/class-factory-paths.php';
|
||||
require_once FACTORY_600_DIR . '/includes/entities/class-factory-support.php';
|
||||
|
||||
require_once FACTORY_600_DIR . '/includes/class-factory-requests.php';
|
||||
require_once FACTORY_600_DIR . '/includes/class-factory-options.php';
|
||||
require_once FACTORY_600_DIR . '/includes/class-factory-plugin-base.php';
|
||||
require_once FACTORY_600_DIR . '/includes/class-factory-migrations.php';
|
||||
require_once FACTORY_600_DIR . '/includes/class-factory-notices.php';
|
||||
|
||||
// ASSETS
|
||||
require_once FACTORY_600_DIR . '/includes/assets-managment/class-factory-assets-list.php';
|
||||
require_once FACTORY_600_DIR . '/includes/assets-managment/class-factory-script-list.php';
|
||||
require_once FACTORY_600_DIR . '/includes/assets-managment/class-factory-style-list.php';
|
||||
|
||||
// PREMIUM
|
||||
require_once FACTORY_600_DIR . '/includes/premium/class-factory-license-interface.php';
|
||||
require_once FACTORY_600_DIR . '/includes/premium/class-factory-provider-abstract.php';
|
||||
require_once FACTORY_600_DIR . '/includes/premium/class-factory-manager.php';
|
||||
|
||||
// UPDATES
|
||||
require_once FACTORY_600_DIR . '/includes/updates/repositories/class-factory-repository-abstract.php';
|
||||
require_once FACTORY_600_DIR . '/includes/updates/repositories/class-factory-wordpress.php';
|
||||
require_once FACTORY_600_DIR . '/includes/updates/repositories/class-factory-github.php';
|
||||
require_once FACTORY_600_DIR . '/includes/updates/class-factory-upgrader.php';
|
||||
require_once FACTORY_600_DIR . '/includes/updates/class-factory-premium-upgrader.php';
|
||||
|
||||
require_once FACTORY_600_DIR . '/includes/class-factory-plugin-abstract.php';
|
||||
|
||||
require_once FACTORY_600_DIR . '/includes/activation/class-factory-activator.php';
|
||||
require_once FACTORY_600_DIR . '/includes/activation/class-factory-update.php';
|
||||
// endcomp
|
||||
|
||||
add_action(
|
||||
'admin_enqueue_scripts',
|
||||
function () {
|
||||
wp_enqueue_script(
|
||||
'wfactory-600-core-general',
|
||||
FACTORY_600_URL . '/assets/js/core-general.js',
|
||||
[
|
||||
'jquery',
|
||||
],
|
||||
FACTORY_600_VERSION
|
||||
);
|
||||
wp_enqueue_script(
|
||||
'wfactory-600-core-components',
|
||||
FACTORY_600_URL . '/assets/js/core-components.js',
|
||||
[
|
||||
'jquery',
|
||||
'wfactory-600-core-general',
|
||||
],
|
||||
FACTORY_600_VERSION
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains a base class for plugin activators.
|
||||
*
|
||||
* @package factory-core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Plugin Activator
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
abstract class Wbcr_Factory600_Activator {
|
||||
|
||||
/**
|
||||
* Curent plugin.
|
||||
*
|
||||
* @var Wbcr_Factory600_Plugin
|
||||
*/
|
||||
public $plugin;
|
||||
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin ) {
|
||||
$this->plugin = $plugin;
|
||||
}
|
||||
|
||||
public function activate() {
|
||||
}
|
||||
|
||||
public function deactivate() {
|
||||
}
|
||||
|
||||
public function update() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains a base class for update items of plugins.
|
||||
*
|
||||
* @package factory-core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Plugin Activator
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
abstract class Wbcr_Factory600_Update {
|
||||
|
||||
/**
|
||||
* Current plugin
|
||||
*
|
||||
* @var Wbcr_Factory600_Plugin
|
||||
*/
|
||||
var $plugin;
|
||||
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin ) {
|
||||
$this->plugin = $plugin;
|
||||
}
|
||||
|
||||
abstract function install();
|
||||
|
||||
// abstract function rollback();
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* The class contains a base class for all lists of assets.
|
||||
*
|
||||
* @package factory-core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assets List
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_Factory600_AssetsList {
|
||||
|
||||
protected $all = [];
|
||||
public $header_place = [];
|
||||
public $footer_place = [];
|
||||
public $required = [];
|
||||
|
||||
protected $default_place;
|
||||
|
||||
/**
|
||||
* @var Wbcr_Factory600_Plugin
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
* @param bool $defaultIsFooter
|
||||
*/
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin, $defaultIsFooter = true ) {
|
||||
$this->plugin = $plugin;
|
||||
|
||||
if ( $defaultIsFooter ) {
|
||||
$this->default_place = &$this->footer_place;
|
||||
}
|
||||
if ( ! $defaultIsFooter ) {
|
||||
$this->default_place = &$this->header_place;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove items from the collection
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function deregister() {
|
||||
foreach ( func_get_args() as $item ) {
|
||||
|
||||
if ( ! is_string( $item ) ) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$key_in_all = array_search( $item, $this->all );
|
||||
$key_in_default_place = array_search( $item, $this->default_place );
|
||||
$key_in_header_place = array_search( $item, $this->header_place );
|
||||
$key_inFooterPlace = array_search( $item, $this->footer_place );
|
||||
|
||||
if ( $key_in_all ) {
|
||||
unset( $this->all[ $key_in_all ] );
|
||||
}
|
||||
if ( $key_in_default_place ) {
|
||||
unset( $this->default_place[ $key_in_default_place ] );
|
||||
}
|
||||
if ( $key_in_header_place ) {
|
||||
unset( $this->header_place[ $key_in_header_place ] );
|
||||
}
|
||||
if ( $key_inFooterPlace ) {
|
||||
unset( $this->footer_place[ $key_inFooterPlace ] );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the collection is empty.
|
||||
*
|
||||
* @param string $source if the 'bootstrap' specified, checks only whether the bootstrap assets were required.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isEmpty( $source = 'WordPress' ) {
|
||||
if ( 'bootstrap' === $source ) {
|
||||
return empty( $this->required[ $source ] );
|
||||
}
|
||||
|
||||
return empty( $this->all ) && empty( $this->required );
|
||||
}
|
||||
|
||||
public function IsHeaderEmpty() {
|
||||
return empty( $this->header_place );
|
||||
}
|
||||
|
||||
public function IsFooterEmpty() {
|
||||
return empty( $this->footer_place );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new items to the requried collection.
|
||||
*
|
||||
* @param mixed
|
||||
*/
|
||||
public function request( $items, $source = 'WordPress' ) {
|
||||
|
||||
if ( is_array( $items ) ) {
|
||||
foreach ( $items as $item ) {
|
||||
$this->required[ $source ][] = $item;
|
||||
}
|
||||
} else {
|
||||
$this->required[ $source ][] = $items;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains a class to manage script assets.
|
||||
*
|
||||
* @package factory-core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Script List
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_Factory600_ScriptList extends Wbcr_Factory600_AssetsList {
|
||||
|
||||
public $localize_data = [];
|
||||
public $use_ajax = false;
|
||||
|
||||
/**
|
||||
* Adds new items to the collection (default place).
|
||||
*
|
||||
* @param mixed
|
||||
*
|
||||
* @version 2.0
|
||||
*/
|
||||
public function add( $file_url, $deps = [ 'jquery' ], $handle = null, $version = false, $place = 'default' ) {
|
||||
|
||||
if ( empty( $file_url ) ) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$resource = [];
|
||||
$resource['file_url'] = $file_url;
|
||||
$resource['deps'] = $deps;
|
||||
$resource['handle'] = $handle;
|
||||
$resource['version'] = $version;
|
||||
|
||||
$this->all[] = $resource;
|
||||
|
||||
switch ( $place ) {
|
||||
case 'header':
|
||||
$this->header_place[] = $resource;
|
||||
break;
|
||||
case 'footer':
|
||||
$this->footer_place[] = $resource;
|
||||
break;
|
||||
default:
|
||||
$this->default_place[] = $resource;
|
||||
break;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new items to the collection (header).
|
||||
*
|
||||
* @param mixed
|
||||
*/
|
||||
public function addToHeader( $file_url, $deps = [ 'jquery' ], $handle = null ) {
|
||||
return $this->add( $file_url, $deps, $handle, 'header' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new items to the collection (footer).
|
||||
*
|
||||
* @param mixed
|
||||
*/
|
||||
public function addToFooter( $file_url, $deps = [ 'jquery' ], $handle = null ) {
|
||||
return $this->add( $file_url, $deps, $handle, 'footer' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Осуществляет подключение всех зарегистрированных скриптов
|
||||
*
|
||||
* @param string $source
|
||||
*/
|
||||
public function connect( $source = 'WordPress' ) {
|
||||
|
||||
// register all global required scripts
|
||||
if ( ! empty( $this->required[ $source ] ) ) {
|
||||
foreach ( $this->required[ $source ] as $script ) {
|
||||
if ( 'WordPress' === $source ) {
|
||||
wp_enqueue_script( $script );
|
||||
} elseif ( 'bootstrap' === $source ) {
|
||||
$this->plugin->bootstrap->enqueueScript( $script );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $source == 'bootstrap' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$is_first_script = true;
|
||||
$is_footer = false;
|
||||
|
||||
// register all other scripts
|
||||
foreach ( [ $this->header_place, $this->footer_place ] as $script_place ) {
|
||||
foreach ( $script_place as $script ) {
|
||||
|
||||
if ( empty( $script['file_url'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$handle = ! empty( $script['handle'] ) ? $script['handle'] : $script['file_url'];
|
||||
$deps = ! is_array( $script['deps'] ) ? [] : $script['deps'];
|
||||
$version = ! empty( $script['version'] ) ? $script['version'] : $this->plugin->getPluginVersion();
|
||||
|
||||
wp_register_script( $handle, $script['file_url'], $deps, $version, $is_footer );
|
||||
|
||||
if ( $is_first_script && $this->use_ajax ) {
|
||||
wp_localize_script( $handle, 'factory', [ 'ajaxurl' => admin_url( 'admin-ajax.php' ) ] );
|
||||
}
|
||||
|
||||
if ( ! empty( $this->localize_data[ $handle ] ) ) {
|
||||
wp_localize_script( $handle, $this->localize_data[ $handle ][0], $this->localize_data[ $handle ][1] );
|
||||
}
|
||||
|
||||
wp_enqueue_script( $handle );
|
||||
|
||||
$is_first_script = false;
|
||||
}
|
||||
|
||||
$is_footer = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Если вызвать этот метод, на странице будет обязательно добавлена
|
||||
* глобальная JS переменная с ссылкой на ajax обработчик
|
||||
*/
|
||||
public function useAjax() {
|
||||
$this->use_ajax = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует глобальную JS переменную с пользовательскими данными
|
||||
*
|
||||
* @param string $varname
|
||||
* @param array $data
|
||||
*
|
||||
* @return Wbcr_Factory600_ScriptList $this
|
||||
*/
|
||||
public function localize( $varname, $data ) {
|
||||
$bindTo = count( $this->all ) == 0 ? null : end( $this->all );
|
||||
|
||||
if ( ! $bindTo ) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$handle = ! empty( $bindTo['handle'] ) ? $bindTo['handle'] : $bindTo['file_url'];
|
||||
$this->localize_data[ $handle ] = [ $varname, $data ];
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains a class to manage style assets.
|
||||
*
|
||||
* @package factory-core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Style List
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_Factory600_StyleList extends Wbcr_Factory600_AssetsList {
|
||||
|
||||
/**
|
||||
* Adds new items to the collection (default place).
|
||||
*
|
||||
* @param mixed
|
||||
*
|
||||
* @version 2.0
|
||||
*/
|
||||
public function add( $file_url, $deps = [], $handle = null, $version = false, $media = 'all' ) {
|
||||
|
||||
if ( empty( $file_url ) ) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$resource = [];
|
||||
$resource['file_url'] = $file_url;
|
||||
$resource['deps'] = $deps;
|
||||
$resource['handle'] = $handle;
|
||||
$resource['version'] = $version;
|
||||
$resource['media'] = $media;
|
||||
|
||||
$this->all[] = $resource;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function connect( $source = 'WordPress' ) {
|
||||
// register all global required scripts
|
||||
if ( ! empty( $this->required[ $source ] ) ) {
|
||||
|
||||
foreach ( $this->required[ $source ] as $style ) {
|
||||
if ( 'WordPress' === $source ) {
|
||||
wp_enqueue_style( $style );
|
||||
} elseif ( 'bootstrap' === $source ) {
|
||||
$this->plugin->bootstrap->enqueueStyle( $style );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $source == 'bootstrap' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( empty( $this->all ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// register all other styles
|
||||
foreach ( $this->all as $style ) {
|
||||
|
||||
if ( empty( $style['file_url'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$handle = ! empty( $style['handle'] ) ? $style['handle'] : md5( $style['file_url'] );
|
||||
$deps = ! is_array( $style['deps'] ) ? [] : $style['deps'];
|
||||
$version = ! empty( $style['version'] ) ? $style['version'] : $this->plugin->getPluginVersion();
|
||||
|
||||
wp_enqueue_style( $handle, $style['file_url'], $deps, $version );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Проверяет совместимость с плагинами, с версиями php, с версиями WordPress
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @since 4.0.8
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'Wbcr_Factory_Compatibility' ) ) {
|
||||
class Wbcr_Factory_Compatibility {
|
||||
|
||||
protected $plugin_prefix;
|
||||
protected $plugin_class_prefix;
|
||||
protected $plugin_name;
|
||||
protected $plugin_title = '(no title)';
|
||||
protected $required_php_version = '5.3';
|
||||
protected $required_wp_version = '4.2.0';
|
||||
|
||||
function __construct( array $plugin_info ) {
|
||||
foreach ( (array) $plugin_info as $property => $value ) {
|
||||
$this->$property = $value;
|
||||
}
|
||||
|
||||
add_action( 'admin_init', [ $this, 'registerNotices' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод проверяет совместимость плагина с php и WordPress версией
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function check() {
|
||||
if ( ! $this->isPhpCompatibility() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->isWpCompatibility() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод проверяет совместимость плагина с php версией сервера
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function isPhpCompatibility() {
|
||||
return version_compare( PHP_VERSION, $this->required_php_version, '>=' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод проверяет совместимость плагина с WordPress версией сайта
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function isWpCompatibility() {
|
||||
// Get the WP Version global.
|
||||
global $wp_version;
|
||||
|
||||
return version_compare( $wp_version, $this->required_wp_version, '>=' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод возвращает текст уведомления
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNoticeText() {
|
||||
$notice_text = $notice_default_text = '';
|
||||
$notice_default_text .= '<b>' . $this->plugin_title . ' ' . __( 'warning', 'robin-image-optimizer' ) . ':</b>' . '<br>';
|
||||
|
||||
// translators: %s is the plugin title
|
||||
$notice_default_text .= sprintf( __( 'The %s plugin has stopped.', 'robin-image-optimizer' ), $this->plugin_title ) . ' ';
|
||||
$notice_default_text .= __( 'Possible reasons:', 'robin-image-optimizer' ) . ' <br>';
|
||||
|
||||
$has_one = false;
|
||||
|
||||
if ( ! $this->isPhpCompatibility() ) {
|
||||
$has_one = true;
|
||||
// translators: %s is the required php version
|
||||
$notice_text .= '- ' . sprintf( __( 'You need to update the PHP version to %s or higher!', 'robin-image-optimizer' ), $this->required_php_version ) . '<br>';
|
||||
}
|
||||
|
||||
if ( ! $this->isWpCompatibility() ) {
|
||||
$has_one = true;
|
||||
// translators: %s is the required WordPress version
|
||||
$notice_text .= '- ' . sprintf( __( 'You need to update WordPress to %s or higher!', 'robin-image-optimizer' ), $this->required_wp_version ) . '<br>';
|
||||
}
|
||||
|
||||
if ( $has_one ) {
|
||||
$notice_text = $notice_default_text . $notice_text;
|
||||
}
|
||||
|
||||
return $notice_text;
|
||||
}
|
||||
|
||||
public function registerNotices() {
|
||||
if ( current_user_can( 'activate_plugins' ) && current_user_can( 'edit_plugins' ) && current_user_can( 'install_plugins' ) ) {
|
||||
if ( is_multisite() ) {
|
||||
add_action( 'network_admin_notices', [ $this, 'showNotice' ] );
|
||||
}
|
||||
|
||||
add_action( 'admin_notices', [ $this, 'showNotice' ] );
|
||||
}
|
||||
}
|
||||
|
||||
public function showNotice() {
|
||||
$notice_text = $this->getNoticeText();
|
||||
|
||||
if ( empty( $notice_text ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$notice_text = '<p>' . $this->getNoticeText() . '</p>';
|
||||
|
||||
echo '<div class="notice notice-error">' . esc_html( apply_filters( 'wbcr/factory/check_compatibility/notice_text', $notice_text, $this->plugin_name ) ) . '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,540 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600;
|
||||
|
||||
use Exception;
|
||||
use Wbcr_Factory600_Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Often when updating plugins, you need to make some changes to the database.
|
||||
* This class automatically checks for plugin migrations and executes them when
|
||||
* updating.
|
||||
*
|
||||
* The class has a debug mode, to enable the debug mode add constants to your plugin:
|
||||
* define ('FACTORY_MIGRATIONS_DEBUG', true) - enables/disables debugging mode
|
||||
* define ('FACTORY_MIGRATIONS_FORCE_OLD_VERSION', '1.1.9') - sets previous version
|
||||
* for the plugin, if constant isn't set, then the previous version is taken from
|
||||
* the database.
|
||||
*
|
||||
* todo: get_option and get_site_option are used because some caching plugins caching options, which causes problems
|
||||
*
|
||||
* @since 4.1.1
|
||||
*/
|
||||
class Migrations {
|
||||
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* Migrations constructor.
|
||||
*
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin ) {
|
||||
|
||||
$this->plugin = $plugin;
|
||||
$plugin_name = $plugin->getPluginName();
|
||||
|
||||
if ( ! file_exists( $this->plugin->get_paths()->migrations ) ) {
|
||||
throw new Exception( 'Starting with version 4.1.1 of the Core for Factory framework module, you must create a "migrations" folder in the root of your plugin to store the migration of the plugin.' );
|
||||
}
|
||||
|
||||
if ( is_admin() ) {
|
||||
add_action( 'admin_init', [ $this, 'check_migrations' ] );
|
||||
|
||||
add_action( "wbcr/factory/plugin_{$plugin_name}_activated", [ $this, 'activation_hook' ] );
|
||||
add_action( 'wbcr/factory/admin_notices', [ $this, 'debug_bar_notice' ], 10, 2 );
|
||||
add_action( 'wbcr/factory/admin_notices', [ $this, 'migration_error_notice' ], 10, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1.1
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function get_plugin_activated_time() {
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
return get_site_option( $this->plugin->getOptionName( 'plugin_activated' ), 0 );
|
||||
}
|
||||
|
||||
return get_option( $this->plugin->getOptionName( 'plugin_activated' ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if migration is necessary for plugin and if there are errors from previous migrations.
|
||||
* In debug mode, migrations are not performed automatically.
|
||||
*/
|
||||
public function check_migrations() {
|
||||
if ( $this->is_migration_error() && isset( $_GET['wbcr_factory_fix_migration_error'] ) ) {
|
||||
$this->fix_migration_error();
|
||||
wp_safe_redirect( esc_url_raw( remove_query_arg( 'wbcr_factory_fix_migration_error' ) ) );
|
||||
die();
|
||||
}
|
||||
|
||||
if ( $this->is_debug() && isset( $_GET['wbcr_factory_test_migration'] ) ) {
|
||||
$this->make_migration();
|
||||
wp_safe_redirect( esc_url_raw( remove_query_arg( 'wbcr_factory_test_migration' ) ) );
|
||||
die();
|
||||
}
|
||||
|
||||
if ( $this->need_migration() && ! $this->is_debug() ) {
|
||||
$this->make_migration();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification displays the errors of outstanding migrations to fix errors
|
||||
* you need to follow the instructions in the notification and click
|
||||
* "I fixed, confirm migration".
|
||||
*
|
||||
* What is it for. Migrations are performed in background and on some sites,
|
||||
* due to php errors or for some other reason, migration may be
|
||||
* interrupted, because of what plugin will work incorrectly, you may lose settings.
|
||||
*
|
||||
* When creating new migrations, developer will add error handlers,
|
||||
* and framework will intercept them safely for user and display them
|
||||
* in this notice.
|
||||
*
|
||||
* @param array $notices
|
||||
* @param static $plugin_name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function migration_error_notice( $notices, $plugin_name ) {
|
||||
|
||||
if ( $this->plugin->getPluginName() !== $plugin_name ) {
|
||||
return $notices;
|
||||
}
|
||||
|
||||
if ( ! $this->is_migration_error() || ! current_user_can( 'update_plugins' ) ) {
|
||||
return $notices;
|
||||
}
|
||||
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
$migration_error_text = get_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ), '' );
|
||||
} else {
|
||||
$migration_error_text = get_option( $this->plugin->getOptionName( 'plugin_migration_error' ), '' );
|
||||
}
|
||||
|
||||
$fix_migration_error_url = esc_url( add_query_arg( 'wbcr_factory_fix_migration_error', 1 ) );
|
||||
|
||||
$notice_text = $migration_error_text;
|
||||
$notice_text .= "<br><br><a href='{$fix_migration_error_url}' class='button button-default'>" . __( 'I fixed, confirm migration', 'robin-image-optimizer' ) . '</a>';
|
||||
|
||||
$notices[] = [
|
||||
'id' => 'migration_debug_bar',
|
||||
'type' => 'error',
|
||||
'dismissible' => false,
|
||||
'dismiss_expires' => 0,
|
||||
'text' => '<p><b>' . $this->plugin->getPluginTitle() . ' ' . __( 'migration error', 'robin-image-optimizer' ) . '</b><br>' . $notice_text . '</p>',
|
||||
];
|
||||
|
||||
return $notices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug panel, display some information from the database. Also allows
|
||||
* perform manual migrations to test new migrations.
|
||||
*
|
||||
* @param array $notices
|
||||
* @param string $plugin_name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function debug_bar_notice( $notices, $plugin_name ) {
|
||||
|
||||
if ( $this->plugin->getPluginName() !== $plugin_name ) {
|
||||
return $notices;
|
||||
}
|
||||
if ( ! $this->is_debug() || ! current_user_can( 'update_plugins' ) ) {
|
||||
return $notices;
|
||||
}
|
||||
|
||||
$migrate_url = esc_url( add_query_arg( 'wbcr_factory_test_migration', 1 ) );
|
||||
|
||||
$notice_text = __( 'Plugin activated:', 'robin-image-optimizer' ) . ' ' . date( 'Y-m-d H:i:s', $this->get_plugin_activated_time() ) . '<br>';
|
||||
|
||||
$notice_text .= __( 'Old plugin version (debug):', 'robin-image-optimizer' ) . ' ' . $this->get_old_plugin_version() . '<br>';
|
||||
$notice_text .= __( 'Current plugin version:', 'robin-image-optimizer' ) . ' ' . $this->get_current_plugin_version() . '<br>';
|
||||
$notice_text .= __( 'Need migration:', 'robin-image-optimizer' ) . ' ' . ( $this->need_migration() ? 'true' : 'false' ) . '<br><br>';
|
||||
$notice_text .= "<a href='{$migrate_url}' class='button button-default'>" . __( 'Migrate now', 'robin-image-optimizer' ) . '</a><br>';
|
||||
|
||||
$notices[] = [
|
||||
'id' => 'migration_debug_bar',
|
||||
'type' => 'warning',
|
||||
'dismissible' => false,
|
||||
'dismiss_expires' => 0,
|
||||
'text' => '<p><b style="color:red;">' . $this->plugin->getPluginTitle() . ' ' . __( 'migrations DEBUG bar', 'robin-image-optimizer' ) . '</b><br>' . $notice_text . '</p>',
|
||||
];
|
||||
|
||||
return $notices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs when plugin is activated. Checks if you need to migrate
|
||||
* and if necessary it does it. Also adds a option when the plugin
|
||||
* was activated for the first time.
|
||||
*/
|
||||
public function activation_hook() {
|
||||
/*
|
||||
if ( $this->need_migration() && ! $this->is_debug() ) {
|
||||
$this->make_migration();
|
||||
}*/
|
||||
|
||||
// just time to know when the plugin was activated the first time
|
||||
$activated = $this->get_plugin_activated_time();
|
||||
|
||||
if ( ! $activated ) {
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
update_site_option( $this->plugin->getOptionName( 'plugin_activated' ), time() );
|
||||
update_site_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
|
||||
} else {
|
||||
update_option( $this->plugin->getOptionName( 'plugin_activated' ), time() );
|
||||
update_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if debug mode of migrations from version x.x.x to x.x.y is enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_debug() {
|
||||
return defined( 'FACTORY_MIGRATIONS_DEBUG' ) && FACTORY_MIGRATIONS_DEBUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets previous version of plugin that plugin had before updating to the new version.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function get_old_plugin_version() {
|
||||
|
||||
if ( $this->is_debug() && defined( 'FACTORY_MIGRATIONS_FORCE_OLD_VERSION' ) ) {
|
||||
return FACTORY_MIGRATIONS_FORCE_OLD_VERSION;
|
||||
}
|
||||
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
$plugin_version = get_site_option( $this->plugin->getOptionName( 'plugin_version' ), null );
|
||||
} else {
|
||||
$plugin_version = get_option( $this->plugin->getOptionName( 'plugin_version' ), null );
|
||||
}
|
||||
|
||||
if ( ! empty( $plugin_version ) ) {
|
||||
return $plugin_version;
|
||||
}
|
||||
|
||||
// TODO: Remove after few releases
|
||||
// This block for compatibility code with old version of framework < 4.1.1
|
||||
// -------------------------------------------
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
$plugin_versions = get_site_option( 'factory_plugin_versions', [] );
|
||||
} else {
|
||||
$plugin_versions = get_option( 'factory_plugin_versions', [] );
|
||||
}
|
||||
|
||||
$plugin_version = isset( $plugin_versions[ $this->plugin->getPluginName() ] ) ? $plugin_versions[ $this->plugin->getPluginName() ] : null;
|
||||
|
||||
if ( ! empty( $plugin_version ) ) {
|
||||
$plugin_version = str_replace( [ 'free-', 'premium-', 'offline-' ], '', $plugin_version );
|
||||
}
|
||||
|
||||
// -------------------------------------------
|
||||
|
||||
return $plugin_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current version of plugin.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_current_plugin_version() {
|
||||
return $this->plugin->getPluginVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do I need migration for plugin? If previous migration was with a error, then
|
||||
* method will always return false to prevent looping.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function need_migration() {
|
||||
if ( $this->is_migration_error() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return version_compare( $this->get_old_plugin_version(), $this->get_current_plugin_version(), '<' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Are there errors from previous migrations?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_migration_error() {
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
$error = get_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ), false );
|
||||
} else {
|
||||
$error = get_option( $this->plugin->getOptionName( 'plugin_migration_error' ), false );
|
||||
}
|
||||
|
||||
return $error !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an option in database, thereby fix errors of the previous migration.
|
||||
*/
|
||||
protected function fix_migration_error() {
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
delete_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
delete_option( $this->plugin->getOptionName( 'plugin_migration_error' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates the plugin from version x.x.x to x.x.y. Automatically searches for files
|
||||
* migrations to the plugin's root directory and executes them. Default files
|
||||
* migrations are stored in wp-content/plugins/plugin-name/migrations and have names
|
||||
* 0x0x0x.php, which corresponds to the version x.x.x. Method executes those migration files
|
||||
* versions of which are between the previous version of plugin and current one.
|
||||
*/
|
||||
protected function make_migration() {
|
||||
|
||||
if ( ! current_user_can( 'update_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$old_plugin_version = $this->get_old_plugin_version();
|
||||
$new_plugin_version = $this->get_current_plugin_version();
|
||||
|
||||
if ( empty( $old_plugin_version ) ) {
|
||||
$this->update_plugin_version_in_db();
|
||||
}
|
||||
|
||||
// converts versions like 0.0.0 to 000000
|
||||
$old_number = $this->get_version_number( $old_plugin_version );
|
||||
$new_number = $this->get_version_number( $new_plugin_version );
|
||||
|
||||
try {
|
||||
|
||||
$update_files = $this->plugin->get_paths()->migrations;
|
||||
$files = $this->find_files( $update_files );
|
||||
|
||||
if ( empty( $files ) ) {
|
||||
$this->update_plugin_version_in_db();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// finds updates that has intermediate version
|
||||
foreach ( (array) $files as $item ) {
|
||||
if ( ! preg_match( '/^\d+$/', $item['name'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item_number = intval( $item['name'] );
|
||||
|
||||
if ( $item_number > $old_number && $item_number <= $new_number ) {
|
||||
$classes = $this->get_classes( $item['path'] );
|
||||
|
||||
if ( count( $classes ) == 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( $classes as $path => $class_data ) {
|
||||
include_once $path;
|
||||
$update_class = $class_data['name'];
|
||||
|
||||
$update = new $update_class( $this->plugin );
|
||||
$update->install();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->update_plugin_version_in_db();
|
||||
} catch ( Exception $e ) {
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
update_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ), $e->getMessage() );
|
||||
|
||||
return;
|
||||
}
|
||||
update_option( $this->plugin->getOptionName( 'plugin_migration_error' ), $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates version of plugin in database. So that we can track which
|
||||
* previous version of plugin was at the user, before he updated
|
||||
* plugin.
|
||||
*/
|
||||
protected function update_plugin_version_in_db() {
|
||||
|
||||
// TODO: Delete after few releases
|
||||
// This block for compatibility code with the old version of framework.
|
||||
// Cleans up old data, after the transition to new version of framework.
|
||||
// -------------------------------------------
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
$plugin_versions = get_site_option( 'factory_plugin_versions', [] );
|
||||
} else {
|
||||
$plugin_versions = get_option( 'factory_plugin_versions', [] );
|
||||
}
|
||||
|
||||
if ( isset( $plugin_versions[ $this->plugin->getPluginName() ] ) ) {
|
||||
unset( $plugin_versions[ $this->plugin->getPluginName() ] );
|
||||
}
|
||||
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
if ( empty( $plugin_versions ) ) {
|
||||
delete_site_option( 'factory_plugin_versions' );
|
||||
}
|
||||
update_site_option( 'factory_plugin_versions', $plugin_versions );
|
||||
update_site_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( empty( $plugin_versions ) ) {
|
||||
delete_option( 'factory_plugin_versions' );
|
||||
}
|
||||
|
||||
update_option( 'factory_plugin_versions', $plugin_versions );
|
||||
update_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts string representation of the version to the numeric.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param string $version A string version to convert.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
protected function get_version_number( $version ) {
|
||||
preg_match( '/(\d+)\.(\d+)\.(\d+)/', $version, $matches );
|
||||
if ( count( $matches ) == 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$number = '';
|
||||
$number .= ( strlen( $matches[1] ) == 1 ) ? '0' . $matches[1] : $matches[1];
|
||||
$number .= ( strlen( $matches[2] ) == 1 ) ? '0' . $matches[2] : $matches[2];
|
||||
$number .= ( strlen( $matches[3] ) == 1 ) ? '0' . $matches[3] : $matches[3];
|
||||
|
||||
return intval( $number );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of files at a given path.
|
||||
*
|
||||
* @param string $path path for search
|
||||
*/
|
||||
private function find_files( $path ) {
|
||||
return $this->find_file_or_folders( $path, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of folders at a given path.
|
||||
*
|
||||
* @param string $path path for search
|
||||
*/
|
||||
/*
|
||||
private function find_folders( $path ) {
|
||||
return $this->find_file_or_folders( $path, false );
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Returns a list of files or folders at a given path.
|
||||
*
|
||||
* @param string $path path for search
|
||||
* @param bool $files files or folders?
|
||||
*/
|
||||
private function find_file_or_folders( $path, $areFiles = true ) {
|
||||
if ( ! is_dir( $path ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$entries = scandir( $path );
|
||||
if ( empty( $entries ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$files = [];
|
||||
foreach ( $entries as $entryName ) {
|
||||
if ( $entryName == '.' || $entryName == '..' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filename = $path . '/' . $entryName;
|
||||
if ( ( $areFiles && is_file( $filename ) ) || ( ! $areFiles && is_dir( $filename ) ) ) {
|
||||
$files[] = [
|
||||
'path' => str_replace( '\\', '/', $filename ),
|
||||
'name' => $areFiles ? str_replace( '.php', '', $entryName ) : $entryName,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets php classes defined in a specified file.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function get_classes( $path ) {
|
||||
|
||||
$phpCode = file_get_contents( $path );
|
||||
|
||||
$classes = [];
|
||||
|
||||
if ( ! function_exists( 'token_get_all' ) ) {
|
||||
throw new Exception(
|
||||
// translators: %s is the function name.
|
||||
sprintf( __( 'There is no PHP Tokenizer extension installed on your server, you cannot use the %s function.', 'robin-image-optimizer' ), 'token_get_all' )
|
||||
);
|
||||
}
|
||||
|
||||
$tokens = token_get_all( $phpCode );
|
||||
|
||||
$count = count( $tokens );
|
||||
for ( $i = 2; $i < $count; $i++ ) {
|
||||
if ( is_array( $tokens ) && $tokens[ $i - 2 ][0] == T_CLASS && $tokens[ $i - 1 ][0] == T_WHITESPACE && $tokens[ $i ][0] == T_STRING ) {
|
||||
|
||||
$extends = null;
|
||||
if ( $tokens[ $i + 2 ][0] == T_EXTENDS && $tokens[ $i + 4 ][0] == T_STRING ) {
|
||||
$extends = $tokens[ $i + 4 ][1];
|
||||
}
|
||||
|
||||
$class_name = $tokens[ $i ][1];
|
||||
$classes[ $path ] = [
|
||||
'name' => $class_name,
|
||||
'extends' => $extends,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* result example:
|
||||
*
|
||||
* $classes['/plugin/items/filename.php'] = array(
|
||||
* 'name' => 'PluginNameItem',
|
||||
* 'extendes' => 'PluginNameItemBase'
|
||||
* )
|
||||
*/
|
||||
|
||||
return $classes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600;
|
||||
|
||||
use Wbcr_Factory600_Plugin;
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to manage notices.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* A group of classes and methods to create and manage notices.
|
||||
*
|
||||
* @package factory-notices
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Notices {
|
||||
|
||||
/**
|
||||
* @var Wbcr_Factory600_Plugin
|
||||
*/
|
||||
protected $plugin;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $notices = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $default_where = [
|
||||
'plugins',
|
||||
'themes',
|
||||
'dashboard',
|
||||
'edit',
|
||||
'settings',
|
||||
'dashboard-network',
|
||||
'plugins-network',
|
||||
'themes-network',
|
||||
'settings-network',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $dissmised_notices;
|
||||
|
||||
/**
|
||||
* Инициализируем уведомлений сразу после загрузки модуля уведомлений
|
||||
*
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
*/
|
||||
public function __construct( $plugin ) {
|
||||
// default notices
|
||||
// ---
|
||||
|
||||
$this->plugin = $plugin;
|
||||
$this->dissmised_notices = $this->plugin->getPopulateOption( 'factory_dismissed_notices', [] );
|
||||
|
||||
add_action( 'current_screen', [ $this, 'currentScreenAction' ] );
|
||||
|
||||
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
||||
add_action(
|
||||
'wp_ajax_' . $this->plugin->getPluginName() . '_dismiss_notice',
|
||||
[
|
||||
$this,
|
||||
'dismiss_notice',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует экшены для работы с уведомлениями на текущем экране странице.
|
||||
* Уведомления собираются через фильтр wbcr_factory_admin_notices, если в массиве уведомлений,
|
||||
* хотя бы одно, соответствует условиям в параметре $notice['where'], то метод печает вспомогательные скрипты и уведомления.
|
||||
*/
|
||||
public function currentScreenAction() {
|
||||
/**
|
||||
* @since 2.1.2 - Добавлен, модуль factory_notices_000 был удален. Поэтому в этому хуке мы заменили префикс на factory_600
|
||||
*/
|
||||
$this->notices = apply_filters( 'wbcr/factory/admin_notices', $this->notices, $this->plugin->getPluginName() );
|
||||
|
||||
if ( count( $this->notices ) == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$screen = get_current_screen();
|
||||
|
||||
$has_notices = false;
|
||||
foreach ( (array) $this->notices as $notice ) {
|
||||
if ( ! isset( $notice['id'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$where = ! isset( $notice['where'] ) || empty( $notice['where'] ) ? $this->default_where : $notice['where'];
|
||||
|
||||
if ( in_array( $screen->base, $where ) && ! $this->is_dissmissed( $notice['id'] ) ) {
|
||||
$has_notices = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $has_notices ) {
|
||||
add_action( 'admin_footer', [ $this, 'print_js_code' ] );
|
||||
|
||||
$this->show_notices();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Показывает все зарегистрированные уведомления для текущего плагина.
|
||||
* Уведомления показываются только на определенных страницах через параметр $notice['where'],
|
||||
* если уведомление ранее было скрыто или не соотвествует правилам $notice['where'], оно не будет показано!
|
||||
*/
|
||||
public function show_notices() {
|
||||
if ( count( $this->notices ) == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'activate_plugins' ) || ! current_user_can( 'edit_plugins' ) || ! current_user_can( 'install_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$screen = get_current_screen();
|
||||
|
||||
foreach ( $this->notices as $notice ) {
|
||||
|
||||
if ( ! isset( $notice['id'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$where = ! isset( $notice['where'] ) || empty( $notice['where'] ) ? $this->default_where : $notice['where'];
|
||||
|
||||
if ( in_array( $screen->base, $where ) && ! $this->is_dissmissed( $notice['id'] ) ) {
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
if ( current_user_can( 'manage_network' ) ) {
|
||||
add_action(
|
||||
'network_admin_notices',
|
||||
function () use ( $notice ) {
|
||||
$this->show_notice( $notice );
|
||||
}
|
||||
);
|
||||
add_action(
|
||||
'admin_notices',
|
||||
function () use ( $notice ) {
|
||||
$this->show_notice( $notice );
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
add_action(
|
||||
'admin_notices',
|
||||
function () use ( $notice ) {
|
||||
$this->show_notice( $notice );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Показывает уведомление, по переданным параметрам
|
||||
*
|
||||
* @param array $data - Параметры уведомления
|
||||
* $data['id'] - Индентификатор уведомления
|
||||
* $data['type'] - Тип уведомления (error, warning, success)
|
||||
* $notice['where'] - На каких страницах показывать уведомление ('plugins', 'dashboard', 'edit')
|
||||
* $data['text'] - Текст уведомления
|
||||
* $data['dismissible'] - Если true, уведомление будет с кнопкой закрыть
|
||||
* $data['dismiss_expires'] - Когда снова показать уведомление, нужно указывать время в unix timestamp.
|
||||
* Пример time() + 3600 (1ч), уведомление будет скрыто на 1 час.
|
||||
* $data['classes'] - Произвольный классы для контейнера уведомления.
|
||||
*/
|
||||
public function show_notice( $data ) {
|
||||
$settings = wp_parse_args(
|
||||
$data,
|
||||
[
|
||||
'id' => null,
|
||||
'text' => null,
|
||||
'type' => 'error',
|
||||
'dismissible' => false,
|
||||
'dismiss_expires' => 0,
|
||||
'classes' => [],
|
||||
]
|
||||
);
|
||||
|
||||
if ( empty( $settings['id'] ) || empty( $settings['text'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$plugin_name = str_replace( '_', '-', $this->plugin->getPluginName() );
|
||||
|
||||
$classes = array_merge(
|
||||
[
|
||||
'notice',
|
||||
'notice-' . $settings['type'],
|
||||
$plugin_name . '-factory-notice',
|
||||
],
|
||||
$settings['classes']
|
||||
);
|
||||
|
||||
if ( $settings['dismissible'] ) {
|
||||
$classes[] = 'is-dismissible';
|
||||
$classes[] = $plugin_name . '-factory-notice-dismiss';
|
||||
}
|
||||
?>
|
||||
<div data-name="wbcr_factory_notice_<?php echo esc_attr( $data['id'] ); ?>" data-expires="<?php echo esc_attr( $settings['dismiss_expires'] ); ?>" data-nonce="<?php echo wp_create_nonce( $this->plugin->getPluginName() . '_factory_dismiss_notice' ); ?>" class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
|
||||
<?php echo $data['text']; ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Когда пользователь нажимает кнопку закрыть уведомление,
|
||||
* отправляется ajax запрос с вызовом текущего метода
|
||||
*/
|
||||
public function dismiss_notice() {
|
||||
if ( ! current_user_can( 'activate_plugins' ) || ! current_user_can( 'edit_plugins' ) || ! current_user_can( 'install_plugins' ) ) {
|
||||
wp_die( -1, 403 );
|
||||
}
|
||||
|
||||
check_admin_referer( $this->plugin->getPluginName() . '_factory_dismiss_notice', 'nonce' );
|
||||
|
||||
// Имя уведомления (идентификатор)
|
||||
$name = $this->plugin->request->post( 'name', null, true );
|
||||
|
||||
// Время в Unix timestamp, по истечению, которого уведомление снова будет показано
|
||||
// Если передан 0, то уведомление будет скрыто навсегда
|
||||
$expires = $this->plugin->request->post( 'expires', 0, 'intval' );
|
||||
|
||||
if ( empty( $name ) ) {
|
||||
wp_send_json_error( [ 'error_message' => 'You must pass the notification "Name"! Action was rejected.' ] );
|
||||
}
|
||||
|
||||
$notices = $this->plugin->getPopulateOption( 'factory_dismissed_notices', [] );
|
||||
|
||||
if ( ! empty( $notices ) ) {
|
||||
foreach ( (array) $notices as $notice_id => $notice_expires ) {
|
||||
if ( $notice_expires !== 0 && $notice_expires < time() ) {
|
||||
unset( $notices[ $notice_id ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$notices[ $name ] = $expires;
|
||||
|
||||
$this->plugin->updatePopulateOption( 'factory_dismissed_notices', $notices );
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Javascript code
|
||||
* Печает в подвале страницы код, для взаимодействия с сервером через ajax,
|
||||
* код используется при нажатии на кнопку закрыть уведомление. *
|
||||
*/
|
||||
public function print_js_code() {
|
||||
$plugin_name = str_replace( '_', '-', $this->plugin->getPluginName() );
|
||||
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
jQuery(function($) {
|
||||
|
||||
$(document).on('click', '.<?php echo $plugin_name; ?>-factory-notice-dismiss .notice-dismiss', function() {
|
||||
$.post(ajaxurl, {
|
||||
'action': '<?php echo $this->plugin->getPluginName(); ?>_dismiss_notice',
|
||||
'name': $(this).parent().data('name'),
|
||||
'expires': $(this).parent().data('expires'),
|
||||
'nonce': $(this).parent().attr('data-nonce')
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Проверяет скрыто уведоление или нет
|
||||
*
|
||||
* @param string $notice_id - имя уведомления
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_dissmissed( $notice_id ) {
|
||||
if ( ! empty( $this->dissmised_notices ) && isset( $this->dissmised_notices[ 'wbcr_factory_notice_' . $notice_id ] ) ) {
|
||||
$expires = (int) $this->dissmised_notices[ 'wbcr_factory_notice_' . $notice_id ];
|
||||
|
||||
return $expires === 0 || $expires > time();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600;
|
||||
|
||||
// Exit if accessed directly
|
||||
use Exception;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Трейт используется для расширения базового класса плагина Wbcr_Factory600_Base, позволяя работать с опциями плагина.
|
||||
*
|
||||
* Этот трейт является оберткой для WordPress функций get_option, get_site_option, update_option, update_site_option,
|
||||
* delete_option, delete_site_option. Основная задача была получать, обновлять, удалять опции без использования префиксов,
|
||||
* чтобы класс выполнял эту работу за программиста. В дополнение, трейт содержит методы для полной выгрузки всех опций
|
||||
* плагина, что позволяет при инициализации плагина автоматически выгрузить все существующие опции плагина в объектный
|
||||
* кеш. Все опции, с которыми работает плагин, могут быть отфильтрованы.
|
||||
*
|
||||
* @since 4.0.8 - Добавлен
|
||||
* @package factory-core
|
||||
*/
|
||||
trait Options {
|
||||
|
||||
/**
|
||||
* Абстрактный метод, должен быть реализован в классе использующем этот трейт. Метод позволяет получить префикс
|
||||
* плагина для формирования имен опций в базе данных WordPress. У опций должно быть свое пространство имен,
|
||||
* иначе может быть конфликт с другими плагинами или с сами ядром WordPress.
|
||||
*
|
||||
* @since 4.0.8 - Добавлен
|
||||
* @return string Возвращает префикс плагина. Пример: wbcr_clearfy_
|
||||
*/
|
||||
abstract public function getPrefix();
|
||||
|
||||
/**
|
||||
* Выгружает все опции плагина в объектный кеш. Плагин может получить любую свою опцию без запроса к базе данных.
|
||||
* Метод ускоряет работу плагина, если опций очень много.
|
||||
*
|
||||
* Используется только один раз при инициализации плагина.
|
||||
*
|
||||
* @since 4.0.8 - Добавлен
|
||||
*/
|
||||
public function loadAllOptions() {
|
||||
global $wpdb;
|
||||
|
||||
$is_option_loaded = wp_cache_get( $this->getPrefix() . 'all_options_loaded', $this->getPrefix() . 'options' );
|
||||
|
||||
if ( false === $is_option_loaded ) {
|
||||
$result = $wpdb->get_results( "SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE '{$this->getPrefix()}%'" );
|
||||
|
||||
$options = [];
|
||||
|
||||
if ( ! empty( $result ) ) {
|
||||
wp_cache_add( $this->getPrefix() . 'all_options_loaded', 1, $this->getPrefix() . 'options' );
|
||||
|
||||
foreach ( $result as $option ) {
|
||||
$value = maybe_unserialize( $option->option_value );
|
||||
$value = $this->normalizeValue( $value );
|
||||
|
||||
wp_cache_add( $option->option_name, $value, $this->getPrefix() . 'options' );
|
||||
$options[ $option->option_name ] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Действие, которое будет выполнено, когда все опции плагина будут выгружены.
|
||||
*
|
||||
* @since 4.0.9 - Добавлен
|
||||
*
|
||||
* @param array $options Ассоциативный массив опций плагина
|
||||
* @param string $plugin_name Имя плагина
|
||||
*/
|
||||
do_action( 'wbcr/factory/all_options_loaded', $options, $this->plugin_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Выгружает все сетевые опции плагина в объектный кеш. Плагин может получить любую свою опцию без запроса к базе
|
||||
* данных. Метод ускоряет работу плагина, если опций очень много.
|
||||
*
|
||||
* Используется и работает только в режиме мультисайтов, один раз при инициализации плагина.!
|
||||
*
|
||||
* @since 4.0.8 - Добавлен
|
||||
* @return void
|
||||
*/
|
||||
public function loadAllNetworkOptions() {
|
||||
global $wpdb;
|
||||
|
||||
$network_id = (int) get_current_network_id();
|
||||
|
||||
$is_option_loaded = wp_cache_get( $network_id . ':' . $this->getPrefix() . 'all_options_loaded', $this->getPrefix() . 'network_options' );
|
||||
|
||||
if ( false === $is_option_loaded ) {
|
||||
wp_cache_add_global_groups( [ $this->getPrefix() . 'network_options' ] );
|
||||
|
||||
$result = $wpdb->get_results( "SELECT meta_key, meta_value FROM {$wpdb->sitemeta} WHERE site_id='{$network_id}' AND meta_key LIKE '{$this->getPrefix()}%'" );
|
||||
|
||||
$options = [];
|
||||
if ( ! empty( $result ) ) {
|
||||
wp_cache_add( $network_id . ':' . $this->getPrefix() . 'all_options_loaded', 1, $this->getPrefix() . 'network_options' );
|
||||
|
||||
foreach ( $result as $option ) {
|
||||
$value = maybe_unserialize( $option->meta_value );
|
||||
$value = $this->normalizeValue( $value );
|
||||
|
||||
$cache_key = $network_id . ':' . $option->meta_key;
|
||||
wp_cache_add( $cache_key, $value, $this->getPrefix() . 'network_options' );
|
||||
$options[ $option->meta_key ] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Действие, которое будет выполнено, когда все сетевые опции плагина будут выгружены.
|
||||
*
|
||||
* @since 4.0.9 - Добавлен
|
||||
*
|
||||
* @param array $options Ассоциативный массив опций плагина
|
||||
* @param string $plugin_name Имя плагина
|
||||
*/
|
||||
do_action( 'wbcr/factory/all_network_options_loaded', $options, $this->plugin_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить популярную опцию. В случае если плагин установлен для сети (в режиме мультисайтов),
|
||||
* то метод возвращает опции только для сети, иначе метод возвращает опцию для текущего сайта. Работает
|
||||
* на основе self::getOption и self::getNetworkOption, смотрите полную реализацию в этих методах.
|
||||
*
|
||||
* @since 4.0.8 - Добавлен
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
* @param mixed $default Значение по умолчанию. Если опции нет в базе данных, будет возвращено это значение. По умолчанию false
|
||||
*
|
||||
* @return mixed Возвращает значение опции, если это сериализованная строка, то автоматически распаковывает ее.
|
||||
*/
|
||||
public function getPopulateOption( $option_name, $default = false ) {
|
||||
if ( $this->isNetworkActive() ) {
|
||||
$option_value = $this->getNetworkOption( $option_name, $default );
|
||||
} else {
|
||||
$option_value = $this->getOption( $option_name, $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Фильтр позволяет отфильтровать возвращаемое значение популярной опции.
|
||||
*
|
||||
* @since 4.0.9 - Добавлен
|
||||
*
|
||||
* @param mixed $option_value Значение опции
|
||||
* @param string $option_name Имя опции
|
||||
* @param mixed $default Значение опции по умолчанию
|
||||
*/
|
||||
return apply_filters( "wbcr/factory/populate_option_{$option_name}", $option_value, $option_name, $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить сетевые опции. Если плагин установлен для сети (в режиме мультисайтов), то
|
||||
* метод возвращает опции только для сети, иначе метод возвращает опцию для текущего сайта.
|
||||
*
|
||||
* Опция вытаскивается из объектного кеша, после выполнения метода self:loadAllNetworkOptions,
|
||||
* а не напрямую из базы данных, из-за чего при работе с некоторыми кеширующими плагинами,
|
||||
* может быть странное поведение в работе плагина.
|
||||
*
|
||||
* @since 4.0.8 - Добавлен
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
* @param mixed $default Значение по умолчанию. Если опции нет в базе данных, будет возвращено это значение. По умолчанию false
|
||||
*
|
||||
* @return mixed Возвращает значение опции, если это сериализованная строка, то автоматически распаковывает ее.
|
||||
*/
|
||||
public function getNetworkOption( $option_name, $default = false ) {
|
||||
if ( empty( $option_name ) || ! is_string( $option_name ) ) {
|
||||
throw new Exception( 'Option name must be a string and must not be empty.' );
|
||||
}
|
||||
|
||||
if ( ! is_multisite() ) {
|
||||
return $this->getOption( $option_name, $default );
|
||||
}
|
||||
|
||||
$this->loadAllNetworkOptions();
|
||||
|
||||
$network_id = (int) get_current_network_id();
|
||||
$cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
|
||||
$option_value = wp_cache_get( $cache_key, $this->getPrefix() . 'network_options' );
|
||||
|
||||
if ( false === $option_value ) {
|
||||
$option_value = $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Фильтр позволяет отфильтровать возвращаемое значение сетевой опции.
|
||||
*
|
||||
* @since 4.0.9 - Добавлен
|
||||
*
|
||||
* @param mixed $option_value Значение опции
|
||||
* @param string $option_name Имя опции
|
||||
* @param mixed $default Значение опции по умолчанию
|
||||
* @param int $network_id ID сети
|
||||
*/
|
||||
|
||||
return apply_filters( "wbcr/factory/network_option_{$option_name}", $option_value, $option_name, $default, $network_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод позволяет получить опцию для текущего сайта. Опция вытаскивается из объектного кеша, после выполнения метода
|
||||
* self:loadAllOptions, а не напрямую из базы данных, из-за чего при работе с некоторыми кеширующими плагинами,
|
||||
* может быть странное поведение в работе плагина.
|
||||
*
|
||||
* @since 4.0.0 - Добавлен
|
||||
* @since 4.0.8 - Полностью переделан
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
* @param mixed $default Значение по умолчанию. Если опции нет в базе данных, будет возвращено это значение. По умолчанию false
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOption( $option_name, $default = false ) {
|
||||
if ( empty( $option_name ) || ! is_string( $option_name ) ) {
|
||||
throw new Exception( 'Option name must be a string and must not be empty.' );
|
||||
}
|
||||
|
||||
$this->loadAllOptions();
|
||||
|
||||
$option_value = wp_cache_get( $this->getPrefix() . $option_name, $this->getPrefix() . 'options' );
|
||||
|
||||
if ( false === $option_value ) {
|
||||
$option_value = $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Фильтр позволяет отфильтровать возвращаемое значение опции сайта.
|
||||
*
|
||||
* @since 4.0.9 - Добавлен
|
||||
*
|
||||
* @param mixed $option_value Значение опции
|
||||
* @param string $option_name Имя опции
|
||||
* @param mixed $default Значение опции по умолчанию
|
||||
*/
|
||||
|
||||
return apply_filters( "wbcr/factory/option_{$option_name}", $option_value, $option_name, $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет обновить популярную опцию в базе данных. Если плагин установлен для сети (в режиме мультисайтов), то метод обновляет опцию
|
||||
* только в таблице sitemeta, иначе в таблице options для текущего сайта.
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
* @param mixed $option_value Значение опции. Может принимать массив или объект.
|
||||
*/
|
||||
public function updatePopulateOption( $option_name, $option_value ) {
|
||||
if ( $this->isNetworkActive() ) {
|
||||
$this->updateNetworkOption( $option_name, $option_value );
|
||||
} else {
|
||||
$this->updateOption( $option_name, $option_value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет сетевую опцию в БД таблица sitemeta. После успешного обновления опции в базе данных, метод добавляет опцию в объектный кеш,
|
||||
* чтобы плагин мог приступить к работе с этой опцией незамедлительно.
|
||||
*
|
||||
* @since 4.0.8 - Добавлен
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
* @param mixed $option_value Значение опции. Может принимать массив или объект.
|
||||
*/
|
||||
public function updateNetworkOption( $option_name, $option_value ) {
|
||||
$network_id = (int) get_current_network_id();
|
||||
$cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
|
||||
wp_cache_set( $cache_key, $option_value, $this->getPrefix() . 'network_options' );
|
||||
|
||||
update_site_option( $this->getPrefix() . $option_name, $option_value );
|
||||
|
||||
/**
|
||||
* Действие будет выполнено, когда сетевая опция будет обновлена.
|
||||
*
|
||||
* @since 4.0.8 - Добавлен
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
* @param mixed $option_value Значение опции. Может принимать массив или объект.
|
||||
*/
|
||||
do_action( 'wbcr/factory/update_network_option', $option_name, $option_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет опцию сайта в БД таблица options. После успешного обновления опции в базе данных, метод добавляет опцию в объектный кеш,
|
||||
* чтобы плагин мог приступить к работе с этой опцией незамедлительно.
|
||||
*
|
||||
* @since 4.0.0 - Добавлен
|
||||
* @since 4.0.8 - Полностью переделан
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
* @param mixed $option_value Значение опции. Может принимать массив или объект.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function updateOption( $option_name, $option_value ) {
|
||||
wp_cache_set( $this->getPrefix() . $option_name, $option_value, $this->getPrefix() . 'options' );
|
||||
$result = update_option( $this->getPrefix() . $option_name, $option_value );
|
||||
|
||||
/**
|
||||
* @since 4.0.8
|
||||
*
|
||||
* @param string $option_name
|
||||
*
|
||||
* @param mixed $option_value
|
||||
*/
|
||||
do_action( 'wbcr/factory/update_option', $option_name, $option_value );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет удалять популярную опцию в базе данных. Если плагин установлен для сети (в режиме мультисайтов), то метод удаляет опцию
|
||||
* только в таблице sitemeta, иначе в таблице options для текущего сайта.
|
||||
*
|
||||
* @since 4.0.0 - Добавлен
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
*/
|
||||
public function deletePopulateOption( $option_name ) {
|
||||
if ( $this->isNetworkActive() ) {
|
||||
$this->deleteNetworkOption( $option_name );
|
||||
} else {
|
||||
$this->deleteOption( $option_name );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет сетевую.опцию в БД таблица sitemeta, а если опция есть в кеше, индивидуально удаляет опцию из кеша.
|
||||
*
|
||||
* @since 4.0.0 - Добавлен
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
*
|
||||
* @return bool Возвращает true, если опция удалена успешно, false в случае ошибки.
|
||||
*/
|
||||
public function deleteNetworkOption( $option_name ) {
|
||||
$network_id = (int) get_current_network_id();
|
||||
$cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
|
||||
$delete_cache = wp_cache_delete( $cache_key, $this->getPrefix() . 'network_options' );
|
||||
|
||||
$delete_opt1 = delete_site_option( $this->getPrefix() . $option_name );
|
||||
|
||||
return $delete_cache && $delete_opt1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет опцию сайта в БД таблица options, а если опция есть в кеше, индивидуально удаляет опцию из кеша.
|
||||
*
|
||||
* @since 4.0.0 - Добавлен
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
*
|
||||
* @return bool Возвращает true, если опция удалена успешно, false в случае ошибки.
|
||||
*/
|
||||
public function deleteOption( $option_name ) {
|
||||
$delete_cache = wp_cache_delete( $this->getPrefix() . $option_name, $this->getPrefix() . 'options' );
|
||||
|
||||
// todo: удалить, когда большая часть пользователей обновятся до современных релизов
|
||||
$delete_opt1 = delete_option( $this->getPrefix() . $option_name . '_is_active' );
|
||||
$delete_opt2 = delete_option( $this->getPrefix() . $option_name );
|
||||
|
||||
return $delete_cache && $delete_opt1 && $delete_opt2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Сбрасывает объектный кеш. Может использоваться для перезагрузки опций плагина и WordPress в целом.
|
||||
*
|
||||
* @since 4.0.0 - Добавлен
|
||||
* @return bool Возвращает true, если кеш сброшен успешно, false в случае ошибки.
|
||||
*/
|
||||
public function flushOptionsCache() {
|
||||
return wp_cache_flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить полное имя опции с префиксом. Может быть использовано в тех случаях, где нужно получить
|
||||
* полное имя опции.
|
||||
*
|
||||
* @since 4.0.0 - Добавлен
|
||||
*
|
||||
* @param string $option_name Имя опции без префикса.
|
||||
*
|
||||
* @return null|string Возвращает имя опции с префиксом. Например wbcr_clearfy_{options_name}
|
||||
*/
|
||||
public function getOptionName( $option_name ) {
|
||||
$option_name = trim( rtrim( $option_name ) );
|
||||
if ( empty( $option_name ) || ! is_string( $option_name ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->getPrefix() . $option_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет нормализовать данные. В некоторых методах этого трейта, ожидаются данные определенного типа, чтобы
|
||||
* выполнить различные логические операции. Как раз в этом случае этот метод можно использовать, чтобы привести
|
||||
* все сырые данные в строгий тип. Такое решение позволит избежать ошибок в работе программиста.
|
||||
*
|
||||
* @since 4.0.0 - Добавлен
|
||||
*
|
||||
* @param mixed $data Данные, которые нужно нормализовать.
|
||||
*
|
||||
* @return mixed Возвращает нормализованное значение.
|
||||
* - Если передана строка "true" или "false" вернет булево значение.
|
||||
* - Если передана строка "1" или "0" вернет число.
|
||||
*/
|
||||
public function normalizeValue( $data ) {
|
||||
if ( is_string( $data ) ) {
|
||||
$check_string = rtrim( trim( $data ) );
|
||||
|
||||
if ( $check_string == '1' || $check_string == '0' ) {
|
||||
return intval( $data );
|
||||
} elseif ( $check_string === 'false' ) {
|
||||
return false;
|
||||
} elseif ( $check_string === 'true' ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,897 @@
|
||||
<?php
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Основной класс для создания плагина.
|
||||
*
|
||||
* Это основной класс плагина. который отвечает за подключение модулей фреймворка, линзирование, обновление,
|
||||
* миграции разрабатываемого плагина. При создании нового плагина, вы должны создать основной класс реализующий
|
||||
* функции плагина, этот класс будет наследовать текущий.
|
||||
*
|
||||
* Смотрите подробную инструкцию по созданию плагина и экземпляра основного класса в документации по созданию
|
||||
* плагина для WordPress.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package factory-core
|
||||
*/
|
||||
abstract class Wbcr_Factory600_Plugin extends Wbcr_Factory600_Base {
|
||||
|
||||
/**
|
||||
* Instance class Wbcr_Factory600_Request, required manages http requests
|
||||
*
|
||||
* @var Wbcr_Factory600_Request
|
||||
*/
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* @var \WBCR\Factory_600\Premium\Provider
|
||||
*/
|
||||
public $premium;
|
||||
|
||||
/**
|
||||
* The Bootstrap Manager class
|
||||
*
|
||||
* @var Wbcr_FactoryBootstrap500_Manager
|
||||
*/
|
||||
public $bootstrap;
|
||||
|
||||
/**
|
||||
* The Bootstrap Manager class
|
||||
*
|
||||
* @var Wbcr_FactoryForms600_Manager
|
||||
*/
|
||||
public $forms;
|
||||
|
||||
/**
|
||||
* Простой массив со списком зарегистрированных классов унаследованных от Wbcr_Factory600_Activator.
|
||||
* Классы активации используются для упаковки набора функций, которые нужно выполнить во время
|
||||
* активации плагина.
|
||||
*
|
||||
* @var array[] Wbcr_Factory600_Activator
|
||||
*/
|
||||
protected $activator_class = [];
|
||||
|
||||
/**
|
||||
* Ассоциативный массив со списком уже загруженных модулей фреймворка. Используется для того, чтобы
|
||||
* проверить, каких модули уже были загружены, а какие еще нет.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $loaded_factory_modules = [];
|
||||
|
||||
/**
|
||||
* Ассоциативный массив со списком аддонов плагина. Аддоны плагина являются частью одного проекта,
|
||||
* но не как отдельный плагин.
|
||||
*
|
||||
* @since 4.2.0
|
||||
* @var array
|
||||
*/
|
||||
private $loaded_plugin_components = [];
|
||||
|
||||
/**
|
||||
* The Adverts Manager class
|
||||
*
|
||||
* @since 4.1.9
|
||||
* @var WBCR\Factory_Adverts_159\Base
|
||||
*/
|
||||
private $adverts;
|
||||
|
||||
/**
|
||||
* The Logger class
|
||||
*
|
||||
* @since 4.3.7
|
||||
* @var WBCR\Factory_Logger_359\Logger
|
||||
*/
|
||||
public $logger;
|
||||
|
||||
/**
|
||||
* Инициализирует компоненты фреймворка и плагина.
|
||||
*
|
||||
* @param array $data A set of plugin data.
|
||||
*
|
||||
* @param string $plugin_path A full path to the main plugin file.
|
||||
*
|
||||
* @throws Exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct( $plugin_path, $data ) {
|
||||
|
||||
parent::__construct( $plugin_path, $data );
|
||||
|
||||
$this->request = new Wbcr_Factory600_Request();
|
||||
// $this->route = new Wbcr_Factory600_Route();
|
||||
|
||||
// INIT PLUGIN FRAMEWORK MODULES
|
||||
// Framework modules should always be loaded first,
|
||||
// since all other functions depend on them.
|
||||
$this->init_framework_modules();
|
||||
|
||||
// INIT PLUGIN MIGRATIONS
|
||||
$this->init_plugin_migrations();
|
||||
|
||||
// INIT PLUGIN NOTICES
|
||||
$this->init_plugin_notices();
|
||||
|
||||
// INIT PLUGIN PREMIUM FEATURES
|
||||
// License manager should be installed earlier
|
||||
// so that other modules can access it.
|
||||
$this->init_plugin_premium_features();
|
||||
|
||||
// INIT PLUGIN UPDATES
|
||||
$this->init_plugin_updates();
|
||||
|
||||
// init actions
|
||||
$this->register_plugin_hooks();
|
||||
|
||||
// INIT PLUGIN COMPONENTS
|
||||
$this->init_plugin_components();
|
||||
|
||||
if ( wp_doing_ajax() && isset( $_REQUEST['action'] ) ) {
|
||||
if ( 'wfactory-600-intall-component' == $_REQUEST['action'] ) {
|
||||
add_action( 'wp_ajax_wfactory-600-intall-component', [ $this, 'ajax_handler_install_components' ] );
|
||||
}
|
||||
|
||||
if ( 'wfactory-600-prepare-component' == $_REQUEST['action'] ) {
|
||||
add_action( 'wp_ajax_wfactory-600-prepare-component', [ $this, 'ajax_handler_prepare_component' ] );
|
||||
}
|
||||
if ( 'wfactory-600-creativemotion-install-plugin' == $_REQUEST['action'] ) {
|
||||
add_action(
|
||||
'wp_ajax_wfactory-600-creativemotion-install-plugin',
|
||||
[
|
||||
$this,
|
||||
'ajax_handler_install_creativemotion_plugins',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ajax Handlers
|
||||
// --------------------------------------------------------
|
||||
|
||||
public function ajax_handler_install_components() {
|
||||
require_once FACTORY_600_DIR . '/ajax/install-addons.php';
|
||||
wfactory_600_install_components( $this );
|
||||
}
|
||||
|
||||
public function ajax_handler_prepare_component() {
|
||||
require_once FACTORY_600_DIR . '/ajax/install-addons.php';
|
||||
wfactory_600_prepare_component( $this );
|
||||
}
|
||||
|
||||
public function ajax_handler_install_creativemotion_plugins() {
|
||||
require_once FACTORY_600_DIR . '/ajax/install-addons.php';
|
||||
wfactory_600_creativemotion_install_plugin( $this );
|
||||
}
|
||||
// --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Устанавливает класс менеджер, которому плагин будет делегировать подключение ресурсов (картинок,
|
||||
* скриптов, стилей) фреймворка.
|
||||
*
|
||||
* @param Wbcr_FactoryBootstrap500_Manager $bootstrap
|
||||
*/
|
||||
public function setBootstap( Wbcr_FactoryBootstrap500_Manager $bootstrap ) {
|
||||
$this->bootstrap = $bootstrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает класс менеджер, которому будет делегирована работа с html формами фреймворка.
|
||||
*
|
||||
* @param Wbcr_FactoryForms600_Manager $forms
|
||||
*/
|
||||
public function setForms( Wbcr_FactoryForms600_Manager $forms ) {
|
||||
$this->forms = $forms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает класс менеджер, которому будет делегирована работа с объявлениями в WordPress
|
||||
*
|
||||
* @since 4.1.9
|
||||
*/
|
||||
public function set_adverts_manager( $class_name ) {
|
||||
if ( empty( $this->adverts ) && $this->render_adverts ) {
|
||||
$this->adverts = new $class_name( $this, $this->adverts_settings );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает класс менеджер, которому будет делегирована работа с объявлениями в WordPress
|
||||
*
|
||||
* @param string $class_name Logger class name
|
||||
* @param array $settings Logger settings
|
||||
*
|
||||
* @since 4.3.7
|
||||
*/
|
||||
public function set_logger( $class_name, $settings = [] ) {
|
||||
if ( empty( $this->logger ) ) {
|
||||
$this->logger = new $class_name( $this, $settings );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает класс провайдера лицензий
|
||||
*
|
||||
* С помощью этого класса, мы проверяем валидность лицензий и получаем дополнительную информацию
|
||||
* о лицензии и ее покупателе. Класс используется в премиум менеджере.
|
||||
*
|
||||
* @param string $name Имя провайдер
|
||||
* @param string $class_name Имя класса провайдера
|
||||
*
|
||||
* @since 4.1.6 - Добавлен
|
||||
*/
|
||||
public function set_license_provider( $name, $class_name ) {
|
||||
if ( ! isset( WBCR\Factory_600\Premium\Manager::$providers[ $name ] ) ) {
|
||||
WBCR\Factory_600\Premium\Manager::$providers[ $name ] = $class_name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрируем класс репозитория
|
||||
*
|
||||
* С помощью этого класса мы реализиуем доставку и откат обновлений плагина, на сайт пользователя.
|
||||
* Скачиваение премиум версий происходит по защенному каналу. Класс используется в менеджере обновлений.
|
||||
*
|
||||
* @param string $name Имя репозитория
|
||||
* @param string $class_name Имя класса репозитория
|
||||
*
|
||||
* @since 4.1.7 - Добавлен
|
||||
*/
|
||||
public function set_update_repository( $name, $class_name ) {
|
||||
if ( ! isset( WBCR\Factory_600\Updates\Upgrader::$repositories[ $name ] ) ) {
|
||||
WBCR\Factory_600\Updates\Upgrader::$repositories[ $name ] = $class_name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить экземпляр менеджера объявления
|
||||
*
|
||||
* Доступен глобально через метод app(), чаще всего используется для создания точек для ротации
|
||||
* рекламных объявлений.
|
||||
*
|
||||
* @return \WBCR\Factory_Adverts_159\Base
|
||||
* @since 1.1
|
||||
*/
|
||||
public function get_adverts_manager() {
|
||||
return $this->adverts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает текстовый домен для плагина. Текстовый домен берется из заголовка входного
|
||||
* файла плагина.
|
||||
*
|
||||
* @since 4.2.5 - Добавлены 2 аргумента $text_domain, $plugin_dir. Теперь protected
|
||||
* @since 4.0.8 - Добавлен
|
||||
*
|
||||
* @see https://codex.wordpress.org/I18n_for_WordPress_Developers
|
||||
*/
|
||||
protected function set_text_domain( $text_domain, $plugin_dir ) {
|
||||
if ( empty( $text_domain ) || empty( $plugin_dir ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$locale = apply_filters( 'plugin_locale', is_admin() ? get_user_locale() : get_locale(), $text_domain );
|
||||
|
||||
$mofile = $text_domain . '-' . $locale . '.mo';
|
||||
|
||||
if ( ! load_textdomain( $text_domain, $plugin_dir . '/languages/' . $mofile ) ) {
|
||||
load_muplugin_textdomain( $text_domain );
|
||||
}
|
||||
}
|
||||
|
||||
public function newScriptList() {
|
||||
return new Wbcr_Factory600_ScriptList( $this );
|
||||
}
|
||||
|
||||
public function newStyleList() {
|
||||
return new Wbcr_Factory600_StyleList( $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Все страницы плагина создаются через специальную обертку, за которую отвечает модуль
|
||||
* фреймворка pages. Разработчик создает собственный класс, унаследованный от
|
||||
* Wbcr_FactoryPages600_AdminPage, а затем регистрирует его через этот метод.
|
||||
* Метод выполняет подключение класса страницы и регистрирует его в модуле фреймворка
|
||||
* pages.
|
||||
*
|
||||
* Больше информации о создании и регистрации страниц, вы можете узнать из документации по созданию
|
||||
* страниц плагина.
|
||||
*
|
||||
* @param string $class_name Имя регистрируемого класса страницы. Пример: WCL_Page_Name.
|
||||
* Регистрируемый класс должен быть унаследован от класса Wbcr_FactoryPages600_AdminPage.
|
||||
* @param string $file_path Абсолютный путь к файлу с классом страницы.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function registerPage( $class_name, $file_path ) {
|
||||
// if ( $this->isNetworkActive() && ! is_network_admin() ) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
if ( ! file_exists( $file_path ) ) {
|
||||
throw new Exception( 'The page file was not found by the path {' . $file_path . '} you set.' );
|
||||
}
|
||||
|
||||
require_once $file_path;
|
||||
|
||||
if ( ! class_exists( $class_name ) ) {
|
||||
throw new Exception( 'A class with this name {' . $class_name . '} does not exist.' );
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryPages600' ) ) {
|
||||
throw new Exception( 'The factory_pages_600 module is not included.' );
|
||||
}
|
||||
|
||||
Wbcr_FactoryPages600::register( $this, $class_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Произвольные типы записей в плагине, создаются через специальную обертку, за которую отвечает
|
||||
* модуль фреймворка types. Разработчик создает собственный класс, унаследованный от
|
||||
* Wbcr_FactoryTypes000_Type, а затем регистрирует его через этот метод. Метод выполняет
|
||||
* подключение класса с новым типом записи и регистрирует его в модуле фреймворка types. *
|
||||
*
|
||||
* @param string $class_name Имя регистрируемого класса страницы. Пример: WCL_Type_Name.
|
||||
* Регистрируемый класс должен быть унаследован от класса Wbcr_FactoryTypes000_Type.
|
||||
* @param string $file_path Абсолютный путь к файлу с классом страницы.
|
||||
*
|
||||
* @throws Exception
|
||||
* @deprecated 4.1.7 You cannot use it!
|
||||
*/
|
||||
public function registerType( $class_name, $file_path ) {
|
||||
throw new Exception( 'As of factory core module 4.1.7, the "registerType" method is deprecated. You cannot use it!' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a class to activate the plugin.
|
||||
*
|
||||
* @param string $className class name of the plugin activator.
|
||||
*
|
||||
* @return void
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function registerActivation( $className ) {
|
||||
$this->activator_class[] = $className;
|
||||
}
|
||||
|
||||
/*
|
||||
end services region
|
||||
/* -------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* It's invoked on plugin activation. Don't excite it directly.
|
||||
*
|
||||
* @return void
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function activation_hook() {
|
||||
|
||||
/**
|
||||
* @since 4.1.1 - change hook name
|
||||
*/
|
||||
if ( apply_filters( "wbcr/factory_600/cancel_plugin_activation_{$this->plugin_name}", false ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* wbcr_factory_600_plugin_activation
|
||||
*
|
||||
* @since 4.1.1 - deprecated
|
||||
*/
|
||||
wbcr_factory_600_do_action_deprecated(
|
||||
'wbcr_factory_600_plugin_activation',
|
||||
[
|
||||
$this,
|
||||
],
|
||||
'4.1.1',
|
||||
'wbcr/factory/plugin_activation'
|
||||
);
|
||||
|
||||
/**
|
||||
* wbcr/factory/plugin_activation
|
||||
*
|
||||
* @since 4.1.2 - deprecated
|
||||
*/
|
||||
wbcr_factory_600_do_action_deprecated(
|
||||
'wbcr/factory/plugin_activation',
|
||||
[
|
||||
$this,
|
||||
],
|
||||
'4.1.2',
|
||||
'wbcr/factory/before_plugin_activation'
|
||||
);
|
||||
|
||||
/**
|
||||
* wbcr/factory/before_plugin_activation
|
||||
*
|
||||
* @since 4.1.2 - added
|
||||
*/
|
||||
do_action( 'wbcr/factory/before_plugin_activation', $this );
|
||||
|
||||
/**
|
||||
* # wbcr/factory/plugin_{$this->plugin_name}_activation
|
||||
*
|
||||
* @since 4.1.2 - deprecated
|
||||
*/
|
||||
wbcr_factory_600_do_action_deprecated(
|
||||
"wbcr/factory/plugin_{$this->plugin_name}_activation",
|
||||
[
|
||||
$this,
|
||||
],
|
||||
'4.1.2',
|
||||
"wbcr/factory/before_plugin_{$this->plugin_name}_activation"
|
||||
);
|
||||
|
||||
/**
|
||||
* wbcr_factory_600_plugin_activation_' . $this->plugin_name
|
||||
*
|
||||
* @since 4.1.1 - deprecated
|
||||
*/
|
||||
wbcr_factory_600_do_action_deprecated(
|
||||
'wbcr_factory_600_plugin_activation_' . $this->plugin_name,
|
||||
[
|
||||
$this,
|
||||
],
|
||||
'4.1.1',
|
||||
"wbcr/factory/before_plugin_{$this->plugin_name}_activation"
|
||||
);
|
||||
|
||||
/**
|
||||
* wbcr/factory/plugin_{$this->plugin_name}_activation
|
||||
*
|
||||
* @since 4.1.2 - added
|
||||
*/
|
||||
do_action( "wbcr/factory/plugin_{$this->plugin_name}_activation", $this );
|
||||
|
||||
if ( ! empty( $this->activator_class ) ) {
|
||||
foreach ( (array) $this->activator_class as $activator_class ) {
|
||||
$activator = new $activator_class( $this );
|
||||
$activator->activate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1.2 - added
|
||||
*/
|
||||
do_action( 'wbcr/factory/plugin_activated', $this );
|
||||
|
||||
/**
|
||||
* @since 4.1.2 - added
|
||||
*/
|
||||
do_action( "wbcr/factory/plugin_{$this->plugin_name}_activated", $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* It's invoked on plugin deactionvation. Don't excite it directly.
|
||||
*
|
||||
* @return void
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function deactivation_hook() {
|
||||
|
||||
/**
|
||||
* @since 4.1.1 - change hook name
|
||||
*/
|
||||
if ( apply_filters( "wbcr/factory_600/cancel_plugin_deactivation_{$this->plugin_name}", false ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* wbcr_factory_600_plugin_deactivation
|
||||
*
|
||||
* @since 4.1.1 - deprecated
|
||||
*/
|
||||
wbcr_factory_600_do_action_deprecated(
|
||||
'wbcr_factory_600_plugin_deactivation',
|
||||
[
|
||||
$this,
|
||||
],
|
||||
'4.1.1',
|
||||
'wbcr/factory/plugin_deactivation'
|
||||
);
|
||||
|
||||
/**
|
||||
* wbcr/factory/plugin_deactivation
|
||||
*
|
||||
* @since 4.1.2 - deprecated
|
||||
*/
|
||||
wbcr_factory_600_do_action_deprecated(
|
||||
'wbcr/factory/plugin_deactivation',
|
||||
[
|
||||
$this,
|
||||
],
|
||||
'4.1.2',
|
||||
'wbcr/factory/before_plugin_deactivation'
|
||||
);
|
||||
|
||||
/**
|
||||
* wbcr/factory/plugin_deactivation
|
||||
*
|
||||
* @since 4.1.2 - added
|
||||
*/
|
||||
do_action( 'wbcr/factory/plugin_deactivation', $this );
|
||||
|
||||
/**
|
||||
* wbcr_factory_600_plugin_deactivation_ . $this->plugin_name
|
||||
*
|
||||
* @since 4.1.1 - deprecated
|
||||
*/
|
||||
wbcr_factory_600_do_action_deprecated(
|
||||
'wbcr_factory_600_plugin_deactivation_' . $this->plugin_name,
|
||||
[
|
||||
$this,
|
||||
],
|
||||
'4.1.1',
|
||||
"wbcr/factory/before_plugin_{$this->plugin_name}_deactivation"
|
||||
);
|
||||
|
||||
/**
|
||||
* wbcr/factory/plugin_{$this->plugin_name}_deactivation
|
||||
*
|
||||
* @since 4.1.2 - deprecated
|
||||
*/
|
||||
wbcr_factory_600_do_action_deprecated(
|
||||
"wbcr/factory/plugin_{$this->plugin_name}_deactivation",
|
||||
[
|
||||
$this,
|
||||
],
|
||||
'4.1.2',
|
||||
"wbcr/factory/before_plugin_{$this->plugin_name}_deactivation"
|
||||
);
|
||||
|
||||
/**
|
||||
* @since 4.1.2 - added
|
||||
*/
|
||||
do_action( "wbcr/factory/before_plugin_{$this->plugin_name}_deactivation" );
|
||||
|
||||
if ( ! empty( $this->activator_class ) ) {
|
||||
foreach ( (array) $this->activator_class as $activator_class ) {
|
||||
$activator = new $activator_class( $this );
|
||||
$activator->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1.2 - added
|
||||
*/
|
||||
do_action( 'wbcr/factory/plugin_deactivated', $this );
|
||||
|
||||
/**
|
||||
* @since 4.1.2 - added
|
||||
*/
|
||||
do_action( "wbcr/factory/plugin_{$this->plugin_name}_deactivated", $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ссылку на внутреннюю страницу плагина
|
||||
*
|
||||
* @param string $page_id
|
||||
*
|
||||
* @sicne: 4.0.8
|
||||
* @return string|void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getPluginPageUrl( $page_id, $args = [] ) {
|
||||
if ( ! class_exists( 'Wbcr_FactoryPages600' ) ) {
|
||||
throw new Exception( 'The factory_pages_600 module is not included.' );
|
||||
}
|
||||
|
||||
if ( ! is_admin() ) {
|
||||
_doing_it_wrong( __METHOD__, __( 'You cannot use this feature on the frontend.', 'robin-image-optimizer' ), '4.0.8' );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return Wbcr_FactoryPages600::getPageUrl( $this, $page_id, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows you to get a button to install the plugin component
|
||||
*
|
||||
* @param $component_type
|
||||
* @param $slug
|
||||
* param $premium
|
||||
*
|
||||
* @return \WBCR\Factory_600\Components\Install_Button
|
||||
*/
|
||||
public function get_install_component_button( $component_type, $slug ) {
|
||||
require_once FACTORY_600_DIR . '/includes/components/class-install-component-button.php';
|
||||
|
||||
return new \WBCR\Factory_600\Components\Install_Button( $this, $component_type, $slug );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows you to get a button to delete the plugin component
|
||||
*
|
||||
* @param $component_type
|
||||
* @param $slug
|
||||
*
|
||||
* @return \WBCR\Factory_600\Components\Delete_Button
|
||||
*/
|
||||
public function get_delete_component_button( $component_type, $slug ) {
|
||||
require_once FACTORY_600_DIR . '/includes/components/class-delete-component-button.php';
|
||||
|
||||
return new WBCR\Factory_600\Components\Delete_Button( $this, $component_type, $slug );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $component_name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_activate_component( $component_name ) {
|
||||
if ( ! is_string( $component_name ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$deactivate_components = $this->getPopulateOption( 'deactive_preinstall_components', [] );
|
||||
|
||||
if ( ! is_array( $deactivate_components ) ) {
|
||||
$deactivate_components = [];
|
||||
}
|
||||
|
||||
if ( $deactivate_components && in_array( $component_name, $deactivate_components ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $component_name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function activate_component( $component_name ) {
|
||||
if ( $this->is_activate_component( $component_name ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
do_action( 'wfactory/pre_activate_component', $component_name );
|
||||
|
||||
$deactivate_components = $this->getPopulateOption( 'deactive_preinstall_components', [] );
|
||||
|
||||
if ( ! empty( $deactivate_components ) && is_array( $deactivate_components ) ) {
|
||||
$index = array_search( $component_name, $deactivate_components );
|
||||
unset( $deactivate_components[ $index ] );
|
||||
}
|
||||
|
||||
if ( empty( $deactivate_components ) ) {
|
||||
$this->deletePopulateOption( 'deactive_preinstall_components' );
|
||||
} else {
|
||||
$this->updatePopulateOption( 'deactive_preinstall_components', $deactivate_components );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $component_name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deactivate_component( $component_name ) {
|
||||
if ( ! $this->is_activate_component( $component_name ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
do_action( 'wfactory/pre_deactivate_component', $component_name );
|
||||
|
||||
$deactivate_components = $this->getPopulateOption( 'deactive_preinstall_components', [] );
|
||||
|
||||
if ( ! empty( $deactivate_components ) && is_array( $deactivate_components ) ) {
|
||||
$deactivate_components[] = $component_name;
|
||||
} else {
|
||||
$deactivate_components = [];
|
||||
$deactivate_components[] = $component_name;
|
||||
}
|
||||
|
||||
$this->updatePopulateOption( 'deactive_preinstall_components', $deactivate_components );
|
||||
|
||||
do_action( 'wfactory/deactivated_component', $component_name );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Загружает аддоны для плагина, как часть проекта, а не как отдельный плагин
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function init_plugin_components() {
|
||||
|
||||
$load_plugin_components = $this->get_load_plugin_components();
|
||||
|
||||
if ( empty( $load_plugin_components ) || ! is_array( $load_plugin_components ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $load_plugin_components as $component_ID => $component ) {
|
||||
if ( ! isset( $this->loaded_plugin_components[ $component_ID ] ) ) {
|
||||
|
||||
if ( ! isset( $component['autoload'] ) || ! isset( $component['plugin_prefix'] ) ) {
|
||||
throw new Exception( sprintf( 'Component %s cannot be loaded, you must specify the path to the component autoload file and plugin prefix!', $component_ID ) );
|
||||
}
|
||||
|
||||
$prefix = rtrim( $component['plugin_prefix'], '_' ) . '_';
|
||||
|
||||
if ( defined( $prefix . 'PLUGIN_ACTIVE' ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$autoload_file = trailingslashit( $this->get_paths()->absolute ) . $component['autoload'];
|
||||
|
||||
if ( ! file_exists( $autoload_file ) ) {
|
||||
throw new Exception( sprintf( 'Component %s autoload file not found!', $component_ID ) );
|
||||
}
|
||||
|
||||
$plugin_var_name = strtolower( $prefix . 'plugin' );
|
||||
global $$plugin_var_name;
|
||||
$$plugin_var_name = $this;
|
||||
|
||||
require_once $autoload_file;
|
||||
|
||||
if ( defined( $prefix . 'PLUGIN_ACTIVE' ) ) {
|
||||
$this->loaded_plugin_components[ $component_ID ] = [
|
||||
'plugin_dir' => constant( $prefix . 'PLUGIN_DIR' ),
|
||||
'plugin_url' => constant( $prefix . 'PLUGIN_URL' ),
|
||||
'plugin_base' => constant( $prefix . 'PLUGIN_BASE' ),
|
||||
'text_domain' => constant( $prefix . 'TEXT_DOMAIN' ),
|
||||
'plugin_version' => constant( $prefix . 'PLUGIN_VERSION' ),
|
||||
];
|
||||
|
||||
/**
|
||||
* Оповещает внешние приложения, что компонент плагина был загружен
|
||||
*
|
||||
* @param array $load_plugin_components Информация о загруженном компоненте
|
||||
* @param string $plugin_name Имя плагина
|
||||
*/
|
||||
do_action( "wbcr/factory/component_{$component_ID}_loaded", $this->loaded_plugin_components[ $component_ID ], $this->getPluginName() );
|
||||
} else {
|
||||
throw new Exception( sprintf( 'Сomponent %s does not meet development standards!', $component_ID ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Загружает специальные модули для расширения Factory фреймворка.
|
||||
* Разработчик плагина сам выбирает, какие модули ему нужны для
|
||||
* создания плагина.
|
||||
*
|
||||
* Модули фреймворка хранятся в libs/factory/framework
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function init_framework_modules() {
|
||||
|
||||
if ( ! empty( $this->load_factory_modules ) ) {
|
||||
foreach ( (array) $this->load_factory_modules as $module ) {
|
||||
$scope = isset( $module[2] ) ? $module[2] : 'all';
|
||||
|
||||
if ( $scope == 'all' || ( is_admin() && $scope == 'admin' ) || ( ! is_admin() && $scope == 'public' ) ) {
|
||||
|
||||
if ( ! file_exists( $this->get_paths()->absolute . '/' . $module[0] . '/boot.php' ) ) {
|
||||
throw new Exception( 'Module ' . $module[1] . ' is not included.' );
|
||||
}
|
||||
|
||||
$module_boot_file = $this->get_paths()->absolute . '/' . $module[0] . '/boot.php';
|
||||
require_once $module_boot_file;
|
||||
|
||||
$this->loaded_factory_modules[ $module[1] ] = $module_boot_file;
|
||||
|
||||
do_action( 'wbcr_' . $module[1] . '_plugin_created', $this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1.1 - deprecated
|
||||
*/
|
||||
wbcr_factory_600_do_action_deprecated( 'wbcr_factory_600_core_modules_loaded-' . $this->plugin_name, [], '4.1.1', 'wbcr/factory_600/modules_loaded-' . $this->plugin_name );
|
||||
|
||||
/**
|
||||
* @since 4.1.1 - add
|
||||
*/
|
||||
do_action( 'wbcr/factory_600/modules_loaded-' . $this->plugin_name );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setups actions related with the Factory Plugin.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function register_plugin_hooks() {
|
||||
|
||||
add_action(
|
||||
'plugins_loaded',
|
||||
function () {
|
||||
$this->set_text_domain( $this->plugin_text_domain, $this->paths->absolute );
|
||||
|
||||
if ( ! empty( $this->loaded_plugin_components ) ) {
|
||||
foreach ( $this->loaded_plugin_components as $component ) {
|
||||
if ( empty( $component['text_domain'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->set_text_domain( $component['text_domain'], $component['plugin_dir'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if ( is_admin() ) {
|
||||
add_filter( 'wbcr_factory_600_core_admin_allow_multisite', '__return_true' );
|
||||
|
||||
register_activation_hook( $this->get_paths()->main_file, [ $this, 'activation_hook' ] );
|
||||
register_deactivation_hook( $this->get_paths()->main_file, [ $this, 'deactivation_hook' ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициализируем миграции плагина
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function init_plugin_migrations() {
|
||||
new WBCR\Factory_600\Migrations( $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициализируем уведомления плагина
|
||||
*
|
||||
* @return void
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function init_plugin_notices() {
|
||||
new Wbcr\Factory_600\Notices( $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает нового рабочего для проверки обновлений и апгрейда текущего плагина.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function init_plugin_updates() {
|
||||
if ( $this->has_updates ) {
|
||||
new WBCR\Factory_600\Updates\Upgrader( $this );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Начинает инициализацию лицензирования текущего плагина. Доступ к менеджеру лицензий можно
|
||||
* получить через свойство license_manager.
|
||||
*
|
||||
* Дополнительно создает рабочего, чтобы совершить апгрейд до премиум версии
|
||||
* и запустить проверку обновлений для этого модуля.
|
||||
*
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function init_plugin_premium_features() {
|
||||
if ( ! $this->has_premium || ! $this->license_settings ) {
|
||||
$this->premium = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Создаем экземляр премиум менеджера, мы сможем к нему обращаться глобально.
|
||||
$this->premium = WBCR\Factory_600\Premium\Manager::instance( $this, $this->license_settings );
|
||||
|
||||
// Подключаем премиум апгрейдер
|
||||
if ( isset( $this->license_settings['has_updates'] ) && $this->license_settings['has_updates'] ) {
|
||||
new WBCR\Factory_600\Updates\Premium_Upgrader( $this );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,565 @@
|
||||
<?php
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Базовый класс для создания нового плагина. Полную реализацию класса смотрите в Wbcr_Factory600_Plugin
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package factory-core
|
||||
*/
|
||||
class Wbcr_Factory600_Base {
|
||||
|
||||
use WBCR\Factory_600\Options;
|
||||
|
||||
/**
|
||||
* Обязательное свойство. Префикс, используется для создания пространство имен.
|
||||
* Чаще всего используется на именования опций в базе данных. Также может быть
|
||||
* использован для именования полей html форм, создания уникальных имен, хуков.
|
||||
* Пример: wrio_
|
||||
*
|
||||
* Для префикса всегда используете нижнее подчеркивание справа!
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* Обязательное свойство. Заголовок плагина. Используете в интерфейсе плагина,
|
||||
* может быть использован в уведомлениях для администратора, чтобы пользователь
|
||||
* мог понять, с каким плагином он ведет коммуникацию. Пример: Robin image optimizer
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_title;
|
||||
|
||||
/**
|
||||
* Обязательное свойство. Имя плагина. Используется аналогично префиксу, но с небольшим
|
||||
* отличием. Имя плагина имеет человеку понятную строку, которую можно использовать в
|
||||
* именовании хуков, созданию условной логики. Допустимые символы [A-z0-9_].
|
||||
* Пример: wbcr_clearfy
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_name;
|
||||
|
||||
protected $plugin_slug;
|
||||
|
||||
/**
|
||||
* Обязательное свойство. Версия плагина в формате 0.0.0. Допустимые символы [0-9.]
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_version;
|
||||
|
||||
/**
|
||||
* Обязательное свойство. Текстовый домен плагина, используется для подключения файлов
|
||||
* переводов. Рекомендуется использовать slug плагина, идентичный slug в репозитории
|
||||
* Wordpress.org
|
||||
*
|
||||
* @since 4.1.1
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_text_domain;
|
||||
|
||||
/**
|
||||
* Обязательное свойство. Информация для поддержки клиента. Для начала работы плагина,
|
||||
* достаточно только указать адрес лендинга в атрибут url. На лендинге должны быть
|
||||
* созданы страницы features, pricing, support, docs. Если страницы (features, pricing,
|
||||
* support, docs) не могут иметь такие же адреса, вы можете наложить карту адресов в
|
||||
* атрибуте pages_map. К примеру: я создал страницу "Pro Features" и она имеет адрес
|
||||
* {site}/premium-features, для pages_map в атрибуте features, я указал, что адрес
|
||||
* страницы со списком функций имеет слаг premium-features. Теперь плагин будет понимать,
|
||||
* что адрес страницы со списком функций будет таким:
|
||||
*
|
||||
* Это свойство заполняется для того, чтобы в процессе разработки вы могли использовать
|
||||
* экземпляр класса \WBCR\Factory_600\Entities\Support, для получения информации о сайте плагина.
|
||||
* Тем самым вы избавляете себя от жесткого прописывания ссылок на лендинг плагина и
|
||||
* можете изменить все ссылки в одном месте.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $support_details;
|
||||
|
||||
/**
|
||||
* Включение/отключение обновлений для бесплатного плагина. Если вашего плагина нет в репозитори
|
||||
* Wordpress.org, вы можете включить собственный режим обновлений, например через GitHub или
|
||||
* собственный репозиторий. Если установлено true, плагин будет проверять наличие обновлений
|
||||
* для этого плагина.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $has_updates = false;
|
||||
|
||||
/**
|
||||
* Настройка обновлений для бесплатного плагина. Если вы хотите настроить обновления для
|
||||
* бесплатного плагина через собственный репозиторий (например: github), вам нужно указать имя
|
||||
* репозитория и slug плагина. Slug может быть идентичен имени репозитория в github. Для Wordpress.org
|
||||
* эти настройки не обязательны, так как в WordPress ядре есть встроенные функции для обновлений
|
||||
* плагинов и тем.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $updates_settings = [];
|
||||
|
||||
/**
|
||||
* Включение/отключение премиум версии для плагина. Если вы создаете бесплатный плагин и хотите
|
||||
* реализовать для него премиум версию, вам нужно начать с этого свойства. Если свойство установлено,
|
||||
* как true, при инициализации плагина будут подключены функции лицензирования, проверки обновлений
|
||||
* для премиум версии.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $has_premium = false;
|
||||
|
||||
/**
|
||||
* Настройки лицензирования
|
||||
*
|
||||
* Лицензирование плагина может быть реализовано для любого провайдера,
|
||||
* к примеру: freemius, codecanyon, templatemonster, вам нужно указать только настройки для
|
||||
* взаимодействия с выбранным вами провайдером. Каждая реализация провайдера лицензий может иметь
|
||||
* индивидуальный настройки, в этом примере приведены настройки для freemius провайдера
|
||||
* WBCR\Factory_600\Premium\Provider > WBCR\Factory_Freemius_Rio_600\Premium\Provider
|
||||
*
|
||||
* На текущий момент существует только реализация для freemius провайдера.
|
||||
*
|
||||
* Для премиум плагина вы должны также указать настройки обновлений. Атрибут has_updates
|
||||
* включает/отключает обновления для премиум плагина, в атрибуте updates_settings вы указываете
|
||||
* дополнительные настройки обновлений.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $license_settings = [];
|
||||
|
||||
/**
|
||||
* Переключатель внутренней рекламы в плагине
|
||||
*
|
||||
* Если установить true, то плагин будет показывать рекламу компании в интерфейсе WordPress.
|
||||
* Рекламный модуль может отображать рекламу внутри инрефейса плагина, на странице dashboard
|
||||
* и создавать сквозные уведомления на всех страницах админ панели WordPress.
|
||||
*
|
||||
* @since 4.1.9
|
||||
* @var bool
|
||||
*/
|
||||
protected $render_adverts = false;
|
||||
|
||||
/**
|
||||
* Настройки внутренней рекламы компании
|
||||
*
|
||||
* @since 4.1.9
|
||||
* @var array
|
||||
*/
|
||||
protected $adverts_settings = [];
|
||||
|
||||
/**
|
||||
* Обязательное свойство. Подключаемые модули фреймворка.
|
||||
*
|
||||
* Модули фреймворка позволяют расширять его функциональность.
|
||||
*
|
||||
* @var array {
|
||||
* Array with information about the loadable module
|
||||
* {type} string $module [0] Relative path to the module directory
|
||||
* {type} string $module [1] Module name with prefix 000
|
||||
* {type} string $module [2] Scope:
|
||||
* admin - Module will be loaded only in the admin panel,
|
||||
* public - Module will be loaded only on the frontend
|
||||
* all - Module will be loaded everywhere
|
||||
* }
|
||||
*/
|
||||
protected $load_factory_modules = [
|
||||
[ 'libs/factory/bootstrap', 'factory_bootstrap_500', 'admin' ],
|
||||
[ 'libs/factory/forms', 'factory_forms_600', 'admin' ],
|
||||
[ 'libs/factory/pages', 'factory_pages_600', 'admin' ],
|
||||
];
|
||||
|
||||
/**
|
||||
* Не обязательное свойство. Список подключаемых компонентов плагина.
|
||||
*
|
||||
* Компоненты плагина, это независимые плагины, которые расширяют возможности текущего плагина.
|
||||
* Вы должны указать файл для автозагрузки компонента и префикс плагина, чтобы фреймворк
|
||||
* мог обращаться к классам и константам компонентов.
|
||||
*
|
||||
* @since 4.2.0 Добавлен
|
||||
* @var array Пример данных
|
||||
* array(
|
||||
* 'component_ID' => array(
|
||||
* 'autoload' => 'relative_path/autoload_filename.php',
|
||||
* 'plugin_prefix' => 'WPRFX_'
|
||||
* ),
|
||||
* // Реальный пример
|
||||
* 'cyrlitera' => array(
|
||||
* 'autoload' => 'components/cyrlitera/clearfy.php',
|
||||
* 'plugin_prefix' => 'WCTR_'
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
protected $load_plugin_components = [];
|
||||
|
||||
|
||||
/**
|
||||
* Экземпляр класса \WBCR\Factory_600\Entities\Support используется для получения информации
|
||||
* о сайте плагина. Чаще всего используется для получения ссылки на страницу с тарифами или
|
||||
* ссылки на форму обратной связи. Встроен механизм отслеживания по utm меткам.
|
||||
*
|
||||
* @var \WBCR\Factory_600\Entities\Support
|
||||
*/
|
||||
protected $support;
|
||||
|
||||
/**
|
||||
* Экземпляр класса \WBCR\Factory_600\Entities\Paths используется для получения информации о
|
||||
* путях плагина. Часто используется для получения путей или ссылок на место хранения плагина
|
||||
* или его входного файла.
|
||||
*
|
||||
* @var \WBCR\Factory_600\Entities\Paths
|
||||
*/
|
||||
protected $paths;
|
||||
|
||||
/**
|
||||
* Абсолютный путь к входному файлу плагина: C://server/site.dev/wp-content/plugins/plugin_name/plugin_name.php
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $plugin_file;
|
||||
|
||||
/**
|
||||
* Свойство хранит сырые настройки плагина, а также дополнительные настройки, которые не описаны
|
||||
* в интерфейсе класса.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $plugin_data;
|
||||
|
||||
/**
|
||||
* Конструктор:
|
||||
* - Заполняет свойства класса из сырых данных плагина
|
||||
* - Выполняет проверку на обязательные настройки
|
||||
* - Инициализирует сущности support и paths
|
||||
*
|
||||
* @param string $plugin_file
|
||||
* @param array $data
|
||||
*
|
||||
* @throws Exception
|
||||
* @since 4.0.8 - добавлена дополнительная логика
|
||||
*
|
||||
* @since 4.1.1 - добавил две сущности support, paths. Удалил свойства, plugin_build
|
||||
* plugin_assembly, main_file, plugin_root, relative_path, plugin_url
|
||||
*/
|
||||
public function __construct( $plugin_file, $data ) {
|
||||
$this->plugin_file = $plugin_file;
|
||||
$this->plugin_data = $data;
|
||||
|
||||
foreach ( (array) $data as $option_name => $option_value ) {
|
||||
if ( property_exists( $this, $option_name ) ) {
|
||||
$this->$option_name = $option_value;
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $this->prefix ) || empty( $this->plugin_name ) || empty( $this->plugin_title ) || empty( $this->plugin_version ) || empty( $this->plugin_text_domain ) ) {
|
||||
throw new Exception( 'One of the required attributes has not been passed (prefix, plugin_title, plugin_name, plugin_version, plugin_text_domain).' );
|
||||
}
|
||||
|
||||
$this->support = new \WBCR\Factory_600\Entities\Support( $this->support_details );
|
||||
$this->paths = new \WBCR\Factory_600\Entities\Paths( $plugin_file );
|
||||
|
||||
// used only in the module 'updates'
|
||||
$this->plugin_slug = ! empty( $this->plugin_name ) ? $this->plugin_name : basename( $plugin_file );
|
||||
}
|
||||
|
||||
/**
|
||||
* При обновлении фреймворка, некоторые свойства класса были удалены. Однако плагины на старом
|
||||
* фреймворке по прежнему используют удаленные свойства. С помощью этого магического метода мы
|
||||
* добавляем совместимость со старыми плагинами, но при этом выводим предупреждение, что нужно
|
||||
* обновить некоторые свойства.
|
||||
*
|
||||
* @param string $name Имя свойства класса.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get( $name ) {
|
||||
|
||||
$deprecated_props = [
|
||||
'plugin_build',
|
||||
'plugin_assembly',
|
||||
'main_file',
|
||||
'plugin_root',
|
||||
'relative_path',
|
||||
'plugin_url',
|
||||
];
|
||||
|
||||
if ( in_array( $name, $deprecated_props ) ) {
|
||||
$deprecated_message = 'In version 4.1.1 of the Factory framework, the class properties ';
|
||||
$deprecated_message .= '(' . implode( ',', $deprecated_props ) . ')';
|
||||
$deprecated_message .= 'have been removed. To get plugin paths, use the new paths property.' . PHP_EOL;
|
||||
|
||||
$backtrace = debug_backtrace();
|
||||
if ( ! empty( $backtrace ) && isset( $backtrace[1] ) ) {
|
||||
$deprecated_message .= 'BACKTRACE:(';
|
||||
$deprecated_message .= 'File: ' . $backtrace[1]['file'];
|
||||
$deprecated_message .= 'Function: ' . $backtrace[1]['function'];
|
||||
$deprecated_message .= 'Line: ' . $backtrace[1]['line'];
|
||||
$deprecated_message .= ')';
|
||||
}
|
||||
|
||||
_deprecated_argument( __METHOD__, '4.1.1', $deprecated_message );
|
||||
|
||||
switch ( $name ) {
|
||||
case 'plugin_build':
|
||||
return null;
|
||||
break;
|
||||
case 'plugin_assembly':
|
||||
return null;
|
||||
break;
|
||||
case 'main_file':
|
||||
return $this->get_paths()->main_file;
|
||||
break;
|
||||
case 'plugin_root':
|
||||
return $this->get_paths()->absolute;
|
||||
break;
|
||||
case 'relative_path':
|
||||
return $this->get_paths()->basename;
|
||||
break;
|
||||
case 'plugin_url':
|
||||
return $this->get_paths()->url;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* При обновлении фреймворка, некоторые методы класса были удалены. Однако плагины на старом фреймворке
|
||||
* по прежнему используют удаленные методы. С помощью этого магического метода мы добавляем совместимость
|
||||
* со старыми плагинами, но при этом выводим предупреждение, что нужно обновить некоторые методы.
|
||||
*
|
||||
* @param string $name Имя метода класса.
|
||||
* @param array $arguments Массив аргументов метода класса.
|
||||
*
|
||||
* @return stdClass|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call( $name, $arguments ) {
|
||||
|
||||
$deprecated_methods = [
|
||||
'getPluginBuild',
|
||||
'getPluginAssembly',
|
||||
'getPluginPathInfo',
|
||||
];
|
||||
|
||||
if ( in_array( $name, $deprecated_methods ) ) {
|
||||
$deprecated_message = 'In version 4.1.1 of the Factory framework, methods (' . implode( ',', $deprecated_methods ) . ') have been removed.';
|
||||
|
||||
$backtrace = debug_backtrace();
|
||||
if ( ! empty( $backtrace ) && isset( $backtrace[1] ) ) {
|
||||
$deprecated_message .= 'BACKTRACE:(';
|
||||
$deprecated_message .= 'File: ' . $backtrace[1]['file'];
|
||||
$deprecated_message .= 'Function: ' . $backtrace[1]['function'];
|
||||
$deprecated_message .= 'Line: ' . $backtrace[1]['line'];
|
||||
$deprecated_message .= ')';
|
||||
}
|
||||
|
||||
_deprecated_argument( __METHOD__, '4.1.1', $deprecated_message );
|
||||
|
||||
if ( 'getPluginPathInfo' == $name ) {
|
||||
$object = new stdClass();
|
||||
|
||||
$object->main_file = $this->get_paths()->main_file;
|
||||
$object->plugin_root = $this->get_paths()->absolute;
|
||||
$object->relative_path = $this->get_paths()->basename;
|
||||
$object->plugin_url = $this->get_paths()->url;
|
||||
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception( "Method {$name} does not exist" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, включен ли премиум для этого плагина или нет.
|
||||
*
|
||||
* @return bool Возвращает true, если премиум пакет включен для этого плагина.
|
||||
* См. Wbcr_Factory600_Base::has_premium
|
||||
*/
|
||||
public function has_premium() {
|
||||
return $this->has_premium;
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить заголовок плагина.
|
||||
*
|
||||
* @return string Возвращает заголовок плагина. См. Wbcr_Factory600_Base::plugin_title
|
||||
*/
|
||||
public function getPluginTitle() {
|
||||
return apply_filters( 'wbcr/factory/plugin_title', $this->plugin_title, $this->getPluginName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить префикс плагина.
|
||||
*
|
||||
* @return string Возвращает префикс плагина.См. Wbcr_Factory600_Base::prefix
|
||||
*/
|
||||
public function getPrefix() {
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить имя плагина.
|
||||
*
|
||||
* @return string Возвращает имя плагина. См. Wbcr_Factory600_Base::plugin_name
|
||||
*/
|
||||
public function getPluginName() {
|
||||
return $this->plugin_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить версию плагина.
|
||||
*
|
||||
* @return string Возвращает версию плагина. См. Wbcr_Factory600_Base::plugin_version
|
||||
*/
|
||||
public function getPluginVersion() {
|
||||
return $this->plugin_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить список подключаемых к плагином компонентов
|
||||
*
|
||||
* @return array
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function get_load_plugin_components() {
|
||||
return $this->load_plugin_components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Предоставляет доступ к сырым данным плагина. Может быть полезен, если вы хотите получить
|
||||
* какие-то данные не описанные в интерфейсе этого плагина.
|
||||
*
|
||||
* @param string $attr_name Имя атрибута, который нужно получить. Идентично ключу в массиве
|
||||
* Wbcr_Factory600_Base::plugin_data
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getPluginInfoAttr( $attr_name ) {
|
||||
if ( isset( $this->plugin_data[ $attr_name ] ) ) {
|
||||
return $this->plugin_data[ $attr_name ];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Предоставляет доступ к экземпляру класса \WBCR\Factory_600\Entities\Support.
|
||||
*
|
||||
* @return \WBCR\Factory_600\Entities\Support
|
||||
*/
|
||||
public function get_support() {
|
||||
return $this->support;
|
||||
}
|
||||
|
||||
/**
|
||||
* Предоставляет доступ к экземпляру класса \WBCR\Factory_600\Entities\Paths.
|
||||
*
|
||||
* @return \WBCR\Factory_600\Entities\Paths
|
||||
*/
|
||||
public function get_paths() {
|
||||
return $this->paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить сырые данные плагина в виде объекта StdClass.
|
||||
*
|
||||
* @return object Возвращает объект с сырыми данными плагина. См. Wbcr_Factory600_Base::plugin_data
|
||||
*/
|
||||
public function getPluginInfo() {
|
||||
return (object) $this->plugin_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет права пользователя
|
||||
*
|
||||
* @return bool
|
||||
* @since 4.2.0 Добавлен
|
||||
*/
|
||||
public function current_user_can( $capability = 'manage_options' ) {
|
||||
// Просмотр страниц: read_pages
|
||||
// Просмотр уведомлений: read_notices
|
||||
// Редактирование: edit_forms
|
||||
|
||||
if ( 'manage_options' == $capability && is_multisite() && $this->isNetworkActive() ) {
|
||||
$capability = 'manage_network';
|
||||
}
|
||||
|
||||
return current_user_can( $capability );
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверят, находится ли пользователь в панели усправления сетью сайтов
|
||||
*
|
||||
* @return bool
|
||||
* @since 4.0.8 Добавлен
|
||||
*/
|
||||
public function isNetworkAdmin() {
|
||||
return is_multisite() && is_network_admin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет активирован ли плагин для сети. Если проект работает в режиме мультисайтов..
|
||||
*
|
||||
* @return bool Если true, плагин активирован для сети или в текущий момент активируется для сети.
|
||||
* @since 4.0.8 Добавлен
|
||||
*/
|
||||
public function isNetworkActive() {
|
||||
// Makes sure the plugin is defined before trying to use it
|
||||
if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
|
||||
require_once ABSPATH . '/wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
$activate = is_plugin_active_for_network( $this->get_paths()->basename );
|
||||
|
||||
if ( ! $activate && $this->isNetworkAdmin() && isset( $_GET['action'] ) && $_GET['action'] == 'activate' ) {
|
||||
return isset( $_GET['networkwide'] ) && 1 == (int) $_GET['networkwide'];
|
||||
}
|
||||
|
||||
return $activate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет получить все активные сайты сети. Если проект работает в режиме мультисайтов.
|
||||
*
|
||||
* @return array|int
|
||||
* @since 4.0.8
|
||||
*/
|
||||
public function getActiveSites( $args = [
|
||||
'archived' => 0,
|
||||
'mature' => 0,
|
||||
'spam' => 0,
|
||||
'deleted' => 0,
|
||||
]) {
|
||||
global $wp_version;
|
||||
|
||||
if ( version_compare( $wp_version, '4.6', '>=' ) ) {
|
||||
return get_sites( $args );
|
||||
} else {
|
||||
$converted_array = [];
|
||||
|
||||
$sites = wp_get_sites( $args );
|
||||
|
||||
if ( empty( $sites ) ) {
|
||||
return $converted_array;
|
||||
}
|
||||
|
||||
foreach ( (array) $sites as $key => $site ) {
|
||||
$obj = new stdClass();
|
||||
foreach ( $site as $attr => $value ) {
|
||||
$obj->$attr = $value;
|
||||
}
|
||||
$converted_array[ $key ] = $obj;
|
||||
}
|
||||
|
||||
return $converted_array;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* @package factory-core
|
||||
*/
|
||||
|
||||
class Wbcr_Factory600_Request {
|
||||
|
||||
/**
|
||||
* @param string|null $param
|
||||
* @param bool|string $sanitize true/false or sanitize function name
|
||||
* @param bool $default
|
||||
* @param string $method_name
|
||||
*
|
||||
* @return array|bool|mixed
|
||||
*/
|
||||
private function getBody( $param, $sanitize = false, $default = false, $method_name = 'REQUEST' ) {
|
||||
if ( empty( $param ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$sanitize_function_name = 'sanitize_text_field';
|
||||
|
||||
switch ( strtoupper( $method_name ) ) {
|
||||
case 'GET':
|
||||
$method = $_GET;
|
||||
break;
|
||||
case 'POST':
|
||||
$method = $_POST;
|
||||
break;
|
||||
case 'REQUEST':
|
||||
$method = $_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( is_string( $sanitize ) && $sanitize !== $sanitize_function_name ) {
|
||||
$sanitize_function_name = $sanitize;
|
||||
}
|
||||
|
||||
if ( isset( $method[ $param ] ) ) {
|
||||
if ( is_array( $method[ $param ] ) ) {
|
||||
return ! empty( $sanitize ) ? $this->recursiveArrayMap( $sanitize_function_name, $method[ $param ] ) : $method[ $param ];
|
||||
} else {
|
||||
return ! empty( $sanitize ) ? call_user_func( $sanitize_function_name, $method[ $param ] ) : $method[ $param ];
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive sanitation for an array
|
||||
*
|
||||
* @param string $function_name
|
||||
* @param $array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function recursiveArrayMap( $function_name, $array ) {
|
||||
foreach ( $array as $key => &$value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
$value = $this->recursiveArrayMap( $function_name, $value );
|
||||
} else {
|
||||
if ( ! function_exists( $function_name ) ) {
|
||||
throw new Exception( 'Function ' . $function_name . 'is undefined.' );
|
||||
}
|
||||
|
||||
$value = $function_name( $value );
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $param
|
||||
* @param mixed $default see method getBody
|
||||
* @param bool $sanitize
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function request( $param, $default = false, $sanitize = false ) {
|
||||
return $this->getBody( $param, $sanitize, $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $param
|
||||
* @param mixed $default see method getBody
|
||||
* @param bool $sanitize
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function get( $param, $default = false, $sanitize = false ) {
|
||||
return $this->getBody( $param, $sanitize, $default, 'get' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $param
|
||||
* @param mixed $default see method getBody
|
||||
* @param bool $sanitize
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function post( $param, $default = false, $sanitize = false ) {
|
||||
return $this->getBody( $param, $sanitize, $default, 'post' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class to check if the current WordPress and PHP versions meet our requirements
|
||||
*
|
||||
* @version 2.0.0
|
||||
* @since 4.0.9
|
||||
*/
|
||||
// @formatter:off
|
||||
if ( ! class_exists( 'Wbcr_Factory600_Requirements' ) ) {
|
||||
class Wbcr_Factory600_Requirements {
|
||||
|
||||
/**
|
||||
* Factory framework version
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $factory_version;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_version;
|
||||
|
||||
/**
|
||||
* Plugin file path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_file;
|
||||
|
||||
/**
|
||||
* Plugin dir
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_abs_path;
|
||||
|
||||
/**
|
||||
* Plugin base dir
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_basename;
|
||||
|
||||
/**
|
||||
* Plugin url
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_url;
|
||||
|
||||
/**
|
||||
* Plugin prefix
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_prefix;
|
||||
|
||||
/**
|
||||
* Plugin name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_name;
|
||||
|
||||
/**
|
||||
* Plugin title
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_title = '(no title)';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_text_domain;
|
||||
|
||||
/**
|
||||
* Required PHP version
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $required_php_version = '5.3';
|
||||
|
||||
/**
|
||||
* Required WordPress version
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $required_wp_version = '4.2.0';
|
||||
|
||||
/**
|
||||
* Is this plugin already activated?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $plugin_already_activate = false;
|
||||
|
||||
/**
|
||||
* WFF_Requirements constructor.
|
||||
*
|
||||
* @param string $plugin_file
|
||||
* @param array $plugin_info
|
||||
*/
|
||||
public function __construct( $plugin_file, array $plugin_info ) {
|
||||
|
||||
foreach ( (array) $plugin_info as $property => $value ) {
|
||||
if ( property_exists( $this, $property ) ) {
|
||||
$this->$property = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$this->plugin_file = $plugin_file;
|
||||
$this->plugin_abs_path = dirname( $plugin_file );
|
||||
$this->plugin_basename = plugin_basename( $plugin_file );
|
||||
$this->plugin_url = plugins_url( '', $plugin_file );
|
||||
|
||||
$plugin_info = get_file_data(
|
||||
$this->plugin_file,
|
||||
[
|
||||
'Version' => 'Version',
|
||||
'FrameworkVersion' => 'Framework Version',
|
||||
'TextDomain' => 'Text Domain',
|
||||
],
|
||||
'plugin'
|
||||
);
|
||||
|
||||
if ( isset( $plugin_info['FrameworkVersion'] ) ) {
|
||||
$this->factory_version = $plugin_info['FrameworkVersion'];
|
||||
}
|
||||
|
||||
if ( isset( $plugin_info['Version'] ) ) {
|
||||
$this->plugin_version = $plugin_info['Version'];
|
||||
}
|
||||
|
||||
if ( isset( $plugin_info['TextDomain'] ) ) {
|
||||
$this->plugin_text_domain = $plugin_info['TextDomain'];
|
||||
}
|
||||
|
||||
add_action( 'admin_init', [ $this, 'register_notices' ] );
|
||||
}
|
||||
|
||||
public function get_plugin_version() {
|
||||
return $this->plugin_version;
|
||||
}
|
||||
|
||||
public function get_text_domain() {
|
||||
return $this->plugin_text_domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1.1
|
||||
* @return void
|
||||
*/
|
||||
public function register_notices() {
|
||||
if ( current_user_can( 'activate_plugins' ) && current_user_can( 'edit_plugins' ) && current_user_can( 'install_plugins' ) ) {
|
||||
|
||||
if ( is_multisite() ) {
|
||||
add_action( 'network_admin_notices', [ $this, 'show_notice' ] );
|
||||
|
||||
if ( ! empty( $this->plugin_basename ) && in_array( $this->plugin_basename, (array) get_option( 'active_plugins', [] ) ) ) {
|
||||
add_action( 'admin_notices', [ $this, 'show_notice' ] );
|
||||
}
|
||||
} else {
|
||||
add_action( 'admin_notices', [ $this, 'show_notice' ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the incompatibility notification.
|
||||
*
|
||||
* @since 4.1.1
|
||||
* @return void
|
||||
*/
|
||||
public function show_notice() {
|
||||
if ( $this->check() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<div class="notice notice-error"><p>' . wp_kses( $this->get_notice_text(), 'default' ) . '</p></div>';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The method checks the compatibility of the plugin with php and WordPress version.
|
||||
*
|
||||
* @since 4.1.1
|
||||
* @return bool
|
||||
*/
|
||||
public function check() {
|
||||
|
||||
// Fix for ithemes sync. When the ithemes sync plugin accepts the request, set the WP_ADMIN constant,
|
||||
// Solution to simply terminate the plugin if there is a request from ithemes sync
|
||||
// --------------------------------------
|
||||
if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'ithemes_sync_request' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isset( $_GET['ithemes-sync-request'] ) && ! empty( $_GET['ithemes-sync-request'] ) ) {
|
||||
return false;
|
||||
}
|
||||
// ----------------------------------------
|
||||
|
||||
if ( ! $this->check_php_compat() || ! $this->check_wp_compat() || $this->plugin_already_activate ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The method checks the compatibility of the plugin with the php version of the server.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function check_php_compat() {
|
||||
return version_compare( PHP_VERSION, $this->required_php_version, '>=' );
|
||||
}
|
||||
|
||||
/**
|
||||
* The method checks the compatibility of the plugin with the WordPress version of the site.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function check_wp_compat() {
|
||||
// Get the WP Version global.
|
||||
global $wp_version;
|
||||
|
||||
return version_compare( $wp_version, $this->required_wp_version, '>=' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Method returns notification text
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_notice_text() {
|
||||
$notice_text = $notice_default_text = '';
|
||||
$notice_default_text .= '<b>' . $this->plugin_title . ' ' . __( 'warning', 'robin-image-optimizer' ) . ':</b>' . '<br>';
|
||||
|
||||
// translators: %s is the plugin title
|
||||
$notice_default_text .= sprintf( __( 'The %s plugin has stopped.', 'robin-image-optimizer' ), $this->plugin_title ) . ' ';
|
||||
$notice_default_text .= __( 'Possible reasons:', 'robin-image-optimizer' ) . ' <br>';
|
||||
|
||||
$has_one = false;
|
||||
|
||||
if ( ! $this->check_php_compat() ) {
|
||||
$has_one = true;
|
||||
$notice_text .= '- ' . $this->get_php_incompat_text() . '<br>';
|
||||
}
|
||||
|
||||
if ( ! $this->check_wp_compat() ) {
|
||||
$has_one = true;
|
||||
$notice_text .= '- ' . $this->get_wp_incompat_text() . '<br>';
|
||||
}
|
||||
|
||||
if ( $this->plugin_already_activate ) {
|
||||
$has_one = true;
|
||||
$notice_text = '- ' . $this->get_plugin_already_activate_text() . '<br>';
|
||||
}
|
||||
|
||||
if ( $has_one ) {
|
||||
$notice_text = $notice_default_text . $notice_text;
|
||||
}
|
||||
|
||||
return $notice_text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function get_php_incompat_text() {
|
||||
// translators: %s is the required php version
|
||||
return sprintf( __( 'You need to update the PHP version to %s or higher!', 'robin-image-optimizer' ), $this->required_php_version );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function get_wp_incompat_text() {
|
||||
// translators: %s is the required WordPress version
|
||||
return sprintf( __( 'You need to update WordPress to %s or higher!', 'robin-image-optimizer' ), $this->required_wp_version );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function get_plugin_already_activate_text() {
|
||||
// translators: %s is the plugin title
|
||||
return sprintf( __( 'Plugin %s is already activated, you are trying to activate it again.', 'robin-image-optimizer' ), $this->plugin_title );
|
||||
}
|
||||
}
|
||||
}
|
||||
// @formatter:on
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Components;
|
||||
|
||||
/**
|
||||
* This file groups the settings for quick setup
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'class-install-component-button.php';
|
||||
|
||||
class Delete_Button extends Install_Button {
|
||||
|
||||
public $plugin;
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function build_wordpress() {
|
||||
parent::build_wordpress();
|
||||
|
||||
$this->action = 'delete';
|
||||
$this->add_data( 'plugin-action', $this->action );
|
||||
$this->remove_class( 'button-primary' );
|
||||
}
|
||||
|
||||
protected function build_internal() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $echo
|
||||
*
|
||||
* @return string|void
|
||||
*/
|
||||
public function get_button() {
|
||||
$button = '<a href="#" class="' . implode( ' ', $this->get_classes() ) . '" ' . implode( ' ', $this->get_data() ) . '><span class="dashicons dashicons-trash"></span></a>';
|
||||
|
||||
if ( $this->type == 'internal' || ! $this->is_plugin_install() || $this->is_plugin_activate() ) {
|
||||
$button = '';
|
||||
}
|
||||
|
||||
return $button;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Components;
|
||||
|
||||
/**
|
||||
* This file groups the settings for quick setup
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class Install_Button {
|
||||
|
||||
public $plugin;
|
||||
protected $type;
|
||||
protected $plugin_slug;
|
||||
|
||||
protected $classes = [
|
||||
'button',
|
||||
'wfactory-600-process-button',
|
||||
];
|
||||
protected $data = [];
|
||||
protected $base_path;
|
||||
|
||||
protected $action;
|
||||
|
||||
protected $url;
|
||||
|
||||
/**
|
||||
* @param string $group_name
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function __construct( \Wbcr_Factory600_Plugin $plugin, $type, $plugin_slug ) {
|
||||
if ( empty( $type ) || ! is_string( $plugin_slug ) ) {
|
||||
throw new \Exception( 'Empty type or plugin_slug attribute.' );
|
||||
}
|
||||
|
||||
$this->plugin = $plugin;
|
||||
$this->type = $type;
|
||||
$this->plugin_slug = $plugin_slug;
|
||||
|
||||
if ( $this->type == 'WordPress' || $this->type == 'creativemotion' ) {
|
||||
if ( strpos( rtrim( trim( $this->plugin_slug ) ), '/' ) !== false ) {
|
||||
$this->base_path = $this->plugin_slug;
|
||||
$base_path_parts = explode( '/', $this->base_path );
|
||||
if ( sizeof( $base_path_parts ) === 2 ) {
|
||||
$this->plugin_slug = $base_path_parts[0];
|
||||
}
|
||||
} else {
|
||||
$this->base_path = $this->get_plugin_base_path_by_slug( $this->plugin_slug );
|
||||
}
|
||||
|
||||
$this->build_wordpress();
|
||||
} elseif ( $this->type == 'internal' ) {
|
||||
$this->build_internal();
|
||||
} else {
|
||||
throw new \Exception( 'Invalid button type.' );
|
||||
}
|
||||
|
||||
// Set default data
|
||||
$this->add_data( 'storage', $this->type );
|
||||
$this->add_data( 'i18n', \WBCR\Factory_Templates_759\Helpers::getEscapeJson( $this->get_i18n() ) );
|
||||
$this->add_data( 'wpnonce', wp_create_nonce( 'updates' ) );
|
||||
}
|
||||
|
||||
// Удалить, через несколько версий!
|
||||
// Добавлено в 4.3.3
|
||||
// --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* todo: для совместимости со старыми плагинами
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function getLink() {
|
||||
return $this->get_link();
|
||||
}
|
||||
|
||||
/**
|
||||
* todo: для совместимости со старыми плагинами
|
||||
*
|
||||
* @return string
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function getButton() {
|
||||
return $this->get_button();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an install a link
|
||||
* todo: для совместимости со старыми плагинами
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function renderLink() {
|
||||
echo esc_html( $this->get_link() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an install button
|
||||
* todo: для совместимости со старыми плагинами
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function renderButton() {
|
||||
$this->render_button();
|
||||
}
|
||||
|
||||
/**
|
||||
* todo: для совместимости со старыми плагинами
|
||||
*
|
||||
* @param $class
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function addClass( $class ) {
|
||||
$this->add_class( $class );
|
||||
}
|
||||
|
||||
/**
|
||||
* todo: для совместимости со старыми плагинами
|
||||
*
|
||||
* @param $class
|
||||
*
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function removeClass( $class ) {
|
||||
return $this->remove_class( $class );
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function is_plugin_activate() {
|
||||
if ( ( $this->type == 'WordPress' || $this->type == 'creativemotion' ) && $this->is_plugin_install() ) {
|
||||
require_once ABSPATH . '/wp-admin/includes/plugin.php';
|
||||
|
||||
return is_plugin_active( $this->base_path );
|
||||
} elseif ( $this->type == 'internal' ) {
|
||||
$preinsatall_components = $this->plugin->getPopulateOption( 'deactive_preinstall_components', [] );
|
||||
|
||||
return ! in_array( $this->plugin_slug, $preinsatall_components );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function is_plugin_install() {
|
||||
if ( $this->type == 'WordPress' || $this->type == 'creativemotion' ) {
|
||||
if ( empty( $this->base_path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the function get_plugins() is registered. It is necessary for the front-end
|
||||
// usually get_plugins() only works in the admin panel.
|
||||
if ( ! function_exists( 'get_plugins' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
$plugins = get_plugins();
|
||||
|
||||
if ( isset( $plugins[ $this->base_path ] ) ) {
|
||||
return true;
|
||||
}
|
||||
} elseif ( $this->type == 'internal' ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function add_class( $class ) {
|
||||
if ( ! is_string( $class ) ) {
|
||||
throw new \Exception( 'Attribute class must be a string.' );
|
||||
}
|
||||
$this->classes[] = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
*
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function remove_class( $class ) {
|
||||
if ( ! is_string( $class ) ) {
|
||||
throw new \Exception( 'Attribute class must be a string.' );
|
||||
}
|
||||
$key = array_search( $class, $this->classes );
|
||||
if ( isset( $this->classes[ $key ] ) ) {
|
||||
unset( $this->classes[ $key ] );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function add_data( $name, $value ) {
|
||||
if ( ! is_string( $name ) || ! is_string( $value ) ) {
|
||||
throw new \Exception( 'Attributes name and value must be a string.' );
|
||||
}
|
||||
|
||||
$this->data[ $name ] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function remove_data( $name ) {
|
||||
if ( ! is_string( $name ) ) {
|
||||
throw new \Exception( 'Attribute name must be a string.' );
|
||||
}
|
||||
|
||||
if ( isset( $this->data[ $name ] ) ) {
|
||||
unset( $this->data[ $name ] );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an install button
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function render_button() {
|
||||
echo $this->get_button();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function get_button() {
|
||||
$i18n = $this->get_i18n();
|
||||
|
||||
$button = '<a href="#" class="' . implode( ' ', $this->get_classes() ) . '" ' . implode( ' ', $this->get_data() ) . '>' . $i18n[ $this->action ] . '</a>';
|
||||
|
||||
return $button;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function get_link() {
|
||||
$this->remove_class( 'button' );
|
||||
$this->remove_class( 'button-default' );
|
||||
$this->remove_class( 'button-primary' );
|
||||
|
||||
// $this->add_class('link');
|
||||
$this->add_class( 'button-link' );
|
||||
|
||||
return $this->get_button();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an install a link
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public function render_link() {
|
||||
echo $this->get_link();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @since 4.3.3
|
||||
*/
|
||||
protected function get_data() {
|
||||
$data_to_print = [];
|
||||
|
||||
foreach ( (array) $this->data as $key => $value ) {
|
||||
$data_to_print[ $key ] = 'data-' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
|
||||
}
|
||||
|
||||
return $data_to_print;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @since 4.3.3
|
||||
*/
|
||||
protected function get_classes() {
|
||||
return array_map( 'esc_attr', $this->classes );
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
protected function build_wordpress() {
|
||||
if ( ( 'WordPress' === $this->type || 'creativemotion' === $this->type ) && ! empty( $this->base_path ) ) {
|
||||
|
||||
$this->action = 'install';
|
||||
|
||||
if ( $this->is_plugin_install() ) {
|
||||
$this->action = 'deactivate';
|
||||
if ( ! $this->is_plugin_activate() ) {
|
||||
$this->action = 'activate';
|
||||
}
|
||||
}
|
||||
|
||||
$this->add_data( 'plugin-action', $this->action );
|
||||
$this->add_data( 'slug', $this->plugin_slug );
|
||||
$this->add_data( 'plugin', $this->base_path );
|
||||
|
||||
if ( $this->action == 'activate' ) {
|
||||
$this->add_class( 'button-primary' );
|
||||
} else {
|
||||
$this->add_class( 'button-default' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configurate button of internal components
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.3.3
|
||||
*/
|
||||
protected function build_internal() {
|
||||
if ( $this->type != 'internal' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->action = 'activate';
|
||||
|
||||
if ( $this->is_plugin_activate() ) {
|
||||
$this->action = 'deactivate';
|
||||
}
|
||||
|
||||
$this->add_data( 'plugin-action', $this->action );
|
||||
$this->add_data( 'plugin', $this->plugin_slug );
|
||||
|
||||
if ( $this->action == 'activate' ) {
|
||||
$this->add_class( 'button-primary' );
|
||||
} else {
|
||||
$this->add_class( 'button-default' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internalization for action buttons
|
||||
*
|
||||
* @return array
|
||||
* @since 4.3.3
|
||||
*/
|
||||
protected function get_i18n() {
|
||||
return [
|
||||
'activate' => __( 'Activate', 'robin-image-optimizer' ),
|
||||
'install' => __( 'Install', 'robin-image-optimizer' ),
|
||||
'deactivate' => __( 'Deactivate', 'robin-image-optimizer' ),
|
||||
'delete' => __( 'Delete', 'robin-image-optimizer' ),
|
||||
'loading' => __( 'Please wait...', 'robin-image-optimizer' ),
|
||||
'preparation' => __( 'Preparation...', 'robin-image-optimizer' ),
|
||||
'read' => __( 'Read more', 'robin-image-optimizer' ),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allows you to get the base path to the plugin in the directory wp-content/plugins/
|
||||
*
|
||||
* @param $slug - slug for example "clearfy", "hide-login-page"
|
||||
*
|
||||
* @return int|null|string - "clearfy/clearfy.php"
|
||||
*/
|
||||
protected function get_plugin_base_path_by_slug( $slug ) {
|
||||
// Check if the function get_plugins() is registered. It is necessary for the front-end
|
||||
// usually get_plugins() only works in the admin panel.
|
||||
if ( ! function_exists( 'get_plugins' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
$plugins = get_plugins();
|
||||
|
||||
foreach ( $plugins as $base_path => $plugin ) {
|
||||
if ( strpos( $base_path, rtrim( trim( $slug ) ) ) !== false ) {
|
||||
return $base_path;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Entities;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* @since 4.1.1
|
||||
*/
|
||||
|
||||
class Paths {
|
||||
|
||||
public $absolute;
|
||||
public $main_file;
|
||||
public $relative;
|
||||
public $url;
|
||||
public $basename;
|
||||
public $migrations;
|
||||
|
||||
protected $plugin_path;
|
||||
|
||||
public function __construct( $plugin_file ) {
|
||||
$this->plugin_path = $plugin_file;
|
||||
|
||||
$this->main_file = $plugin_file;
|
||||
$this->absolute = dirname( $plugin_file );
|
||||
$this->basename = plugin_basename( $plugin_file );
|
||||
$this->url = plugins_url( '', $plugin_file );
|
||||
$this->migrations = $this->absolute . '/migrations';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Entities;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* @since 4.1.1
|
||||
*/
|
||||
|
||||
class Support {
|
||||
|
||||
protected $plugin_name;
|
||||
protected $site_url;
|
||||
|
||||
protected $features_page_slug = 'premium-features';
|
||||
protected $pricing_page_slug = 'pricing';
|
||||
protected $support_page_slug = 'support';
|
||||
protected $docs_page_slug = 'docs';
|
||||
|
||||
/**
|
||||
* Plugin_Site constructor.
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function __construct( array $data ) {
|
||||
$this->site_url = isset( $data['url'] ) ? $data['url'] : null;
|
||||
|
||||
if ( isset( $data['pages_map'] ) && is_array( $data['pages_map'] ) ) {
|
||||
foreach ( $data['pages_map'] as $key => $def_value ) {
|
||||
$attr = $key . '_page_slug';
|
||||
$this->{$attr} = isset( $data[ $key ] ) ? $data[ $key ] : $def_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_site_url( $track = false, $utm_content = null ) {
|
||||
if ( $track ) {
|
||||
return $this->get_tracking_page_url( $this->site_url, $utm_content );
|
||||
}
|
||||
|
||||
return $this->site_url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_features_url( $track = false, $utm_content = null ) {
|
||||
if ( $track ) {
|
||||
return $this->get_tracking_page_url( $this->features_page_slug, $utm_content );
|
||||
}
|
||||
|
||||
return $this->get_site_url() . '/' . $this->features_page_slug;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_pricing_url( $track = false, $utm_content = null ) {
|
||||
if ( $track ) {
|
||||
return $this->get_tracking_page_url( $this->pricing_page_slug, $utm_content );
|
||||
}
|
||||
|
||||
return $this->get_site_url() . '/' . $this->pricing_page_slug;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_contacts_url( $track = false, $utm_content = null ) {
|
||||
if ( $track ) {
|
||||
return $this->get_tracking_page_url( $this->support_page_slug, $utm_content );
|
||||
}
|
||||
|
||||
return $this->get_site_url() . '/' . $this->support_page_slug;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_docs_url( $track = false, $utm_content = null ) {
|
||||
if ( $track ) {
|
||||
return $this->get_tracking_page_url( $this->docs_page_slug, $utm_content );
|
||||
}
|
||||
|
||||
return $this->get_site_url() . '/' . $this->docs_page_slug;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate URL with UTM parameters.
|
||||
*
|
||||
* @param string|null $page The page slug.
|
||||
* @param string $utm_content The UTM content parameter.
|
||||
* @param string $utm_source The UTM source parameter.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_tracking_page_url( $page = null, $utm_content = '', $utm_source = 'wordpress.org' ) {
|
||||
$url = $this->get_site_url();
|
||||
if ( $page ) {
|
||||
$url .= '/' . $page . '/';
|
||||
}
|
||||
|
||||
return tsdk_utmify( $url, $utm_content, $utm_source );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
/**
|
||||
* Factory Function Library
|
||||
*
|
||||
* @package factory-core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'get_user_locale' ) ) {
|
||||
function get_user_locale( $user_id = 0 ) {
|
||||
$user = false;
|
||||
if ( 0 === $user_id && function_exists( 'wp_get_current_user' ) ) {
|
||||
$user = wp_get_current_user();
|
||||
} elseif ( $user_id instanceof WP_User ) {
|
||||
$user = $user_id;
|
||||
} elseif ( $user_id && is_numeric( $user_id ) ) {
|
||||
$user = get_user_by( 'id', $user_id );
|
||||
}
|
||||
|
||||
if ( ! $user ) {
|
||||
return get_locale();
|
||||
}
|
||||
|
||||
$locale = $user->locale;
|
||||
|
||||
return $locale ? $locale : get_locale();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires functions attached to a deprecated filter hook.
|
||||
*
|
||||
* When a filter hook is deprecated, the apply_filters() call is replaced with
|
||||
* apply_filters_deprecated(), which triggers a deprecation notice and then fires
|
||||
* the original filter hook.
|
||||
*
|
||||
* This is a copy of `apply_filters_deprecated` introduced in WP 4.6.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param string $tag The name of the filter hook.
|
||||
* @param array $args Array of additional function arguments to be passed to apply_filters().
|
||||
* @param string $version The version of BP Block Users that deprecated the hook.
|
||||
* @param string $replacement Optional. The hook that should have been used.
|
||||
* @param string $message Optional. A message regarding the change.
|
||||
*
|
||||
* @return mixed
|
||||
* @see wbcr_factory_600_deprecated_hook()
|
||||
*/
|
||||
function wbcr_factory_600_apply_filters_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
|
||||
if ( function_exists( 'apply_filters_deprecated' ) ) {
|
||||
return apply_filters_deprecated( $tag, $args, $version, $replacement, $message );
|
||||
}
|
||||
if ( ! has_filter( $tag ) ) {
|
||||
return $args[0];
|
||||
}
|
||||
wbcr_factory_600_deprecated_hook( $tag, $version, $replacement, $message );
|
||||
|
||||
return apply_filters_ref_array( $tag, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires functions attached to a deprecated action hook.
|
||||
*
|
||||
* When an action hook is deprecated, the do_action() call is replaced with
|
||||
* do_action_deprecated(), which triggers a deprecation notice and then fires
|
||||
* the original hook.
|
||||
*
|
||||
* This is a copy of `do_action_deprecated` introduced in WP 4.6.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param string $tag The name of the action hook.
|
||||
* @param array $args Array of additional function arguments to be passed to do_action().
|
||||
* @param string $version The version of BP Block Users that deprecated the hook.
|
||||
* @param string $replacement Optional. The hook that should have been used.
|
||||
* @param string $message Optional. A message regarding the change.
|
||||
*
|
||||
* @return void
|
||||
* @see _deprecated_hook()
|
||||
*/
|
||||
function wbcr_factory_600_do_action_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
|
||||
if ( function_exists( 'do_action_deprecated' ) ) {
|
||||
do_action_deprecated( $tag, $args, $version, $replacement, $message );
|
||||
|
||||
return;
|
||||
}
|
||||
if ( ! has_action( $tag ) ) {
|
||||
return;
|
||||
}
|
||||
wbcr_factory_600_deprecated_hook( $tag, $version, $replacement, $message );
|
||||
do_action_ref_array( $tag, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a deprecated action or filter hook as deprecated and throws a notice.
|
||||
*
|
||||
* Use the 'wbcr_factory_600_deprecated_hook_run' action to get the backtrace describing where the
|
||||
* deprecated hook was called.
|
||||
*
|
||||
* Default behavior is to trigger a user error if WP_DEBUG is true.
|
||||
*
|
||||
* This function is called by the do_action_deprecated() and apply_filters_deprecated()
|
||||
* functions, and so generally does not need to be called directly.
|
||||
*
|
||||
* This is a copy of `_deprecated_hook` introduced in WP 4.6.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
*
|
||||
* @param string $hook The hook that was used.
|
||||
* @param string $version The version of WordPress that deprecated the hook.
|
||||
* @param string $replacement Optional. The hook that should have been used.
|
||||
* @param string $message Optional. A message regarding the change.
|
||||
*/
|
||||
function wbcr_factory_600_deprecated_hook( $hook, $version, $replacement = null, $message = null ) {
|
||||
/**
|
||||
* Fires when a deprecated hook is called.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param string $hook The hook that was called.
|
||||
* @param string $replacement The hook that should be used as a replacement.
|
||||
* @param string $version The version of BP Block Users that deprecated the argument used.
|
||||
* @param string $message A message regarding the change.
|
||||
*/
|
||||
do_action( 'deprecated_hook_run', $hook, $replacement, $version, $message );
|
||||
|
||||
/**
|
||||
* Filter whether to trigger deprecated hook errors.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param bool $trigger Whether to trigger deprecated hook errors. Requires
|
||||
* `WP_DEBUG` to be defined true.
|
||||
*/
|
||||
if ( WP_DEBUG && apply_filters( 'deprecated_hook_trigger_error', true ) ) {
|
||||
$message = empty( $message ) ? '' : ' ' . $message;
|
||||
if ( ! is_null( $replacement ) ) {
|
||||
// translators: %1$s is the hook name, %2$s is the version, %3$s is the replacement hook
|
||||
trigger_error( sprintf( __( '%1$s is deprecated since version %2$s! Use %3$s instead.', 'robin-image-optimizer' ), $hook, $version, $replacement ) . $message );
|
||||
} else {
|
||||
// translators: %1$s is the hook name, %2$s is the version
|
||||
trigger_error( sprintf( __( '%1$s is deprecated since version %2$s with no alternative available.', 'robin-image-optimizer' ), $hook, $version ) . $message );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( '_sanitize_text_fields' ) ) {
|
||||
function _sanitize_text_fields( $str, $keep_newlines = false ) {
|
||||
$filtered = wp_check_invalid_utf8( $str );
|
||||
|
||||
if ( strpos( $filtered, '<' ) !== false ) {
|
||||
$filtered = wp_pre_kses_less_than( $filtered );
|
||||
// This will strip extra whitespace for us.
|
||||
$filtered = wp_strip_all_tags( $filtered, false );
|
||||
|
||||
// Use html entities in a special case to make sure no later
|
||||
// newline stripping stage could lead to a functional tag
|
||||
$filtered = str_replace( "<\n", "<\n", $filtered );
|
||||
}
|
||||
|
||||
if ( ! $keep_newlines ) {
|
||||
$filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
|
||||
}
|
||||
$filtered = trim( $filtered );
|
||||
|
||||
$found = false;
|
||||
while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
|
||||
$filtered = str_replace( $match[0], '', $filtered );
|
||||
$found = true;
|
||||
}
|
||||
|
||||
if ( $found ) {
|
||||
// Strip out the whitespace that may now exist after removing the octets.
|
||||
$filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'sanitize_textarea_field' ) ) {
|
||||
function sanitize_textarea_field( $str ) {
|
||||
$filtered = _sanitize_text_fields( $str, true );
|
||||
|
||||
/**
|
||||
* Filters a sanitized textarea field string.
|
||||
*
|
||||
* @since 4.7.0
|
||||
*
|
||||
* @param string $filtered The sanitized string.
|
||||
* @param string $str The string prior to being sanitized.
|
||||
*/
|
||||
return apply_filters( 'sanitize_textarea_field', $filtered, $str );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Premium\Interfaces;
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
*/
|
||||
interface License {
|
||||
|
||||
public function get_key();
|
||||
|
||||
public function get_hidden_key();
|
||||
|
||||
public function get_expiration_time( $format = 'time' );
|
||||
|
||||
public function get_sites_quota();
|
||||
|
||||
public function get_count_active_sites();
|
||||
|
||||
public function is_valid();
|
||||
|
||||
public function is_lifetime();
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Premium;
|
||||
|
||||
use Exception;
|
||||
use Wbcr_Factory600_Plugin;
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
class Manager {
|
||||
|
||||
/**
|
||||
* @since 4.1.6
|
||||
* @var array
|
||||
*/
|
||||
public static $providers;
|
||||
|
||||
/**
|
||||
* @var Wbcr_Factory600_Plugin
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* Manager constructor.
|
||||
*
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
* @param array $settings
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin, array $settings ) {
|
||||
$this->plugin = $plugin;
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
* @param array $settings
|
||||
*
|
||||
* @return \WBCR\Factory_Freemius_Rio_600\Premium\Provider
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function instance( Wbcr_Factory600_Plugin $plugin, array $settings ) {
|
||||
$premium_manager = new Manager( $plugin, $settings );
|
||||
|
||||
return $premium_manager->instance_provider();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $provider_name
|
||||
*
|
||||
* @return \WBCR\Factory_Freemius_Rio_600\Premium\Provider
|
||||
* @throws Exception
|
||||
*/
|
||||
public function instance_provider() {
|
||||
$provider_name = $this->get_setting( 'provider' );
|
||||
|
||||
if ( isset( self::$providers[ $provider_name ] ) && class_exists( self::$providers[ $provider_name ] ) ) {
|
||||
if ( self::$providers[ $provider_name ] instanceof Provider ) {
|
||||
throw new Exception( "Provider {$provider_name} must extend the class WBCR\Factory_600\Premium\Provider interface!" );
|
||||
}
|
||||
|
||||
return new self::$providers[ $provider_name ]( $this->plugin, $this->settings );
|
||||
}
|
||||
|
||||
throw new Exception( "Provider {$provider_name} is not supported!" );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function get_setting( $name ) {
|
||||
return isset( $this->settings[ $name ] ) ? $this->settings[ $name ] : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Premium;
|
||||
|
||||
use Exception;
|
||||
use Wbcr_Factory600_Plugin;
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняет проверку обновлений, обновления, скачивание плагинов
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
abstract class Provider {
|
||||
|
||||
/**
|
||||
* @var Wbcr_Factory600_Plugin
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $is_install_package;
|
||||
|
||||
/**
|
||||
* Provider constructor.
|
||||
*
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
* @param array $settings
|
||||
*/
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin, array $settings ) {
|
||||
$this->plugin = $plugin;
|
||||
$this->settings = $settings;
|
||||
|
||||
$this->register_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_settings() {
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param bool $default
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function get_setting( $name, $default = false ) {
|
||||
return isset( $this->settings[ $name ] ) && ! empty( $this->settings[ $name ] ) ? $this->settings[ $name ] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function get_price() {
|
||||
return $this->get_setting( 'price' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_install_package() {
|
||||
if ( ! is_null( $this->is_install_package ) ) {
|
||||
return $this->is_install_package;
|
||||
}
|
||||
|
||||
$premium_plugin_slug = $this->get_setting( 'slug' );
|
||||
$premium_package = $this->get_package_data();
|
||||
|
||||
if ( ! empty( $premium_package ) && ! empty( $premium_package['basename'] ) ) {
|
||||
$basename_part = explode( '/', $premium_package['basename'] );
|
||||
$is_valid_basename = sizeof( $basename_part ) === 2;
|
||||
|
||||
if ( $is_valid_basename && ! file_exists( WP_PLUGIN_DIR . '/' . $premium_package['basename'] ) ) {
|
||||
$this->delete_package();
|
||||
$this->is_install_package = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
} elseif ( $premium_plugin_slug && file_exists( WP_PLUGIN_DIR . '/' . $premium_plugin_slug ) ) {
|
||||
// If plugin is installed before we update the premium package in database.
|
||||
// ------------------------------------------------------------------------
|
||||
$plugins = get_plugins( $plugin_folder = '' );
|
||||
|
||||
if ( ! empty( $plugins ) ) {
|
||||
foreach ( (array) $plugins as $plugin_base => $plugin ) {
|
||||
$basename_parts = explode( '/', $plugin_base );
|
||||
if ( sizeof( $basename_parts ) == 2 && $basename_parts[0] == $premium_plugin_slug ) {
|
||||
|
||||
$plugin_basename = $plugin_base;
|
||||
$plugin_main_file = WP_PLUGIN_DIR . '/' . $plugin_base;
|
||||
|
||||
$default_headers = [
|
||||
'Version' => 'Version',
|
||||
'FrameworkVersion' => 'Framework Version',
|
||||
];
|
||||
|
||||
$plugin_data = get_file_data( $plugin_main_file, $default_headers, 'plugin' );
|
||||
|
||||
$this->update_package_data(
|
||||
[
|
||||
'basename' => $plugin_basename,
|
||||
'version' => $plugin_data['Version'],
|
||||
'framework_version' => isset( $plugin_data['FrameworkVersion'] ) ? $plugin_data['FrameworkVersion'] : null,
|
||||
]
|
||||
);
|
||||
|
||||
$premium_package = $this->get_package_data();
|
||||
|
||||
/**
|
||||
* @param string $plugin_name Имя плагина
|
||||
*
|
||||
* @param string $package Дополнительная информация о лицензии
|
||||
* @since 4.1.1
|
||||
*/
|
||||
do_action( 'wbcr/factory/premium/installed_package', $premium_package, $this->plugin->getPluginName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->is_install_package = ! empty( $premium_package );
|
||||
|
||||
return $this->is_install_package;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed|null
|
||||
*/
|
||||
public function get_package_data() {
|
||||
$premium_package = $this->plugin->getPopulateOption( 'premium_package' );
|
||||
|
||||
if ( ! empty( $premium_package ) ) {
|
||||
return wp_parse_args(
|
||||
$premium_package,
|
||||
[
|
||||
'basename' => null,
|
||||
'version' => null,
|
||||
'framework_version' => null,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $plugin_data
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function update_package_data( array $package ) {
|
||||
$parsed_args = wp_parse_args(
|
||||
$package,
|
||||
[
|
||||
'basename' => null,
|
||||
'version' => null,
|
||||
'framework_version' => null,
|
||||
]
|
||||
);
|
||||
|
||||
if ( empty( $parsed_args['basename'] ) || empty( $parsed_args['version'] ) ) {
|
||||
throw new Exception( 'You must pass the required attributes (basename, version).' );
|
||||
}
|
||||
|
||||
$this->plugin->updatePopulateOption( 'premium_package', $parsed_args );
|
||||
$this->is_install_package = true;
|
||||
}
|
||||
|
||||
public function delete_package() {
|
||||
$this->plugin->deletePopulateOption( 'premium_package' );
|
||||
$this->is_install_package = false;
|
||||
}
|
||||
|
||||
protected function register_hooks() {
|
||||
/**
|
||||
* Добавляет крон задачу на синхронизацию лицензии
|
||||
*
|
||||
* @param array $license_info
|
||||
* @param string $provider
|
||||
*/
|
||||
add_action(
|
||||
"{$this->plugin->getPluginName()}/factory/premium/license_activate",
|
||||
function ( $provider, $license_info ) {
|
||||
if ( ! wp_next_scheduled( "{$this->plugin->getPluginName()}_license_autosync" ) ) {
|
||||
wp_schedule_event( time(), 'twicedaily', "{$this->plugin->getPluginName()}_license_autosync" );
|
||||
}
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
/**
|
||||
* Удаляет крон задачу на синхронизацию лицензии, когда лицензия деактивирована
|
||||
*
|
||||
* @param array $license_info
|
||||
* @param string $provider
|
||||
*/
|
||||
add_action(
|
||||
"{$this->plugin->getPluginName()}/factory/premium/license_deactivate",
|
||||
function ( $provider, $license_info ) {
|
||||
if ( wp_next_scheduled( "{$this->plugin->getPluginName()}_license_autosync" ) ) {
|
||||
wp_clear_scheduled_hook( "{$this->plugin->getPluginName()}_license_autosync" );
|
||||
}
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
/**
|
||||
* Обработчик крон задачи на синхронизацию лицензии, выполняется 2 раза в день.
|
||||
*/
|
||||
add_action(
|
||||
"{$this->plugin->getPluginName()}_license_autosync",
|
||||
function () {
|
||||
$this->sync();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function is_activate();
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function is_active();
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
abstract public function get_plan();
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
abstract public function get_billing_cycle();
|
||||
|
||||
/**
|
||||
* @return \WBCR\Factory_600\Premium\Interfaces\License
|
||||
*/
|
||||
abstract public function get_license();
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
abstract public function get_package_download_url();
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function activate( $key );
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function deactivate();
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function sync();
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function has_paid_subscription();
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function cancel_paid_subscription();
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,814 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Updates;
|
||||
|
||||
use Exception;
|
||||
use Plugin_Installer_Skin;
|
||||
use Plugin_Upgrader;
|
||||
use Wbcr_Factory600_Plugin;
|
||||
use Wbcr_FactoryPages600_ImpressiveThemplate;
|
||||
use WP_Filesystem_Base;
|
||||
use WP_Upgrader;
|
||||
use WP_Upgrader_Skin;
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once ABSPATH . '/wp-admin/includes/list-table.php';
|
||||
/**
|
||||
* @version 1.0
|
||||
*/
|
||||
class Premium_Upgrader extends Upgrader {
|
||||
|
||||
/**
|
||||
* Тип апгрейдера, может быть default, premium
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'premium';
|
||||
|
||||
/**
|
||||
* Объект таблицы со списком плагинов
|
||||
*
|
||||
* @var \WP_Plugins_List_Table
|
||||
*/
|
||||
protected $wp_list_table;
|
||||
|
||||
/**
|
||||
* Manager constructor.
|
||||
*
|
||||
* @param $args
|
||||
* @param bool $is_premium
|
||||
*
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
*
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin ) {
|
||||
parent::__construct( $plugin );
|
||||
|
||||
$this->plugin_basename = null;
|
||||
$this->plugin_main_file = null;
|
||||
$this->plugin_absolute_path = null;
|
||||
|
||||
if ( $this->plugin->premium->is_activate() && $this->plugin->premium->is_install_package() ) {
|
||||
$premium_package = $this->plugin->premium->get_package_data();
|
||||
|
||||
if ( $premium_package ) {
|
||||
$this->plugin_basename = $premium_package['basename'];
|
||||
$this->plugin_main_file = WP_PLUGIN_DIR . '/' . $premium_package['basename'];
|
||||
$this->plugin_absolute_path = dirname( WP_PLUGIN_DIR . '/' . $premium_package['basename'] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $this->repository->is_support_premium() ) {
|
||||
$settings = $this->get_settings();
|
||||
throw new Exception( "Repository {$settings['repository']} does not have support premium." );
|
||||
}
|
||||
|
||||
$this->init_premium_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function set_repository() {
|
||||
$settings = $this->get_settings();
|
||||
$this->repository = $this->get_repository( $settings['repository'] );
|
||||
|
||||
if ( $this->plugin->premium->is_activate() ) {
|
||||
$this->repository->init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function init_premium_hooks() {
|
||||
// parent::init_hooks();
|
||||
|
||||
if ( $this->need_intall_or_activate_premium() || $this->need_renew_license() || $this->need_activate_license() ) {
|
||||
// Показываем уведомление под бесплатным плагином, если требуется установить или активировать премиум пакет
|
||||
if ( $this->need_intall_or_activate_premium() ) {
|
||||
$free_plugin_base = $this->plugin->get_paths()->basename;
|
||||
|
||||
add_action( "after_plugin_row_{$free_plugin_base}", [ $this, 'notice_in_plugin_row' ], 100, 3 );
|
||||
}
|
||||
|
||||
// Если установлен премиум пакет, то показываем уведомление под премиум плагином.
|
||||
if ( ( $this->need_renew_license() || $this->need_activate_license() ) && $this->plugin->premium->is_install_package() ) {
|
||||
$package = $this->plugin->premium->get_package_data();
|
||||
$premium_plugin_base = $package['basename'];
|
||||
|
||||
add_action( "after_plugin_row_{$premium_plugin_base}", [ $this, 'notice_in_plugin_row' ], 100, 3 );
|
||||
}
|
||||
|
||||
add_action( 'admin_print_styles-plugins.php', [ $this, 'print_styles_for_plugin_row' ] );
|
||||
add_action( 'wbcr/factory/admin_notices', [ $this, 'admin_notices_hook' ], 10, 2 );
|
||||
add_action(
|
||||
'wbcr/factory/pages/impressive/print_all_notices',
|
||||
[
|
||||
$this,
|
||||
'install_notice_in_plugin_interface',
|
||||
],
|
||||
10,
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
add_action( 'admin_init', [ $this, 'init_admin_actions' ] );
|
||||
|
||||
add_action( 'deleted_plugin', [ $this, 'delete_plugin_hook' ], 10, 2 );
|
||||
add_action( 'upgrader_process_complete', [ $this, 'upgrader_process_complete_hook' ], 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.2.2 Fixed bug with plugins namespace (ISW-4)
|
||||
* @since 4.1.1
|
||||
*/
|
||||
public function init_admin_actions() {
|
||||
$plugin_slug = $this->plugin->request->get( 'wfactory_premium_updates_plugin', null );
|
||||
|
||||
if ( isset( $_GET['wfactory_premium_updates_action'] ) && $this->plugin_slug === $plugin_slug ) {
|
||||
$action = $this->plugin->request->get( 'wfactory_premium_updates_action' );
|
||||
|
||||
check_admin_referer( "factory_premium_{$action}" );
|
||||
try {
|
||||
switch ( $action ) {
|
||||
case 'install':
|
||||
$this->install();
|
||||
break;
|
||||
case 'deactivate':
|
||||
$this->deactivate();
|
||||
break;
|
||||
case 'delete':
|
||||
$this->delete();
|
||||
break;
|
||||
case 'check_updates':
|
||||
$this->check_updates();
|
||||
break;
|
||||
case 'cancel_license':
|
||||
$this->plugin->premium->deactivate();
|
||||
|
||||
break;
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
wp_die( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет данные о пакете, если пользовать удалил премиум плагин
|
||||
*
|
||||
* @param $success
|
||||
*
|
||||
* @param $plugin_basename
|
||||
* @since 4.1.1
|
||||
*/
|
||||
public function delete_plugin_hook( $plugin_basename, $success ) {
|
||||
if ( ! $this->plugin->premium->is_install_package() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$package = $this->plugin->premium->get_package_data();
|
||||
|
||||
if ( $package['basename'] == $plugin_basename && $success ) {
|
||||
$this->plugin->premium->delete_package();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Выводит уведомление на всех страницах админ панели WordPress
|
||||
*
|
||||
* @param $notices
|
||||
*
|
||||
* @return array
|
||||
* @since 4.1.1
|
||||
*/
|
||||
public function admin_notices_hook( $notices, $plugin_name ) {
|
||||
|
||||
if ( $plugin_name !== $this->plugin->getPluginName() || ! current_user_can( 'update_plugins' ) ) {
|
||||
return $notices;
|
||||
}
|
||||
|
||||
if ( $this->need_intall_or_activate_premium() ) {
|
||||
$notice_text = $this->get_notice_text( 'please_activate_premium' );
|
||||
|
||||
if ( ! $this->plugin->premium->is_install_package() ) {
|
||||
$notice_text = $this->get_notice_text( 'please_install_premium' );
|
||||
}
|
||||
|
||||
$notices[] = [
|
||||
'id' => 'please_install_premium_for_' . $this->plugin->getPluginName(),
|
||||
'type' => 'warning',
|
||||
'dismissible' => false,
|
||||
'dismiss_expires' => 0,
|
||||
'text' => "<p><b>{$this->plugin->getPluginTitle()}:</b> " . $notice_text . '</p>',
|
||||
];
|
||||
} elseif ( $this->need_activate_license() ) {
|
||||
$notices[] = [
|
||||
'id' => 'need_activate_premium_for_' . $this->plugin->getPluginName(),
|
||||
'type' => 'warning',
|
||||
'dismissible' => false,
|
||||
'dismiss_expires' => 0,
|
||||
'text' => "<p><b>{$this->plugin->getPluginTitle()}:</b> " . $this->get_notice_text( 'need_activate_license' ) . '</p>',
|
||||
];
|
||||
} elseif ( $this->need_renew_license() ) {
|
||||
// todo: может быть перенести уведомление в премиум менеджер?
|
||||
$notices[] = [
|
||||
'id' => 'license_exired_for_' . $this->plugin->getPluginName(),
|
||||
'type' => 'warning',
|
||||
'dismissible' => false,
|
||||
'dismiss_expires' => 0,
|
||||
'text' => "<p><b>{$this->plugin->getPluginTitle()}:</b> " . $this->get_notice_text( 'need_renew_license' ) . '</p>',
|
||||
];
|
||||
}
|
||||
|
||||
return $notices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Выводит уведомление внутри интерфейса плагина, на всех страницах плагина.
|
||||
*
|
||||
* @param Wbcr_FactoryPages600_ImpressiveThemplate $obj
|
||||
*
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
*
|
||||
* @return void
|
||||
* @since 4.1.1
|
||||
*/
|
||||
public function install_notice_in_plugin_interface( $plugin, $obj ) {
|
||||
if ( $plugin->getPluginName() != $this->plugin->getPluginName() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$notice_text = '';
|
||||
|
||||
if ( $this->need_intall_or_activate_premium() ) {
|
||||
$notice_text = $this->get_notice_text( 'please_activate_premium' );
|
||||
|
||||
if ( ! $this->plugin->premium->is_install_package() ) {
|
||||
$notice_text = $this->get_notice_text( 'please_install_premium' );
|
||||
}
|
||||
} elseif ( $this->need_activate_license() ) {
|
||||
$notice_text = $this->get_notice_text( 'need_activate_license' );
|
||||
} elseif ( $this->need_renew_license() ) {
|
||||
$notice_text = $this->get_notice_text( 'need_renew_license' );
|
||||
}
|
||||
|
||||
$obj->printWarningNotice( $notice_text );
|
||||
}
|
||||
|
||||
/**
|
||||
* Выводит уведомление в строке плагина (на странице плагинов),
|
||||
* что нужно установить премиум плагин.
|
||||
*
|
||||
* @param array $plugin_data
|
||||
* @param string $status
|
||||
*
|
||||
* @param string $plugin_file
|
||||
*
|
||||
* @return void
|
||||
* @since 4.1.1
|
||||
*
|
||||
* @see WP_Plugins_List_Table
|
||||
*/
|
||||
public function notice_in_plugin_row( $plugin_file, $plugin_data, $status ) {
|
||||
|
||||
if ( ! current_user_can( 'update_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$notice_text = '';
|
||||
|
||||
if ( $this->need_intall_or_activate_premium() ) {
|
||||
$notice_text = $this->get_notice_text( 'please_activate_premium' );
|
||||
|
||||
if ( ! $this->plugin->premium->is_install_package() ) {
|
||||
$notice_text = $this->get_notice_text( 'please_install_premium' );
|
||||
}
|
||||
} elseif ( $this->need_activate_license() ) {
|
||||
$notice_text = $this->get_notice_text( 'need_activate_license' );
|
||||
} elseif ( $this->need_renew_license() ) {
|
||||
$notice_text = $this->get_notice_text( 'need_renew_license' );
|
||||
}
|
||||
|
||||
if ( ! $this->wp_list_table ) {
|
||||
$this->wp_list_table = \_get_list_table(
|
||||
'WP_Plugins_List_Table',
|
||||
[
|
||||
'screen' => null,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
?>
|
||||
<tr class="plugin-update-tr active update wbcr-factory-updates">
|
||||
<td colspan="<?php echo esc_attr( $this->wp_list_table->get_column_count() ); ?>" class="plugin-update colspanchange">
|
||||
<div class="update-message notice inline notice-warning notice-alt">
|
||||
<p>
|
||||
<?php echo $notice_text; ?>
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Печатает стили для уведомления о загрузке премиум версии на странице плагинов.
|
||||
*
|
||||
* @return void
|
||||
* @since 4.1.1
|
||||
*/
|
||||
public function print_styles_for_plugin_row() {
|
||||
|
||||
if ( ! current_user_can( 'update_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$plugin_base = $this->plugin->get_paths()->basename;
|
||||
|
||||
if ( $this->need_intall_or_activate_premium() ) {
|
||||
$message_background_color = '#f5e9f5';
|
||||
$message_border_color = '#dab9da';
|
||||
} elseif ( $this->need_renew_license() || $this->need_activate_license() ) {
|
||||
$message_background_color = '#ffe2e0';
|
||||
$message_border_color = '#F44336';
|
||||
if ( $this->plugin->premium->is_install_package() ) {
|
||||
$package = $this->plugin->premium->get_package_data();
|
||||
$plugin_base = $package['basename'];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<style>
|
||||
tr[data-plugin="<?php echo $plugin_base; ?>"] th,
|
||||
tr[data-plugin="<?php echo $plugin_base; ?>"] td {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.wbcr-factory-updates .update-message {
|
||||
background-color: <?php echo esc_attr( $message_background_color ); ?> !important;
|
||||
border-color: <?php echo esc_attr( $message_border_color ); ?> !important;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Обновляет данные о премиум пакете в базе данных, после обновления плагина.
|
||||
*
|
||||
* @param WP_Upgrader $wp_upgrader WP_Upgrader instance.
|
||||
* @param array $hook_extra Array of bulk item update data.
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function upgrader_process_complete_hook( $upgrader_object, $hook_extra ) {
|
||||
if ( ! empty( $hook_extra ) && $hook_extra['action'] == 'update' && $hook_extra['type'] == 'plugin' ) {
|
||||
|
||||
// if it isn't bulk upgrade
|
||||
if ( isset( $hook_extra['plugin'] ) && $this->plugin_basename === $hook_extra['plugin'] ) {
|
||||
$this->update_package_data();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if it is bulk upgrade
|
||||
if ( isset( $hook_extra['plugins'] ) && in_array( $this->plugin_basename, $hook_extra['plugins'] ) ) {
|
||||
$this->update_package_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function get_settings() {
|
||||
$settings = $this->plugin->getPluginInfoAttr( 'license_settings' );
|
||||
|
||||
$updates_settings = isset( $settings['updates_settings'] ) ? $settings['updates_settings'] : [];
|
||||
|
||||
if ( is_array( $settings ) ) {
|
||||
$updates_settings['repository'] = $settings['provider'];
|
||||
$updates_settings['slug'] = $settings['slug'];
|
||||
}
|
||||
|
||||
return wp_parse_args(
|
||||
$updates_settings,
|
||||
[
|
||||
'repository' => 'wordpress',
|
||||
'slug' => '',
|
||||
'maybe_rollback' => false,
|
||||
'rollback_settings' => [
|
||||
'prev_stable_version' => '0.0.0',
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function get_plugin_version() {
|
||||
if ( ! $this->plugin->premium->is_install_package() ) {
|
||||
return '0.0.0';
|
||||
}
|
||||
|
||||
$package = $this->plugin->premium->get_package_data();
|
||||
|
||||
return $package['version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $args
|
||||
*
|
||||
* @return string
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function get_admin_url( $args ) {
|
||||
$url = admin_url( 'plugins.php', $args );
|
||||
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
$url = network_admin_url( 'plugins.php', $args );
|
||||
}
|
||||
|
||||
return add_query_arg( $args, $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
*
|
||||
* @return string
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function get_action_url( $action ) {
|
||||
$args = [
|
||||
'wfactory_premium_updates_action' => $action,
|
||||
'wfactory_premium_updates_plugin' => $this->plugin_slug,
|
||||
];
|
||||
|
||||
return wp_nonce_url( $this->get_admin_url( $args ), "factory_premium_{$action}" );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function get_activate_premium_url() {
|
||||
$args = [
|
||||
'action' => 'activate',
|
||||
'plugin' => $this->plugin_basename,
|
||||
];
|
||||
|
||||
return wp_nonce_url( $this->get_admin_url( $args ), "activate-plugin_{$this->plugin_basename}" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Нужно установить или обновить премиум?
|
||||
*
|
||||
* @return bool
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function need_intall_or_activate_premium() {
|
||||
if ( $this->plugin->premium->is_activate() && $this->plugin->premium->is_active() ) {
|
||||
if ( $this->plugin->premium->is_install_package() && is_plugin_active( $this->plugin_basename ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Требуется активировать лицензию?
|
||||
*
|
||||
* @return bool
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function need_activate_license() {
|
||||
return ! $this->plugin->premium->is_activate() && $this->plugin->premium->is_install_package();
|
||||
}
|
||||
|
||||
/**
|
||||
* Нужно продлить лицензию?
|
||||
*
|
||||
* @return bool
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function need_renew_license() {
|
||||
return $this->plugin->premium->is_activate() && ! $this->plugin->premium->is_active();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function install() {
|
||||
global $wp_filesystem;
|
||||
|
||||
if ( ! current_user_can( 'install_plugins' ) ) {
|
||||
throw new Exception( 'Sorry, you are not allowed to install plugins on this site.' );
|
||||
}
|
||||
|
||||
if ( $this->plugin->premium->is_install_package() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $wp_filesystem ) {
|
||||
if ( ! function_exists( 'WP_Filesystem' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
}
|
||||
WP_Filesystem();
|
||||
}
|
||||
|
||||
if ( ! WP_Filesystem( false, WP_PLUGIN_DIR ) ) {
|
||||
throw new Exception( 'You are not allowed to edt folders/files on this site' );
|
||||
} else {
|
||||
|
||||
$download_url = $this->repository->get_download_url();
|
||||
|
||||
/**
|
||||
* @param string $plugin_name Имя плагина
|
||||
*
|
||||
* @param string $package Дополнительная информация о лицензии
|
||||
* @since 4.1.1
|
||||
*/
|
||||
do_action( 'wbcr/factory/premium/install_package', $download_url, $this->plugin->getPluginName() );
|
||||
|
||||
// If plugin is installed before we update the premium package in database.
|
||||
// ------------------------------------------------------------------------
|
||||
// $plugins = get_plugins( $plugin_folder = '' );
|
||||
//
|
||||
// if ( ! empty( $plugins ) ) {
|
||||
// foreach ( (array) $plugins as $plugin_base => $plugin ) {
|
||||
// $basename_parts = explode( '/', $plugin_base );
|
||||
// if ( sizeof( $basename_parts ) == 2 && $basename_parts[0] == $this->plugin_slug ) {
|
||||
//
|
||||
// $this->plugin_basename = $plugin_base;
|
||||
// $this->plugin_main_file = WP_PLUGIN_DIR . '/' . $plugin_base;
|
||||
// $this->plugin_absolute_path = dirname( WP_PLUGIN_DIR . '/' . $plugin_base );
|
||||
//
|
||||
// $this->update_package_data();
|
||||
//
|
||||
// $package = $this->plugin->premium->get_package_data();
|
||||
//
|
||||
// **
|
||||
// * @since 4.1.1
|
||||
// *
|
||||
// * @param string $plugin_name Имя плагина
|
||||
// *
|
||||
// * @param string $package Дополнительная информация о лицензии
|
||||
// */
|
||||
// do_action( 'wbcr/factory/premium/installed_package', $package, $this->plugin->getPluginName() );
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/misc.php';
|
||||
|
||||
if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
|
||||
// Include required resources for the installation.
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
||||
}
|
||||
|
||||
$skin_args = [
|
||||
'type' => 'web',
|
||||
'title' => sprintf( 'Installing plugin: %s', $this->plugin->getPluginTitle() . ' Premium' ),
|
||||
'url' => esc_url_raw( $download_url ),
|
||||
'nonce' => 'install-plugin_' . $this->plugin_slug,
|
||||
'plugin' => '',
|
||||
'api' => null,
|
||||
'extra' => [
|
||||
'slug' => $this->plugin_slug,
|
||||
'freemius' => true,
|
||||
],
|
||||
];
|
||||
|
||||
require_once ABSPATH . 'wp-admin/admin-header.php';
|
||||
|
||||
if ( ! $this->plugin->premium->is_install_package() ) {
|
||||
$skin = new Plugin_Installer_Skin( $skin_args );
|
||||
} else {
|
||||
$skin = new WP_Upgrader_Skin( $skin_args );
|
||||
}
|
||||
|
||||
$upgrader = new Plugin_Upgrader( $skin );
|
||||
|
||||
if ( empty( $download_url ) ) {
|
||||
throw new Exception( 'You must pass the download url to upgrade up premium package.' );
|
||||
}
|
||||
|
||||
$install_result = $upgrader->install( $download_url );
|
||||
|
||||
include ABSPATH . 'wp-admin/admin-footer.php';
|
||||
|
||||
if ( is_wp_error( $install_result ) ) {
|
||||
throw new Exception( $install_result->get_error_message() );
|
||||
} elseif ( is_wp_error( $skin->result ) ) {
|
||||
throw new Exception( $skin->result->get_error_message() );
|
||||
} elseif ( is_null( $install_result ) ) {
|
||||
global $wp_filesystem;
|
||||
|
||||
$error_message = 'Unable to connect to the filesystem. Please confirm your credentials.';
|
||||
|
||||
// Pass through the error from WP_Filesystem if one was raised.
|
||||
if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
|
||||
$error_message = $wp_filesystem->errors->get_error_message();
|
||||
}
|
||||
|
||||
throw new Exception( $error_message );
|
||||
}
|
||||
|
||||
$this->plugin_basename = $upgrader->plugin_info();
|
||||
$this->plugin_main_file = WP_PLUGIN_DIR . '/' . $this->plugin_basename;
|
||||
$this->plugin_absolute_path = dirname( WP_PLUGIN_DIR . '/' . $this->plugin_basename );
|
||||
|
||||
$this->update_package_data();
|
||||
|
||||
$package = $this->plugin->premium->get_package_data();
|
||||
|
||||
/**
|
||||
* @param string $plugin_name Имя плагина
|
||||
*
|
||||
* @param string $package Дополнительная информация о лицензии
|
||||
* @since 4.1.1
|
||||
*/
|
||||
do_action( 'wbcr/factory/premium/installed_package', $package, $this->plugin->getPluginName() );
|
||||
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function delete() {
|
||||
if ( ! $this->plugin->premium->is_install_package() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$package = $this->plugin->premium->get_package_data();
|
||||
|
||||
/**
|
||||
* @param string $plugin_name Имя плагина
|
||||
*
|
||||
* @param string $package Дополнительная информация о лицензии
|
||||
* @since 4.1.1
|
||||
*/
|
||||
do_action( 'wbcr/factory/premium/delete_package', $package, $this->plugin->getPluginName() );
|
||||
|
||||
if ( is_plugin_active( $package['basename'] ) ) {
|
||||
if ( is_multisite() && is_plugin_active_for_network( $package['basename'] ) ) {
|
||||
deactivate_plugins( $package['basename'], false, true );
|
||||
} else {
|
||||
deactivate_plugins( $package['basename'] );
|
||||
}
|
||||
}
|
||||
|
||||
$result = delete_plugins( [ $package['basename'] ] );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
throw new Exception( $result->get_error_message() );
|
||||
}
|
||||
|
||||
$this->plugin->premium->delete_package();
|
||||
|
||||
/**
|
||||
* @param string $plugin_name Имя плагина
|
||||
*
|
||||
* @param string $package Дополнительная информация о лицензии
|
||||
* @since 4.1.1
|
||||
*/
|
||||
do_action( 'wbcr/factory/premium/deleted_package', $package, $this->plugin->getPluginName() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function deactivate() {
|
||||
if ( ! $this->plugin->premium->is_install_package() || ! is_plugin_active( $this->plugin_basename ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$package = $this->plugin->premium->get_package_data();
|
||||
|
||||
/**
|
||||
* @param string $plugin_name Имя плагина
|
||||
*
|
||||
* @param string $package Дополнительная информация о лицензии
|
||||
* @since 4.1.1
|
||||
*/
|
||||
do_action( 'wbcr/factory/premium/deactivate_package', $package, $this->plugin->getPluginName() );
|
||||
|
||||
if ( is_multisite() && is_plugin_active_for_network( $this->plugin_basename ) ) {
|
||||
deactivate_plugins( $this->plugin_basename, false, true );
|
||||
} else {
|
||||
deactivate_plugins( $this->plugin_basename );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $plugin_name Имя плагина
|
||||
*
|
||||
* @param string $package Дополнительная информация о лицензии
|
||||
* @since 4.1.1
|
||||
*/
|
||||
do_action( 'wbcr/factory/premium/deactivated_package', $package, $this->plugin->getPluginName() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $plugin_data
|
||||
*
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function update_package_data() {
|
||||
|
||||
if ( ! $this->plugin_main_file ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$default_headers = [
|
||||
'Version' => 'Version',
|
||||
'FrameworkVersion' => 'Framework Version',
|
||||
];
|
||||
|
||||
$plugin_data = get_file_data( $this->plugin_main_file, $default_headers, 'plugin' );
|
||||
|
||||
$this->plugin->premium->update_package_data(
|
||||
[
|
||||
'basename' => $this->plugin_basename,
|
||||
'version' => $plugin_data['Version'],
|
||||
'framework_version' => isset( $plugin_data['FrameworkVersion'] ) ? $plugin_data['FrameworkVersion'] : null,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return string|null
|
||||
* @since 4.1.1
|
||||
*/
|
||||
private function get_notice_text( $type ) {
|
||||
$upgrade_url = $this->get_action_url( 'install' );
|
||||
$activate_plugin_url = $this->get_activate_premium_url();
|
||||
$cancel_license_url = $this->get_action_url( 'cancel_license' );
|
||||
|
||||
$texts = [
|
||||
'need_activate_license' => __( 'License activation required. A license is required to get premium plugin updates, as well as to get additional services.', 'robin-image-optimizer' ),
|
||||
'need_renew_license' => __( 'Your license has expired. You can no longer get premium plugin updates, premium support and your access to services has been suspended.', 'robin-image-optimizer' ),
|
||||
'please_install_premium' => sprintf(
|
||||
// translators: %1$s is the upgrade URL open tag, %2$s is the upgrade URL close tag, %3$s is the cancel license URL open tag, %4$s is the cancel license URL close tag
|
||||
__( 'Congratulations, you have activated a premium license! Please install premium add-on to use pro features now.%1$sInstall%2$s premium add-on or %3$scancel%4$s license.', 'robin-image-optimizer' ),
|
||||
'<a href="' . esc_url( $upgrade_url ) . '>',
|
||||
'</a>',
|
||||
'<a href="' . esc_url( $cancel_license_url ) . '>',
|
||||
'</a>'
|
||||
),
|
||||
'please_activate_premium' => sprintf(
|
||||
// translators: %1$s is the activate plugin URL open tag, %2$s is the activate plugin URL close tag, %3$s is the cancel license URL open tag, %4$s is the cancel license URL close tag
|
||||
__( 'Congratulations, you have activated a premium license! Please activate premium add-on to use pro features now.%1$sActivate%2$s premium add-on or %3$scancel%4$s license.', 'robin-image-optimizer' ),
|
||||
'<a href="' . esc_url( $activate_plugin_url ) . '">',
|
||||
'</a>',
|
||||
'<a href="' . esc_url( $cancel_license_url ) . '">',
|
||||
'</a>'
|
||||
),
|
||||
];
|
||||
|
||||
if ( isset( $texts[ $type ] ) ) {
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param string $plugin_name
|
||||
*
|
||||
* @param array $messages
|
||||
* @since 4.1.1
|
||||
*/
|
||||
return apply_filters( 'wbcr/factory/premium/notice_text', $texts[ $type ], $type, $this->plugin->getPluginName() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Updates;
|
||||
|
||||
use Exception;
|
||||
use stdClass;
|
||||
use Wbcr_Factory600_Plugin;
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
*/
|
||||
class Upgrader {
|
||||
|
||||
const CHECK_UPDATES_INTERVAL = '43200';
|
||||
|
||||
/**
|
||||
* Список доступных классов для работы с репозиториями
|
||||
*
|
||||
* @since 4.1.7
|
||||
* @var array хранит имя репозитория и его имя класса
|
||||
* [
|
||||
* 'WordPress' => 'WBCR\Factory_Freemius_Rio_600\Updates\Freemius_Repository',
|
||||
* 'freemius' => '\WBCR\Factory_600\Updates\Wordpress_Repository'
|
||||
* ]
|
||||
*/
|
||||
public static $repositories = [];
|
||||
|
||||
/**
|
||||
* Тип апгрейдера, может быть default, premium
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'default';
|
||||
|
||||
/**
|
||||
* @var Wbcr_Factory600_Plugin
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_basename;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_main_file;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_absolute_path;
|
||||
|
||||
/**
|
||||
* Имя плагина, для которого нужно проверять обновления
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_slug;
|
||||
|
||||
/**
|
||||
* @var Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $rollback = [
|
||||
'prev_stable_version' => null,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $is_debug = false;
|
||||
|
||||
/**
|
||||
* Manager constructor.
|
||||
*
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
* @param $args
|
||||
* @param bool $is_premium
|
||||
*
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin ) {
|
||||
|
||||
$this->plugin = $plugin;
|
||||
|
||||
$this->plugin_basename = $plugin->get_paths()->basename;
|
||||
$this->plugin_main_file = $plugin->get_paths()->main_file;
|
||||
$this->plugin_absolute_path = $plugin->get_paths()->absolute;
|
||||
$this->is_debug = defined( 'FACTORY_UPDATES_DEBUG' ) && FACTORY_UPDATES_DEBUG;
|
||||
|
||||
// Добавляем WordPress репозиторий в список доступных репозиториев по умолчанию
|
||||
self::$repositories['wordpress'] = '\WBCR\Factory_600\Updates\Wordpress_Repository';
|
||||
self::$repositories['github'] = '\WBCR\Factory_600\Updates\Github_Repository';
|
||||
|
||||
$settings = $this->get_settings();
|
||||
|
||||
$this->plugin_slug = $settings['slug'];
|
||||
$this->rollback = $settings['rollback_settings'];
|
||||
|
||||
if ( empty( $this->plugin_slug ) || ! is_string( $this->plugin_slug ) ) {
|
||||
throw new Exception( 'Argument {slug} can not be empty and must be of type string.' );
|
||||
}
|
||||
|
||||
$this->set_repository();
|
||||
|
||||
if ( $this->repository->need_check_updates() ) {
|
||||
$this->init_hooks();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function set_repository() {
|
||||
$settings = $this->get_settings();
|
||||
$this->repository = $this->get_repository( $settings['repository'] );
|
||||
$this->repository->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function get_settings() {
|
||||
$settings = $this->plugin->getPluginInfoAttr( 'updates_settings' );
|
||||
|
||||
return wp_parse_args(
|
||||
$settings,
|
||||
[
|
||||
'repository' => 'wordpress',
|
||||
'alternate_updates_mode' => false,
|
||||
'slug' => '',
|
||||
'maybe_rollback' => false,
|
||||
'rollback_settings' => [
|
||||
'prev_stable_version' => '0.0.0',
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function init_hooks() {
|
||||
add_filter(
|
||||
'site_transient_update_plugins',
|
||||
[
|
||||
$this,
|
||||
'site_transient_update_plugins_hook',
|
||||
]
|
||||
);
|
||||
|
||||
add_action( 'wp_update_plugins', [ $this, 'reset_check_update_timer' ], 9 ); // WP Cron.
|
||||
add_action( 'deleted_site_transient', [ $this, 'reset_check_update_timer' ] );
|
||||
add_action( 'setted_site_transient', [ $this, 'reset_check_update_timer' ] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When WP sets the update_plugins site transient, we set our own transient
|
||||
*
|
||||
* @param Object $transient Site transient object.
|
||||
*
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
public function site_transient_update_plugins_hook( $transient ) {
|
||||
|
||||
if ( ! $transient || ! is_object( $transient ) || empty( $this->plugin_basename ) ) {
|
||||
return $transient;
|
||||
}
|
||||
|
||||
$temp_object = $this->check_updates();
|
||||
|
||||
if ( ! empty( $temp_object ) && is_object( $temp_object ) && version_compare( $this->get_plugin_version(), $temp_object->new_version, '<' ) ) {
|
||||
$transient->response[ $temp_object->plugin ] = $temp_object;
|
||||
|
||||
return $transient;
|
||||
}
|
||||
|
||||
return $transient;
|
||||
}
|
||||
|
||||
/**
|
||||
* When WP deletes the update_plugins site transient or updates the plugins, we delete our own transients to avoid another 12 hours waiting
|
||||
*
|
||||
* @param string $transient Transient name.
|
||||
* @param object $value Transient object.
|
||||
* @since 4.1.1
|
||||
*/
|
||||
public function reset_check_update_timer( $transient = 'update_plugins', $value = null ) {
|
||||
$options_prefix = $this->type == 'default' ? '' : '_' . $this->type;
|
||||
|
||||
// $value used by setted.
|
||||
if ( 'update_plugins' === $transient ) {
|
||||
if ( is_null( $value ) || is_object( $value ) && ! isset( $value->response ) ) {
|
||||
|
||||
$last_check_time = (int) $this->plugin->getPopulateOption( "last_check{$options_prefix}_update_time", 0 );
|
||||
|
||||
if ( 0 !== $last_check_time && time() > ( $last_check_time + MINUTE_IN_SECONDS ) ) {
|
||||
$this->plugin->deletePopulateOption( "last_check{$options_prefix}_update_time" );
|
||||
$this->plugin->deletePopulateOption( "last_check{$options_prefix}_update" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет последние обновления для текущего или премиум плагина.
|
||||
*
|
||||
* @return object|null
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function check_updates( $force = false ) {
|
||||
|
||||
$options_prefix = $this->type == 'default' ? '' : '_' . $this->type;
|
||||
$check_updates_interval = self::CHECK_UPDATES_INTERVAL;
|
||||
$last_check_time = (int) $this->plugin->getPopulateOption( "last_check{$options_prefix}_update_time", 0 );
|
||||
|
||||
if ( $this->is_debug && defined( 'FACTORY_CHECK_UPDATES_INTERVAL' ) ) {
|
||||
$check_updates_interval = FACTORY_CHECK_UPDATES_INTERVAL;
|
||||
if ( empty( $check_updates_interval ) || ! is_numeric( $check_updates_interval ) ) {
|
||||
$check_updates_interval = MINUTE_IN_SECONDS;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $force || ( time() > ( $last_check_time + $check_updates_interval ) ) ) {
|
||||
|
||||
$this->plugin->updatePopulateOption( "last_check{$options_prefix}_update_time", time() );
|
||||
|
||||
$last_version = $this->repository->get_last_version();
|
||||
|
||||
if ( ! empty( $last_version ) ) {
|
||||
$temp_object = new stdClass();
|
||||
$temp_object->slug = $this->plugin_slug;
|
||||
$temp_object->plugin = $this->plugin_basename;
|
||||
$temp_object->new_version = $last_version;
|
||||
$temp_object->package = $this->repository->get_download_url();
|
||||
|
||||
$this->plugin->updatePopulateOption( "last_check{$options_prefix}_update", $temp_object );
|
||||
|
||||
return $temp_object;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->plugin->getPopulateOption( "last_check{$options_prefix}_update" );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $args
|
||||
*
|
||||
* @return string
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function get_admin_url( $args ) {
|
||||
$url = admin_url( 'plugins.php', $args );
|
||||
|
||||
if ( $this->plugin->isNetworkActive() ) {
|
||||
$url = network_admin_url( 'plugins.php', $args );
|
||||
}
|
||||
|
||||
return add_query_arg( $args, $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $repository_name
|
||||
*
|
||||
* @return Repository
|
||||
* @throws Exception
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function get_repository( $repository_name ) {
|
||||
|
||||
if ( isset( self::$repositories[ $repository_name ] ) && class_exists( self::$repositories[ $repository_name ] ) ) {
|
||||
if ( self::$repositories[ $repository_name ] instanceof Repository ) {
|
||||
throw new Exception( "Repository {$repository_name} must extend the class WBCR\Factory_600\Updates\Repository interface!" );
|
||||
}
|
||||
|
||||
return new self::$repositories[ $repository_name ]( $this->plugin, $this->get_settings() );
|
||||
}
|
||||
|
||||
throw new Exception( "Repository {$repository_name} is not supported!" );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function get_plugin_version() {
|
||||
return $this->plugin->getPluginVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected function rollback() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Updates;
|
||||
|
||||
// Exit if accessed directly
|
||||
use Wbcr_Factory600_Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
*/
|
||||
class Github_Repository extends Repository {
|
||||
|
||||
/**
|
||||
* Токен доступа
|
||||
*
|
||||
* Требуется, если репозиторий закрытый
|
||||
*
|
||||
* @var string
|
||||
* @since 4.4.1
|
||||
*/
|
||||
protected $github_authorize_token;
|
||||
|
||||
/**
|
||||
* Имя пользователя
|
||||
*
|
||||
* @var string
|
||||
* @since 4.4.1
|
||||
*/
|
||||
protected $github_username;
|
||||
|
||||
/**
|
||||
* Имя репозитория в Github
|
||||
*
|
||||
* @var string
|
||||
* @since 4.4.1
|
||||
*/
|
||||
protected $github_repository;
|
||||
|
||||
/**
|
||||
* Имя репозитория
|
||||
*
|
||||
* @var string
|
||||
* @since 4.4.1
|
||||
*/
|
||||
protected $plugin_slug;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 4.4.1
|
||||
*/
|
||||
protected $plugin_basename;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 4.4.1
|
||||
*/
|
||||
protected $plugin_main_file;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 4.4.1
|
||||
*/
|
||||
protected $plugin_absolute_path;
|
||||
|
||||
/**
|
||||
* Кешируем результаты запроса в этот параметр
|
||||
*
|
||||
* @var array
|
||||
* @since 4.4.1
|
||||
*/
|
||||
private $release_info;
|
||||
|
||||
/**
|
||||
* WordPress constructor.
|
||||
*
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
* @param bool $is_premium
|
||||
* @since 4.4.1
|
||||
*/
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin, array $settings = [] ) {
|
||||
$settings = wp_parse_args(
|
||||
$settings,
|
||||
[
|
||||
'github_username' => '',
|
||||
'github_authorize_token' => '',
|
||||
'github_repository' => '',
|
||||
]
|
||||
);
|
||||
|
||||
if ( empty( $settings['github_username'] ) ) {
|
||||
throw new \Exception( 'You are trying to connect a github repository for plugin updates. You must enter the username of the github repository!' );
|
||||
}
|
||||
|
||||
$this->plugin = $plugin;
|
||||
$this->plugin_basename = $this->plugin->get_paths()->basename;
|
||||
$this->plugin_main_file = $this->plugin->get_paths()->main_file;
|
||||
$this->plugin_absolute_path = $this->plugin->get_paths()->absolute;
|
||||
$this->plugin_slug = $settings['slug'];
|
||||
|
||||
$this->github_authorize_token = $settings['github_authorize_token'];
|
||||
$this->github_username = $settings['github_username'];
|
||||
$this->github_repository = empty( $settings['github_repository'] ) ? $this->plugin_slug : $settings['github_repository'];
|
||||
}
|
||||
|
||||
public function init() {
|
||||
// add_filter('upgrader_source_selection', array($this, 'change_source_package'), 10, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @since 4.4.1
|
||||
*/
|
||||
public function need_check_updates() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Если этот репозиторий используется для обновлени премиум плагина,
|
||||
* нужно установить true. В нашем случае Github используется только
|
||||
* для обновлений бесплатного плагина.
|
||||
*
|
||||
* @return bool
|
||||
* @since 4.4.1
|
||||
*/
|
||||
public function is_support_premium() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод получает ссылку на скачивание последнего релиза в Github
|
||||
*
|
||||
* @return string
|
||||
* @since 4.4.1
|
||||
*/
|
||||
public function get_download_url() {
|
||||
try {
|
||||
$response = $this->get_last_release_info();
|
||||
|
||||
if ( empty( $response['assets'] ) ) {
|
||||
throw new \Exception( 'You must upload the plugin archive to the github as a binary file.' );
|
||||
}
|
||||
|
||||
foreach ( $response['assets'] as $asset ) {
|
||||
if ( false !== strpos( $asset['name'], $this->plugin_slug ) && 'application/zip' === $asset['content_type'] ) {
|
||||
if ( $this->github_authorize_token ) { // Is there an access token?
|
||||
$asset['browser_download_url'] = add_query_arg( 'access_token', $this->github_authorize_token, $asset['browser_download_url'] ); // Update our zip url with token
|
||||
}
|
||||
|
||||
return $asset['browser_download_url'];
|
||||
}
|
||||
}
|
||||
} catch ( \Exception $e ) {
|
||||
if ( defined( 'FACTORY_UPDATES_DEBUG' ) && FACTORY_UPDATES_DEBUG ) {
|
||||
throw new \Exception( $e->getMessage(), $e->getCode() );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод получает версию последнего релиза плагина загруженного на Github
|
||||
*
|
||||
* @return string|null Возвращает версию 1.2.3, в случае ошибки null
|
||||
* @since 4.4.1
|
||||
*/
|
||||
public function get_last_version() {
|
||||
try {
|
||||
$response = $this->get_last_release_info();
|
||||
|
||||
return $response['tag_name'];
|
||||
} catch ( \Exception $e ) {
|
||||
if ( defined( 'FACTORY_UPDATES_DEBUG' ) && FACTORY_UPDATES_DEBUG ) {
|
||||
throw new \Exception( $e->getMessage(), $e->getCode() );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the package source contains .mo and .po files.
|
||||
*
|
||||
* Hooked to the {@see 'upgrader_source_selection'} filter by
|
||||
* Language_Pack_Upgrader::bulk_upgrade().
|
||||
*
|
||||
* @param string|\WP_Error $source The path to the downloaded package source.
|
||||
* @param string $remote_source Remote file source location.
|
||||
* @return string|\WP_Error The source as passed, or a WP_Error object on failure.
|
||||
* @global \WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
|
||||
*
|
||||
* @since 4.4.1
|
||||
*/
|
||||
/*
|
||||
public function change_source_package($source, $remote_source, $upgrader, $hook_extra)
|
||||
{
|
||||
global $wp_filesystem;
|
||||
|
||||
if( is_wp_error($source) ) {
|
||||
return $source;
|
||||
}
|
||||
|
||||
if( !empty($hook_extra) && "plugin" === $hook_extra['type'] && "update" === $hook_extra['action'] && basename($source) === $this->plugin_slug ) {
|
||||
$new_source = $wp_filesystem->wp_content_dir() . 'upgrade/' . $this->plugin_slug;
|
||||
|
||||
$wp_filesystem->move($source, $new_source);
|
||||
|
||||
return $new_source;
|
||||
}
|
||||
|
||||
return $source;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Метод получает информацию о последнем релизе на Github
|
||||
*
|
||||
* Имена релизов и тегов на Github строго должны соотвествовать версии загруженного релиза.
|
||||
* К примеру 0.0.0 - правильное именование, v0.0.0 - будет ошибкой
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
* @since 4.4.1
|
||||
*/
|
||||
protected function get_last_release_info() {
|
||||
if ( ! empty( $this->release_info ) ) {
|
||||
return $this->release_info;
|
||||
}
|
||||
|
||||
$request_uri = sprintf( 'https://api.github.com/repos/%s/%s/releases', $this->github_username, $this->github_repository ); // Build URI
|
||||
|
||||
if ( $this->github_authorize_token ) { // Is there an access token?
|
||||
$request_uri = add_query_arg( 'access_token', $this->github_authorize_token, $request_uri ); // Append it
|
||||
}
|
||||
|
||||
$response = wp_remote_get( $request_uri );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
throw new \Exception( $response->get_error_message() );
|
||||
}
|
||||
|
||||
$data = @json_decode( wp_remote_retrieve_body( $response ), true ); // Get JSON and parse it
|
||||
|
||||
if ( empty( $data ) ) {
|
||||
throw new \Exception( 'Failed to decode received data:' . json_last_error() );
|
||||
}
|
||||
|
||||
if ( isset( $data['message'] ) ) {
|
||||
throw new \Exception( 'It is not possible to get release information in the github repository. The repository may not exist. Received error text: ' . $data['message'] );
|
||||
}
|
||||
|
||||
uasort(
|
||||
$data,
|
||||
function ( $a, $b ) {
|
||||
return version_compare( $b['tag_name'], $a['tag_name'] );
|
||||
}
|
||||
);
|
||||
|
||||
$data = current( $data ); // Get the first item
|
||||
|
||||
$this->release_info = $data;
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Updates;
|
||||
|
||||
// Exit if accessed directly
|
||||
use Wbcr_Factory600_Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
*/
|
||||
abstract class Repository {
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $initialized = false;
|
||||
|
||||
/**
|
||||
* @var Wbcr_Factory600_Plugin
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* Repository constructor.
|
||||
*
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
* @param array $settings
|
||||
*/
|
||||
abstract public function __construct( Wbcr_Factory600_Plugin $plugin, array $settings = [] );
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
abstract public function init();
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function need_check_updates();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function is_support_premium();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract public function get_download_url();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract public function get_last_version();
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace WBCR\Factory_600\Updates;
|
||||
|
||||
// Exit if accessed directly
|
||||
use Wbcr_Factory600_Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
*/
|
||||
class Wordpress_Repository extends Repository {
|
||||
|
||||
/**
|
||||
* WordPress constructor.
|
||||
*
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
* @param array $settings
|
||||
*/
|
||||
public function __construct( Wbcr_Factory600_Plugin $plugin, array $settings = [] ) {
|
||||
$this->plugin = $plugin;
|
||||
}
|
||||
|
||||
public function init() {
|
||||
// TODO: Implement init() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function need_check_updates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_support_premium() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_download_url() {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_last_version() {
|
||||
return '0.0.0';
|
||||
}
|
||||
|
||||
public function check_updates() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function need_update() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<?php
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,12 @@
|
||||
body {
|
||||
font-family: Arial;
|
||||
font-size: 14px;
|
||||
background-color: #fff;
|
||||
}
|
||||
p {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
p + p {
|
||||
margin-top: 5px;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
(function($){
|
||||
|
||||
if ( !$.factory ) $.factory = {}
|
||||
if ( $.factory.widget ) return;
|
||||
|
||||
/**
|
||||
* Widget Factory.
|
||||
*/
|
||||
$.factory.widget = function (pluginName, pluginObject) {
|
||||
|
||||
var factory = {
|
||||
|
||||
createWidget: function (element, options) {
|
||||
var widget = $.extend(true, {}, pluginObject);
|
||||
|
||||
widget.element = $(element);
|
||||
widget.options = $.extend(true, widget.options, options);
|
||||
|
||||
if (widget._init) widget._init();
|
||||
if (widget._create) widget._create();
|
||||
|
||||
$.data(element, 'plugin_' + pluginName, widget);
|
||||
},
|
||||
|
||||
callMethod: function (widget, methodName) {
|
||||
widget[methodName] && widget[methodName]();
|
||||
}
|
||||
};
|
||||
|
||||
$.fn[pluginName] = function () {
|
||||
var args = arguments;
|
||||
var argsCount = arguments.length;
|
||||
|
||||
this.each(function () {
|
||||
|
||||
var widget = $.data(this, 'plugin_' + pluginName);
|
||||
|
||||
// a widget is not created yet
|
||||
if (!widget && argsCount <= 1) {
|
||||
factory.createWidget(this, argsCount ? args[0] : false);
|
||||
|
||||
// a widget is created, the public method with no args is being called
|
||||
} else if (argsCount == 1) {
|
||||
factory.callMethod(widget, args[0]);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Radio #1
|
||||
*/
|
||||
|
||||
$.fn.onpRadioCircles = function( options ) {
|
||||
if ( !options ) options = {};
|
||||
options.theme = 'circles';
|
||||
$(this).onpRadio(options);
|
||||
};
|
||||
|
||||
$.fn.onpRadioSquares = function( options ) {
|
||||
if ( !options ) options = {};
|
||||
options.theme = 'squares';
|
||||
$(this).onpRadio(options);
|
||||
};
|
||||
|
||||
$.factory.widget('onpRadio', {
|
||||
options: {
|
||||
theme: 'squares',
|
||||
selected: null
|
||||
},
|
||||
_create: function() {
|
||||
var self = this;
|
||||
this._createMarkup();
|
||||
|
||||
this.radio.find('.onp-radio-option').click(function(){
|
||||
if ( $(this).is(".disabled") ) return;
|
||||
var selected = self.radio.find('.onp-radio-option.selected');
|
||||
if ( selected.data('value') == $(this).data('value')) return;
|
||||
|
||||
selected.removeClass('selected');
|
||||
$(this).addClass("selected");
|
||||
|
||||
var value = $(this).data('value');
|
||||
self.element.val(value);
|
||||
self.element.trigger( "change", $(this).data('value') );
|
||||
});
|
||||
},
|
||||
_createMarkup: function() {
|
||||
|
||||
var wrap = $("<ul class='onp-radio-wrap'></ul>").addClass('onp-radio-' + this.options.theme);
|
||||
this.element.find("option").each(function(){
|
||||
var $this = $(this);
|
||||
|
||||
var value = $this.attr('value');
|
||||
var text = $this.html();
|
||||
var icon = $this.data('icon');
|
||||
var disabled = $this.attr('disabled');
|
||||
|
||||
var option = $("<li class='onp-radio-option' data-value='" + value + "'></li>");
|
||||
var innerOptionWrap = $("<span class='onp-radio-option-inner-wrap'></span>").appendTo(option);
|
||||
option.addClass('onp-radio-option-' + value);
|
||||
|
||||
if ( icon ) innerOptionWrap.append("<i class='" + icon + "'></i>");
|
||||
if ( disabled ) option.addClass('disabled');
|
||||
|
||||
wrap.append(option);
|
||||
});
|
||||
|
||||
this.options.selected = this.options.selected || this.element.find("option:selected").attr('value');
|
||||
wrap.find('.onp-radio-option-' + this.options.selected).addClass("selected");
|
||||
|
||||
this.element.hide();
|
||||
this.element.after(wrap);
|
||||
this.radio = wrap;
|
||||
}
|
||||
});
|
||||
|
||||
var factoryForms = {
|
||||
|
||||
collapsedGroups: function( $target ) {
|
||||
if ( !$target ) $target = $("body");
|
||||
|
||||
$target.find(".fy-collapsed-show").click(function(){
|
||||
$( $(this).attr('href') ).fadeIn();
|
||||
$(this).hide();
|
||||
return false;
|
||||
});
|
||||
|
||||
$target.find(".fy-collapsed-hide").click(function(){
|
||||
var content = $( $(this).attr('href') );
|
||||
content.fadeOut(300, function(){
|
||||
content.prev().show();
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(function(){
|
||||
$(".onp-radio-circles.auto").onpRadioCircles();
|
||||
$(".onp-radio-squares.auto").onpRadioSquares();
|
||||
factoryForms.collapsedGroups();
|
||||
});
|
||||
|
||||
})(jQuery)
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
<?php
|
||||
/**
|
||||
* Factory Forms
|
||||
*
|
||||
* @since 1.0.1
|
||||
* @package factory-forms
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// checks if the module is already loaded in order to
|
||||
// prevent loading the same version of the module twice.
|
||||
if ( defined( 'FACTORY_FORMS_600_LOADED' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
define( 'FACTORY_FORMS_600_LOADED', true );
|
||||
define( 'FACTORY_FORMS_600_VERSION', '6.0.0' );
|
||||
|
||||
// absolute path and URL to the files and resources of the module.
|
||||
define( 'FACTORY_FORMS_600_DIR', __DIR__ );
|
||||
define( 'FACTORY_FORMS_600_URL', plugins_url( '', __FILE__ ) );
|
||||
|
||||
// comp merge
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/providers/value-provider.interface.php';
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/providers/meta-value-provider.class.php';
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/providers/options-value-provider.class.php';
|
||||
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/form.class.php';
|
||||
// endcomp
|
||||
|
||||
add_action(
|
||||
'init',
|
||||
function () {
|
||||
load_plugin_textdomain( 'robin-image-optimizer', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* We add this code into the hook because all these controls quite heavy. So in order to get better perfomance,
|
||||
* we load the form controls only on pages where the forms are created.
|
||||
*
|
||||
* @since 3.0.7
|
||||
* @see the 'wbcr_factory_forms_600_register_controls' hook
|
||||
*/
|
||||
if ( ! function_exists( 'wbcr_factory_forms_600_register_default_controls' ) ) {
|
||||
|
||||
/**
|
||||
* @param Wbcr_Factory600_Plugin $plugin
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
function wbcr_factory_forms_600_register_default_controls( Wbcr_Factory600_Plugin $plugin ) {
|
||||
|
||||
if ( $plugin && ! isset( $plugin->forms ) ) {
|
||||
throw new Exception( "The module Factory Forms is not loaded for the plugin '{$plugin->getPluginName()}'." );
|
||||
}
|
||||
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/html-builder.class.php';
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/form-element.class.php';
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/control.class.php';
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/complex-control.class.php';
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/holder.class.php';
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/control-holder.class.php';
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/custom-element.class.php';
|
||||
require_once FACTORY_FORMS_600_DIR . '/includes/form-layout.class.php';
|
||||
|
||||
// registration of controls
|
||||
$plugin->forms->registerControls(
|
||||
[
|
||||
[
|
||||
'type' => 'checkbox',
|
||||
'class' => 'Wbcr_FactoryForms600_CheckboxControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/checkbox.php',
|
||||
],
|
||||
[
|
||||
'type' => 'list',
|
||||
'class' => 'Wbcr_FactoryForms600_ListControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/list.php',
|
||||
],
|
||||
[
|
||||
'type' => 'dropdown',
|
||||
'class' => 'Wbcr_FactoryForms600_DropdownControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/dropdown.php',
|
||||
],
|
||||
[
|
||||
'type' => 'dropdown-and-colors',
|
||||
'class' => 'Wbcr_FactoryForms600_DropdownAndColorsControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/dropdown-and-colors.php',
|
||||
],
|
||||
[
|
||||
'type' => 'hidden',
|
||||
'class' => 'Wbcr_FactoryForms600_HiddenControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/hidden.php',
|
||||
],
|
||||
[
|
||||
'type' => 'hidden',
|
||||
'class' => 'Wbcr_FactoryForms600_HiddenControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/hidden.php',
|
||||
],
|
||||
[
|
||||
'type' => 'radio',
|
||||
'class' => 'Wbcr_FactoryForms600_RadioControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/radio.php',
|
||||
],
|
||||
[
|
||||
'type' => 'radio-colors',
|
||||
'class' => 'Wbcr_FactoryForms600_RadioColorsControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/radio-colors.php',
|
||||
],
|
||||
[
|
||||
'type' => 'textarea',
|
||||
'class' => 'Wbcr_FactoryForms600_TextareaControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/textarea.php',
|
||||
],
|
||||
[
|
||||
'type' => 'textbox',
|
||||
'class' => 'Wbcr_FactoryForms600_TextboxControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/textbox.php',
|
||||
],
|
||||
[
|
||||
'type' => 'multiple-textbox',
|
||||
'class' => 'Wbcr_FactoryForms600_MultipleTextboxControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/multiple-textbox.php',
|
||||
],
|
||||
[
|
||||
'type' => 'datetimepicker-range',
|
||||
'class' => 'Wbcr_FactoryForms600_DatepickerRangeControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/datepicker-range.php',
|
||||
],
|
||||
[
|
||||
'type' => 'url',
|
||||
'class' => 'Wbcr_FactoryForms600_UrlControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/url.php',
|
||||
],
|
||||
[
|
||||
'type' => 'wp-editor',
|
||||
'class' => 'Wbcr_FactoryForms600_WpEditorControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/wp-editor.php',
|
||||
],
|
||||
[
|
||||
'type' => 'color',
|
||||
'class' => 'Wbcr_FactoryForms600_ColorControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/color.php',
|
||||
],
|
||||
[
|
||||
'type' => 'color-and-opacity',
|
||||
'class' => 'Wbcr_FactoryForms600_ColorAndOpacityControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/color-and-opacity.php',
|
||||
],
|
||||
[
|
||||
'type' => 'gradient',
|
||||
'class' => 'Wbcr_FactoryForms600_GradientControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/gradient.php',
|
||||
],
|
||||
[
|
||||
'type' => 'font',
|
||||
'class' => 'Wbcr_FactoryForms600_FontControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/font.php',
|
||||
],
|
||||
[
|
||||
'type' => 'google-font',
|
||||
'class' => 'Wbcr_FactoryForms600_GoogleFontControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/google-font.php',
|
||||
],
|
||||
[
|
||||
'type' => 'pattern',
|
||||
'class' => 'Wbcr_FactoryForms600_PatternControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/pattern.php',
|
||||
],
|
||||
[
|
||||
'type' => 'integer',
|
||||
'class' => 'Wbcr_FactoryForms600_IntegerControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/integer.php',
|
||||
],
|
||||
[
|
||||
'type' => 'control-group',
|
||||
'class' => 'Wbcr_FactoryForms600_ControlGroupHolder',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/control-group.php',
|
||||
],
|
||||
[
|
||||
'type' => 'paddings-editor',
|
||||
'class' => 'Wbcr_FactoryForms600_PaddingsEditorControl',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/paddings-editor.php',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
// registration of control holders
|
||||
$plugin->forms->registerHolders(
|
||||
[
|
||||
[
|
||||
'type' => 'tab',
|
||||
'class' => 'Wbcr_FactoryForms600_TabHolder',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/tab.php',
|
||||
],
|
||||
[
|
||||
'type' => 'tab-item',
|
||||
'class' => 'Wbcr_FactoryForms600_TabItemHolder',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/tab-item.php',
|
||||
],
|
||||
[
|
||||
'type' => 'accordion',
|
||||
'class' => 'Wbcr_FactoryForms600_AccordionHolder',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/accordion.php',
|
||||
],
|
||||
[
|
||||
'type' => 'accordion-item',
|
||||
'class' => 'Wbcr_FactoryForms600_AccordionItemHolder',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/accordion-item.php',
|
||||
],
|
||||
[
|
||||
'type' => 'control-group',
|
||||
'class' => 'Wbcr_FactoryForms600_ControlGroupHolder',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/control-group.php',
|
||||
],
|
||||
[
|
||||
'type' => 'control-group-item',
|
||||
'class' => 'Wbcr_FactoryForms600_ControlGroupItem',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/control-group-item.php',
|
||||
],
|
||||
[
|
||||
'type' => 'form-group',
|
||||
'class' => 'Wbcr_FactoryForms600_FormGroupHolder',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/form-group.php',
|
||||
],
|
||||
[
|
||||
'type' => 'more-link',
|
||||
'class' => 'Wbcr_FactoryForms600_MoreLinkHolder',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/more-link.php',
|
||||
],
|
||||
[
|
||||
'type' => 'div',
|
||||
'class' => 'Wbcr_FactoryForms600_DivHolder',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/div.php',
|
||||
],
|
||||
[
|
||||
'type' => 'columns',
|
||||
'class' => 'Wbcr_FactoryForms600_ColumnsHolder',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/holders/columns.php',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
// registration custom form elements
|
||||
$plugin->forms->registerCustomElements(
|
||||
[
|
||||
[
|
||||
'type' => 'html',
|
||||
'class' => 'Wbcr_FactoryForms600_Html',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/customs/html.php',
|
||||
],
|
||||
[
|
||||
'type' => 'separator',
|
||||
'class' => 'Wbcr_FactoryForms600_Separator',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/controls/customs/separator.php',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
// registration of form layouts
|
||||
$plugin->forms->registerFormLayout(
|
||||
[
|
||||
'name' => 'bootstrap-3',
|
||||
'class' => 'Wbcr_FactoryForms600_Bootstrap3FormLayout',
|
||||
'include' => FACTORY_FORMS_600_DIR . '/layouts/bootstrap-3/bootstrap-3.php',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
add_action( 'wbcr_factory_forms_600_register_controls', 'wbcr_factory_forms_600_register_default_controls' );
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Checkbox Control
|
||||
*
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* value => a value to show in the control
|
||||
* default => a default value of the control if the "value" option is not specified
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_CheckboxControl' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_CheckboxControl extends Wbcr_FactoryForms600_Control {
|
||||
|
||||
public $type = 'checkbox';
|
||||
|
||||
public function getSubmitValue( $name, $sub_name ) {
|
||||
$name_on_form = $this->getNameOnForm( $name );
|
||||
|
||||
return isset( $_POST[ $name_on_form ] ) && $_POST[ $name_on_form ] != 0
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the html markup of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
$events_on_data = $this->getOption( 'eventsOn', [] );
|
||||
$events_off_data = $this->getOption( 'eventsOff', [] );
|
||||
|
||||
if ( ! empty( $events_on_data ) || ! empty( $events_off_data ) ) {
|
||||
|
||||
$events_on_string_data = json_encode( $events_on_data );
|
||||
$events_off_string_data = json_encode( $events_off_data );
|
||||
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
$value = $this->getValue();
|
||||
|
||||
$print_styles = '';
|
||||
|
||||
if ( $value ) {
|
||||
$current_events_data = $events_on_data;
|
||||
} else {
|
||||
$current_events_data = $events_off_data;
|
||||
}
|
||||
|
||||
foreach ( $current_events_data as $event_name => $selectors ) {
|
||||
if ( $event_name == 'hide' ) {
|
||||
$print_styles .= $selectors . '{display:none;}';
|
||||
} elseif ( $event_name == 'show' ) {
|
||||
$print_styles .= $selectors . '{display:block;}';
|
||||
}
|
||||
}
|
||||
|
||||
echo '<style>' . esc_html( $print_styles ) . '</style>';
|
||||
?>
|
||||
|
||||
<script>
|
||||
// Onepress factory checkbox control events
|
||||
if( void 0 === window.__factory_checkbox_control_events_on_data ) {
|
||||
window.__factory_checkbox_control_events_on_data = {};
|
||||
}
|
||||
if( void 0 === window.__factory_checkbox_control_events_off_data ) {
|
||||
window.__factory_checkbox_control_events_off_data = {};
|
||||
}
|
||||
window.__factory_checkbox_control_events_on_data['<?php echo esc_attr( $name_on_form ); ?>'] = <?php echo $events_on_string_data; ?>;
|
||||
window.__factory_checkbox_control_events_off_data['<?php echo esc_attr( $name_on_form ); ?>'] = <?php echo $events_off_string_data; ?>;
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
if ( 'buttons' == $this->getOption( 'way' ) ) {
|
||||
$this->buttonsHtml();
|
||||
} else {
|
||||
$this->defaultHtml();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the Buttons Checkbox.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
protected function buttonsHtml() {
|
||||
$value = esc_attr( $this->getValue() );
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
|
||||
$this->addCssClass( 'factory-buttons-way' );
|
||||
$this->addCssClass( 'btn-group' );
|
||||
|
||||
if ( $this->getOption( 'tumbler', false ) ) {
|
||||
$this->addCssClass( 'factory-tumbler' );
|
||||
}
|
||||
|
||||
$tumbler_function = $this->getOption( 'tumblerFunction', false );
|
||||
if ( $tumbler_function ) {
|
||||
$this->addHtmlData( 'tumbler-function', $tumbler_function );
|
||||
}
|
||||
|
||||
if ( $this->getOption( 'tumblerHint', false ) ) {
|
||||
$this->addCssClass( 'factory-has-tumbler-hint' );
|
||||
|
||||
$delay = $this->getOption( 'tumblerDelay', 3000 );
|
||||
$this->addHtmlData( 'tumbler-delay', $delay );
|
||||
}
|
||||
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<button type="button" class="btn btn-default btn-small btn-sm factory-on
|
||||
<?php
|
||||
if ( $value ) {
|
||||
echo 'active';
|
||||
}
|
||||
?>
|
||||
"><?php _e( 'On', 'robin-image-optimizer' ); ?></button>
|
||||
<button type="button" class="btn btn-default btn-small btn-sm factory-off
|
||||
<?php
|
||||
if ( ! $value ) {
|
||||
echo 'active';
|
||||
}
|
||||
?>
|
||||
" data-value="0"><?php _e( 'Off', 'robin-image-optimizer' ); ?></button>
|
||||
<input type="checkbox" style="display: none" id="<?php echo esc_attr( $name_on_form ); ?>" class="factory-result" name="<?php echo esc_attr( $name_on_form ); ?>" value="<?php echo esc_attr( $value ); ?>"
|
||||
<?php
|
||||
if ( $value ) {
|
||||
echo 'checked="checked"';
|
||||
}
|
||||
?>
|
||||
" />
|
||||
</div>
|
||||
<?php if ( $this->getOption( 'tumblerHint', false ) ) { ?>
|
||||
<div class="factory-checkbox-tumbler-hint factory-tumbler-hint" style="display: none;">
|
||||
<div class="factory-tumbler-content">
|
||||
<?php echo esc_html( $this->getOption( 'tumblerHint' ) ); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the standart checkbox.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
protected function defaultHtml() {
|
||||
$value = esc_attr( $this->getValue() );
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
|
||||
$this->addHtmlAttr( 'type', 'checkbox' );
|
||||
$this->addHtmlAttr( 'id', $name_on_form );
|
||||
$this->addHtmlAttr( 'name', $name_on_form );
|
||||
$this->addHtmlAttr( 'value', $value );
|
||||
|
||||
if ( $value ) {
|
||||
$this->addHtmlAttr( 'checked', 'checked' );
|
||||
}
|
||||
$this->addCssClass( 'factory-default-way' );
|
||||
|
||||
?>
|
||||
<input <?php $this->attrs(); ?>/>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Color and Opacity
|
||||
*
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* value => a value to show in the control
|
||||
* default => a default value of the control if the "value" option is not specified
|
||||
*
|
||||
* @package core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_ColorAndOpacityControl' ) ) {
|
||||
}
|
||||
|
||||
class Wbcr_FactoryForms600_ColorAndOpacityControl extends Wbcr_FactoryForms600_ComplexControl {
|
||||
|
||||
public $type = 'color-and-opacity';
|
||||
|
||||
public function __construct( $options, $form, $provider = null ) {
|
||||
parent::__construct( $options, $form, $provider );
|
||||
|
||||
if ( ! isset( $options['color'] ) ) {
|
||||
$options['color'] = [];
|
||||
}
|
||||
|
||||
$options['color'] = array_merge(
|
||||
$options['color'],
|
||||
[
|
||||
'name' => $this->options['name'] . '__color',
|
||||
'default' => isset( $this->options['default'] )
|
||||
? $this->options['default']['color']
|
||||
: '#1e8cbe',
|
||||
'pickerTarget' => '.factory-control-' . $this->options['name'] . ' .factory-picker-target',
|
||||
]
|
||||
);
|
||||
|
||||
if ( ! isset( $options['opacity'] ) ) {
|
||||
$options['opacity'] = [];
|
||||
}
|
||||
|
||||
$options['opacity'] = array_merge(
|
||||
$options['opacity'],
|
||||
[
|
||||
'name' => $this->options['name'] . '__opacity',
|
||||
'default' => isset( $this->options['default'] )
|
||||
? $this->options['default']['opacity']
|
||||
: 100,
|
||||
'units' => '%',
|
||||
'range' => [ 0, 100 ],
|
||||
'way' => 'slider',
|
||||
]
|
||||
);
|
||||
|
||||
$this->color = new Wbcr_FactoryForms600_ColorControl( $options['color'], $form, $provider );
|
||||
$this->opacity = new Wbcr_FactoryForms600_IntegerControl( $options['opacity'], $form, $provider );
|
||||
|
||||
$this->innerControls = [ $this->color, $this->opacity ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the html markup of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<div class="factory-control-row">
|
||||
<div class="factory-color-wrap">
|
||||
<?php $this->color->html(); ?>
|
||||
</div>
|
||||
<div class="factory-opacity-wrap">
|
||||
<?php $this->opacity->html(); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="factory-picker-target"></div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Color
|
||||
*
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* value => a value to show in the control
|
||||
* default => a default value of the control if the "value" option is not specified
|
||||
*
|
||||
* @package core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_ColorControl' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_ColorControl extends Wbcr_FactoryForms600_Control {
|
||||
|
||||
public $type = 'color';
|
||||
|
||||
/**
|
||||
* Shows the html markup of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
$name = $this->getNameOnForm();
|
||||
$value = esc_attr( $this->getValue() );
|
||||
|
||||
if ( ! $value ) {
|
||||
$value = '#1e8cbe';
|
||||
}
|
||||
|
||||
// the "pickerTarget" options allows to select element where the palette will be shown
|
||||
$picker_target = $this->getOption( 'pickerTarget' );
|
||||
|
||||
if ( ! empty( $picker_target ) ) {
|
||||
$this->addHtmlData( 'picker-target', $picker_target );
|
||||
}
|
||||
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<div class="factory-background"
|
||||
<?php
|
||||
echo( ! empty( $value )
|
||||
? 'style="background:' . $value . ';"'
|
||||
: '' );
|
||||
?>
|
||||
></div>
|
||||
<div class="factory-pattern"></div>
|
||||
<input type="text" id="<?php echo esc_attr( $name ); ?>" name="<?php echo esc_attr( $name ); ?>" class="factory-input-text factory-color-hex" value="<?php echo esc_attr( $value ); ?>">
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Html Markup
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_Html' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_Html extends Wbcr_FactoryForms600_CustomElement {
|
||||
|
||||
public $type = 'html';
|
||||
|
||||
/**
|
||||
* Shows the html markup of the element.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
$html = $this->getOption( 'html', '' );
|
||||
|
||||
// if the data options is a valid callback for an object method
|
||||
if ( ( is_array( $html ) && count( $html ) == 2 && gettype( $html[0] ) == 'object' ) || function_exists( $html ) ) {
|
||||
|
||||
call_user_func( $html, $this );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if the data options is an array of values
|
||||
echo $html;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* Separator Markup
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_Separator' ) ) {
|
||||
class Wbcr_FactoryForms600_Separator extends Wbcr_FactoryForms600_CustomElement {
|
||||
|
||||
public $type = 'separator';
|
||||
|
||||
/**
|
||||
* Shows the html markup of the element.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>></div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Datepicker range control
|
||||
*
|
||||
* Example:
|
||||
* 'type' => 'datetimepicker-range',
|
||||
* 'name' => 'facebook_start_date_filter',
|
||||
* 'range_1' => array(
|
||||
* 'format' => 'YYYY/MM/DD HH:mm',
|
||||
* 'default' => date('Y/m/d H:i', strtotime('-1 week'))
|
||||
* ),
|
||||
* 'range_2' => array(
|
||||
* 'format' => 'YYYY/MM/DD HH:mm',
|
||||
* 'default' => date('Y/m/d H:i')
|
||||
* ),
|
||||
* 'title' => __('Выберите период', 'wpcr-scrapes'),
|
||||
* 'hint' => __('Если Вкл., вы сможете установить настройки выбора записей за установленный период времени.', 'wpcr-scrapes')
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_DatepickerRangeControl' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_DatepickerRangeControl extends Wbcr_FactoryForms600_ComplexControl {
|
||||
|
||||
public $type = 'datetimepicker-range';
|
||||
|
||||
public function __construct( $options, $form, $provider = null ) {
|
||||
parent::__construct( $options, $form, $provider );
|
||||
|
||||
if ( ! isset( $options['range_1'] ) ) {
|
||||
$options['range_1'] = [];
|
||||
}
|
||||
|
||||
$options['range_1'] = array_merge(
|
||||
[
|
||||
'scope' => isset( $options['scope'] )
|
||||
? $options['scope']
|
||||
: 'factory',
|
||||
'name' => $this->options['name'] . '__range_1',
|
||||
'format' => 'YYYY/MM/DD HH:mm',
|
||||
'default' => date( 'Y/m/d H:i' ),
|
||||
],
|
||||
$options['range_1']
|
||||
);
|
||||
|
||||
if ( ! isset( $options['range_2'] ) ) {
|
||||
$options['range_2'] = [];
|
||||
}
|
||||
|
||||
$options['range_2'] = array_merge(
|
||||
[
|
||||
'scope' => isset( $options['scope'] )
|
||||
? $options['scope']
|
||||
: 'factory',
|
||||
'name' => $this->options['name'] . '__range_2',
|
||||
'format' => 'YYYY/MM/DD HH:mm',
|
||||
'default' => date( 'Y/m/d H:i', strtotime( '+1 month' ) ),
|
||||
],
|
||||
$options['range_2']
|
||||
);
|
||||
|
||||
$this->range_1 = new Wbcr_FactoryForms600_TextboxControl( $options['range_1'], $form, $provider );
|
||||
$this->range_2 = new Wbcr_FactoryForms600_TextboxControl( $options['range_2'], $form, $provider );
|
||||
$this->inner_controls = [ $this->range_1, $this->range_2 ];
|
||||
|
||||
foreach ( $this->inner_controls as $key => $control ) {
|
||||
$control->addCssClass( 'factory-datetimepicker-range-' . $key );
|
||||
$control->addHtmlAttr( 'data-date-show-today-button', 'true' );
|
||||
$control->addHtmlAttr( 'data-date-show-clear', 'true' );
|
||||
|
||||
$format = $control->getOption( 'format' );
|
||||
|
||||
if ( ! empty( $format ) ) {
|
||||
// 'YYYY/MM/DD HH:mm'
|
||||
$control->addHtmlAttr( 'data-date-format', $format );
|
||||
}
|
||||
|
||||
$locale_parts = explode( '_', get_locale() );
|
||||
|
||||
$locale = isset( $locale_parts[0] )
|
||||
? $locale_parts[0]
|
||||
: 'en';
|
||||
|
||||
$control->addHtmlAttr( 'data-date-locale', $locale );
|
||||
}
|
||||
}
|
||||
|
||||
public function render() {
|
||||
?>
|
||||
<div class='input-group date factory-datetimepicker-input-group' style="display:inline-block; width: 200px">
|
||||
<?php $this->range_1->render(); ?>
|
||||
</div>
|
||||
<div class='input-group date factory-datetimepicker-input-group' style="display:inline-block; width: 200px">
|
||||
<?php $this->range_2->render(); ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Dropdown and Colors List Control
|
||||
*
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* // see FactoryForms600_DropdownControl
|
||||
* 'dropdown' => array(
|
||||
* // a callback to return items or an array of items to select
|
||||
* 'data' => OPanda_ThemeManager::getThemes(OPanda_Items::getCurrentItemName(), 'dropdown'),
|
||||
* 'default' => 'default',
|
||||
* 'value' => 'value' // a value to show in the control
|
||||
* ),
|
||||
* // see FactoryForms600_RadioColorsControl
|
||||
* 'colors' => array(
|
||||
* // a callback to return items or an array of items to select
|
||||
* 'data' => array(
|
||||
* array('default', '#75649b'),
|
||||
* array('black', '#222'),
|
||||
* array('light', '#fff3ce'),
|
||||
* array('forest', '#c9d4be'),
|
||||
* ),
|
||||
* 'value' => 'value' // a value to show in the control
|
||||
* 'default' => 'default', // a default value of the control if the "value" option is not specified
|
||||
* ),
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_DropdownAndColorsControl' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_DropdownAndColorsControl extends Wbcr_FactoryForms600_ComplexControl {
|
||||
|
||||
public $type = 'dropdown-and-colors';
|
||||
|
||||
public function __construct( $options, $form, $provider = null ) {
|
||||
parent::__construct( $options, $form, $provider );
|
||||
|
||||
if ( ! isset( $options['dropdown'] ) ) {
|
||||
$options['dropdown'] = [];
|
||||
}
|
||||
|
||||
$options['dropdown'] = array_merge(
|
||||
$options['dropdown'],
|
||||
[
|
||||
'scope' => isset( $options['scope'] )
|
||||
? $options['scope']
|
||||
: 'opanda',
|
||||
'name' => $this->options['name'] . '__dropdown',
|
||||
]
|
||||
);
|
||||
|
||||
if ( ! isset( $options['colors'] ) ) {
|
||||
$options['colors'] = [];
|
||||
}
|
||||
|
||||
$options['colors'] = array_merge(
|
||||
$options['colors'],
|
||||
[
|
||||
'scope' => isset( $options['scope'] )
|
||||
? $options['scope']
|
||||
: 'opanda',
|
||||
'name' => $this->options['name'] . '__colors',
|
||||
]
|
||||
);
|
||||
|
||||
$this->dropdown = new Wbcr_FactoryForms600_DropdownControl( $options['dropdown'], $form, $provider );
|
||||
$this->colors = new Wbcr_FactoryForms600_RadioColorsControl( $options['colors'], $form, $provider );
|
||||
$this->inner_controls = [ $this->dropdown, $this->colors ];
|
||||
|
||||
$colors = $this->colors->getOption( 'data' );
|
||||
|
||||
if ( empty( $colors ) ) {
|
||||
$dropdown_value = $this->dropdown->getValue();
|
||||
$dOptions = $this->dropdown->getOption( 'data', [] );
|
||||
|
||||
foreach ( $dOptions as $option ) {
|
||||
if ( $option['value'] == $dropdown_value && isset( $option['data']['colors'] ) ) {
|
||||
$colors_options = json_decode( htmlspecialchars_decode( $option['data']['colors'] ) );
|
||||
$this->colors->setOption( 'data', $colors_options );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the html markup of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
?>
|
||||
<script>
|
||||
</script>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<div class="factory-control-row">
|
||||
<div class="factory-dropdown-wrap">
|
||||
<?php $this->dropdown->render(); ?>
|
||||
</div>
|
||||
<div class="factory-colors-wrap">
|
||||
<?php $this->colors->render(); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="factory-picker-target"></div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Dropdown List Control
|
||||
*
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* value => a value to show in the control
|
||||
* default => a default value of the control if the "value" option is not specified
|
||||
* items => a callback to return items or an array of items to select
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_DropdownControl' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_DropdownControl extends Wbcr_FactoryForms600_Control {
|
||||
|
||||
public $type = 'dropdown';
|
||||
|
||||
/**
|
||||
* Returns a set of available items for the list.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function getItems() {
|
||||
$data = $this->getOption( 'data', [] );
|
||||
|
||||
// if the data options is a valid callback for an object method
|
||||
if ( ( is_array( $data ) && count( $data ) == 2 && is_object( $data[0] ) ) || is_string( $data ) ) {
|
||||
|
||||
return call_user_func( $data );
|
||||
}
|
||||
|
||||
// if the data options is an array of values
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if the data should be loaded via ajax.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return bool
|
||||
*/
|
||||
protected function isAjax() {
|
||||
|
||||
$data = $this->getOption( 'data', [] );
|
||||
|
||||
return is_array( $data ) && isset( $data['ajax'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the html markup of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
$way = $this->getOption( 'way', 'default' );
|
||||
$this->addHtmlData( 'way', $way );
|
||||
|
||||
$events_data = $this->getOption( 'events', [] );
|
||||
|
||||
if ( ! empty( $events_data ) ) {
|
||||
$events_string_data = json_encode( $events_data );
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
|
||||
$value = $this->getValue();
|
||||
|
||||
if ( empty( $value ) || ( is_array( $value ) && empty( $value[0] ) ) ) {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
if ( ! empty( $value ) && isset( $events_data[ $value ] ) && is_array( $events_data[ $value ] ) ) {
|
||||
$print_styles = '';
|
||||
foreach ( $events_data[ $value ] as $eventName => $selectors ) {
|
||||
if ( $eventName == 'hide' ) {
|
||||
$print_styles .= $selectors . '{display:none;}';
|
||||
} elseif ( $eventName == 'show' ) {
|
||||
$print_styles .= $selectors . '{display:block;}';
|
||||
}
|
||||
}
|
||||
|
||||
echo '<style>' . esc_html( $print_styles ) . '</style>';
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
// Onepress factory dropdown control events
|
||||
if( void 0 === window.factory_dropdown_control_events_data ) {
|
||||
window.factory_dropdown_control_events_data = {};
|
||||
}
|
||||
window.factory_dropdown_control_events_data['<?php echo esc_attr( $name_on_form ); ?>'] = <?php echo $events_string_data; ?>;
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
if ( $this->isAjax() ) {
|
||||
|
||||
$data = $this->getOption( 'data', [] );
|
||||
$ajax_id = 'factory-dropdown-' . rand( 1000000, 9999999 );
|
||||
|
||||
$value = $this->getValue();
|
||||
|
||||
if ( empty( $value ) || ( is_array( $value ) && empty( $value[0] ) ) ) {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="factory-ajax-loader <?php echo esc_attr( $ajax_id ) . '-loader'; ?>"></div>
|
||||
<script>
|
||||
window['<?php echo $ajax_id; ?>'] = {
|
||||
'loader': '.<?php echo esc_attr( $ajax_id ) . '-loader'; ?>',
|
||||
'url': '<?php echo esc_url( $data['url'] ); ?>',
|
||||
'data': <?php echo json_encode( $data['data'] ); ?>,
|
||||
'selected': '<?php echo esc_attr( $value ); ?>',
|
||||
'empty_list': '<?php echo esc_attr( $this->getOption( 'empty', __( 'The list is empty.', 'robin-image-optimizer' ) ) ); ?>'
|
||||
};
|
||||
</script>
|
||||
<?php
|
||||
|
||||
$this->addHtmlData( 'ajax', true );
|
||||
$this->addHtmlData( 'ajax-data-id', $ajax_id );
|
||||
$this->addCssClass( 'factory-hidden' );
|
||||
}
|
||||
|
||||
if ( 'buttons' == $way ) {
|
||||
$this->buttonsHtml();
|
||||
} elseif ( 'ddslick' == $way ) {
|
||||
$this->ddslickHtml();
|
||||
} else {
|
||||
$this->defaultHtml();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the Buttons Dropdown.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
protected function buttonsHtml() {
|
||||
$items = $this->getItems();
|
||||
$value = $this->getValue();
|
||||
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
|
||||
$this->addCssClass( 'factory-buttons-way' );
|
||||
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<div class="btn-group factory-buttons-group">
|
||||
<?php foreach ( $items as $item ) { ?>
|
||||
<button type="button" class="btn btn-default btn-small factory-<?php echo esc_attr( $item[0] ); ?>
|
||||
<?php
|
||||
if ( $value == $item[0] ) {
|
||||
echo 'active';
|
||||
}
|
||||
?>
|
||||
" data-value="<?php echo esc_attr( $item[0] ); ?>"><?php echo esc_attr( $item[1] ); ?></button>
|
||||
<?php } ?>
|
||||
<input type="hidden" id="<?php echo esc_attr( $name_on_form ); ?>" class="factory-result" name="<?php echo esc_attr( $name_on_form ); ?>" value="<?php echo esc_attr( $value ); ?>"/>
|
||||
</div>
|
||||
<div class="factory-hints">
|
||||
<?php foreach ( $items as $item ) { ?>
|
||||
<?php if ( isset( $item[2] ) ) { ?>
|
||||
<div class="factory-hint factory-hint-<?php echo esc_attr( $item[0] ); ?>"
|
||||
<?php
|
||||
if ( $value !== $item[0] ) {
|
||||
echo 'style="display: none;"';
|
||||
}
|
||||
?>
|
||||
><?php echo wp_kses( $item[2], 'default' ); ?></div>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the ddSlick dropbox.
|
||||
*
|
||||
* @since 3.2.8
|
||||
* @return void
|
||||
*/
|
||||
protected function ddslickHtml() {
|
||||
$items = $this->getItems();
|
||||
$value = $this->getValue();
|
||||
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
|
||||
$this->addCssClass( 'factory-ddslick-way' );
|
||||
$this->addHtmlData( 'name', $name_on_form );
|
||||
|
||||
$this->addHtmlData( 'width', $this->getOption( 'width', 300 ) );
|
||||
$this->addHtmlData( 'align', $this->getOption( 'imagePosition', 'right' ) );
|
||||
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<script>
|
||||
//Dropdown plugin data
|
||||
var factory_<?php echo esc_attr( $name_on_form ); ?>_data = [
|
||||
<?php foreach ( $items as $item ) { ?>
|
||||
{
|
||||
text: "<?php echo esc_html( $item['title'] ); ?>",
|
||||
value: "<?php echo esc_html( $item['value'] ); ?>",
|
||||
selected:
|
||||
<?php
|
||||
if ( $value == $item['value'] ) {
|
||||
echo 'true';
|
||||
} else {
|
||||
echo 'false';
|
||||
}
|
||||
?>
|
||||
,
|
||||
description: "<?php echo( isset( $item['hint'] ) ? wp_kses( $item['hint'], 'default' ) : '' ); ?>",
|
||||
imageSrc: "<?php echo( isset( $item['image'] ) ? esc_url( $item['image'] ) : '' ); ?>",
|
||||
imageHoverSrc: "<?php echo( isset( $item['hover'] ) ? esc_url( $item['hover'] ) : '' ); ?>"
|
||||
},
|
||||
<?php } ?>
|
||||
];
|
||||
</script>
|
||||
<div class="factory-ddslick"></div>
|
||||
<input type="hidden" class="factory-result" id="<?php echo esc_attr( $name_on_form ); ?>" name="<?php echo esc_attr( $name_on_form ); ?>" value="<?php echo esc_attr( $value ); ?>"/>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the standart dropdown.
|
||||
*
|
||||
* @since 1.3.1
|
||||
* @return void
|
||||
*/
|
||||
protected function defaultHtml() {
|
||||
|
||||
$items = $this->getItems();
|
||||
$value = esc_attr( $this->getValue() );
|
||||
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
|
||||
$this->addHtmlAttr( 'id', $name_on_form );
|
||||
$this->addHtmlAttr( 'name', $name_on_form );
|
||||
$this->addCssClass( 'form-control' );
|
||||
|
||||
$hasGroups = $this->getOption( 'hasGroups', true );
|
||||
$has_hints = $this->getOption( 'hasHints', false );
|
||||
|
||||
foreach ( $items as $item ) {
|
||||
if ( isset( $item['type'] ) && $item['type'] == 'group' && ! empty( $item['items'] ) ) {
|
||||
foreach ( (array) $item['items'] as $group_item ) {
|
||||
$is_hint = ( isset( $group_item['hint'] ) && ! empty( $group_item['hint'] ) ) || ( isset( $group_item[2] ) && ! empty( $group_item[2] ) );
|
||||
if ( ! $is_hint ) {
|
||||
continue;
|
||||
}
|
||||
$has_hints = true;
|
||||
break;
|
||||
}
|
||||
if ( $has_hints ) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$is_hint = ( isset( $item['hint'] ) && ! empty( $item['hint'] ) ) || ( isset( $item[2] ) && ! $item[2] );
|
||||
if ( ! $is_hint ) {
|
||||
continue;
|
||||
}
|
||||
$has_hints = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$is_empty = $this->isAjax() || empty( $items );
|
||||
// translators: empty is used as a placeholder for empty dropdown list.
|
||||
$empty_list = $this->getOption( 'empty', '- ' . __( 'empty', 'robin-image-optimizer' ) . ' -' );
|
||||
|
||||
?>
|
||||
<select <?php $this->attrs(); ?>>
|
||||
<?php if ( $is_empty ) { ?>
|
||||
<option value='' class="factory-empty-option">
|
||||
<?php echo $empty_list; ?>
|
||||
</option>
|
||||
<?php } else { ?>
|
||||
<?php $this->printItems( $items, $value ); ?>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<?php if ( $has_hints ) { ?>
|
||||
<div class="factory-hints">
|
||||
<?php
|
||||
foreach ( $items as $item ) {
|
||||
if ( isset( $item['type'] ) && $item['type'] == 'group' && ! empty( $item['items'] ) ) {
|
||||
foreach ( (array) $item['items'] as $group_item ) {
|
||||
|
||||
$hint = isset( $group_item[2] ) ? wp_kses( $group_item[2], 'default' ) : null;
|
||||
$hint = isset( $group_item['hint'] ) ? wp_kses( $group_item['hint'], 'default' ) : $hint;
|
||||
|
||||
$value = isset( $group_item[0] ) ? esc_attr( $group_item[0] ) : null;
|
||||
$value = isset( $group_item['value'] ) ? esc_attr( $group_item['value'] ) : $value;
|
||||
|
||||
$this->printHint( $hint, $value, $value !== $value );
|
||||
}
|
||||
} else {
|
||||
$hint = isset( $item[2] ) ? esc_attr( $item[2] ) : null;
|
||||
$hint = isset( $item['hint'] ) ? esc_attr( $item['hint'] ) : $hint;
|
||||
|
||||
$value = isset( $item[0] ) ? esc_attr( $item[0] ) : null;
|
||||
$value = isset( $item['value'] ) ? esc_attr( $item['value'] ) : $value;
|
||||
|
||||
$this->printHint( $hint, $value, $value !== $value );
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Print single hint markup
|
||||
*
|
||||
* @since 4.1.0
|
||||
*
|
||||
* @param string $hint
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function printHint( $hint, $name, $is_visible = false ) {
|
||||
|
||||
if ( ! empty( $hint ) ) {
|
||||
$styles = ( $is_visible ) ? 'style="display: none;"' : '';
|
||||
|
||||
?>
|
||||
<div style="display: none;" class="factory-hint factory-hint-<?php echo esc_attr( $name ); ?>"<?php echo $styles; ?>><?php echo $hint; ?></div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $items
|
||||
* @param null $selected
|
||||
*/
|
||||
protected function printItems( $items, $selected = null ) {
|
||||
|
||||
foreach ( (array) $items as $item ) {
|
||||
|
||||
$subitems = [];
|
||||
$data = null;
|
||||
|
||||
// this item is an associative array
|
||||
if ( isset( $item['type'] ) || isset( $item['value'] ) ) {
|
||||
|
||||
$type = isset( $item['type'] ) ? $item['type'] : 'option';
|
||||
|
||||
if ( 'group' === $type ) {
|
||||
$subitems = isset( $item['items'] ) ? $item['items'] : [];
|
||||
}
|
||||
|
||||
$value = isset( $item['value'] ) ? $item['value'] : '';
|
||||
$title = isset( $item['title'] ) ? $item['title'] : '- ' . __( 'empty', 'robin-image-optimizer' ) . ' -';
|
||||
|
||||
$data = isset( $item['data'] ) ? $item['data'] : null;
|
||||
} else {
|
||||
|
||||
$type = ( count( $item ) == 3 && $item[0] === 'group' ) ? 'group' : 'option';
|
||||
if ( 'group' === $type ) {
|
||||
$subitems = $item[2];
|
||||
}
|
||||
|
||||
$title = $item[1];
|
||||
$value = esc_attr( $item[0] );
|
||||
}
|
||||
|
||||
if ( 'group' === $type ) {
|
||||
?>
|
||||
<optgroup label="<?php echo $title; ?>">
|
||||
<?php $this->printItems( $subitems, $selected ); ?>
|
||||
</optgroup>
|
||||
<?php
|
||||
} else {
|
||||
|
||||
$attr = ( $selected == $value ) ? 'selected="selected"' : '';
|
||||
|
||||
$strData = '';
|
||||
if ( ! empty( $data ) ) {
|
||||
|
||||
foreach ( $data as $key => $values ) {
|
||||
$strData = $strData . ' data-' . $key . '="' . ( is_array( $values ) ? implode( ',', $values ) : $values ) . '"';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<option value='<?php echo $value; ?>' <?php echo $attr; ?> <?php echo $strData; ?>>
|
||||
<?php echo $title; ?>
|
||||
</option>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Dropdown List Control
|
||||
*
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* value => a value to show in the control
|
||||
* default => a default value of the control if the "value" option is not specified
|
||||
* items => a callback to return items or an array of items to select
|
||||
*
|
||||
* @package core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_FontControl' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_FontControl extends Wbcr_FactoryForms600_ComplexControl {
|
||||
|
||||
public $type = 'font';
|
||||
|
||||
public function __construct( $options, $form, $provider = null ) {
|
||||
parent::__construct( $options, $form, $provider );
|
||||
|
||||
$option_font_size = [
|
||||
'name' => $this->options['name'] . '__size',
|
||||
'units' => $this->options['units'],
|
||||
'default' => isset( $this->options['default'] )
|
||||
? $this->options['default']['size']
|
||||
: null,
|
||||
];
|
||||
|
||||
$option_font_family = [
|
||||
'name' => $this->options['name'] . '__family',
|
||||
'data' => $this->getFonts(),
|
||||
'default' => isset( $this->options['default'] )
|
||||
? $this->options['default']['family']
|
||||
: null,
|
||||
];
|
||||
|
||||
$optionFontColor = [
|
||||
'name' => $this->options['name'] . '__color',
|
||||
'default' => isset( $this->options['default'] )
|
||||
? $this->options['default']['color']
|
||||
: null,
|
||||
'pickerTarget' => '.factory-control-' . $this->options['name'] . ' .factory-picker-target',
|
||||
];
|
||||
|
||||
$this->size = new Wbcr_FactoryForms600_IntegerControl( $option_font_size, $form, $provider );
|
||||
$this->family = new Wbcr_FactoryForms600_DropdownControl( $option_font_family, $form, $provider );
|
||||
$this->color = new Wbcr_FactoryForms600_ColorControl( $optionFontColor, $form, $provider );
|
||||
|
||||
$this->innerControls = [ $this->family, $this->size, $this->color ];
|
||||
}
|
||||
|
||||
public function getFonts() {
|
||||
|
||||
$fonts = $this->getDefaultFonts();
|
||||
|
||||
$fonts = apply_filters( 'wbcr_factory_forms_600_fonts', $fonts );
|
||||
$fonts = apply_filters( 'wbcr_factory_forms_600_fonts-' . $this->options['name'], $fonts );
|
||||
|
||||
return $fonts;
|
||||
}
|
||||
|
||||
public function getDefaultFonts() {
|
||||
|
||||
$fonts = [
|
||||
|
||||
[ 'inherit', '(' . __( 'Use default website font', 'robin-image-optimizer' ) . ')' ],
|
||||
[
|
||||
'group',
|
||||
__( 'Sans Serif:', 'robin-image-optimizer' ),
|
||||
[
|
||||
[ 'Arial, "Helvetica Neue", Helvetica, sans-serif', 'Arial' ],
|
||||
[ '"Arial Black", "Arial Bold", Gadget, sans-serif', 'Arial Black' ],
|
||||
[ '"Arial Narrow", Arial, sans-serif', 'Arial Narrow' ],
|
||||
[
|
||||
'"Arial Rounded MT Bold", "Helvetica Rounded", Arial, sans-serif',
|
||||
'Arial Rounded MT Bold',
|
||||
],
|
||||
[
|
||||
'"Avant Garde", Avantgarde, "Century Gothic", CenturyGothic, "AppleGothic", sans-serif',
|
||||
'Avant Garde',
|
||||
],
|
||||
[ 'Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif', 'Calibri' ],
|
||||
[ 'Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif', 'Candara' ],
|
||||
[ '"Century Gothic", CenturyGothic, AppleGothic, sans-serif', 'Century Gothic' ],
|
||||
[
|
||||
'"Franklin Gothic Medium", "Franklin Gothic", "ITC Franklin Gothic", Arial, sans-serif',
|
||||
'Franklin Gothic Medium',
|
||||
],
|
||||
[ 'Futura, "Trebuchet MS", Arial, sans-serif', 'Futura' ],
|
||||
[ 'Geneva, Tahoma, Verdana, sans-serif', 'Geneva' ],
|
||||
[ '"Gill Sans", "Gill Sans MT", Calibri, sans-serif', 'Gill Sans' ],
|
||||
[ '"Helvetica Neue", Helvetica, Arial, sans-serif', 'Helvetica' ],
|
||||
[
|
||||
'Impact, Haettenschweiler, "Franklin Gothic Bold", Charcoal, "Helvetica Inserat", "Bitstream Vera Sans Bold", "Arial Black", sans serif',
|
||||
'Impact',
|
||||
],
|
||||
[
|
||||
'"Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif',
|
||||
'Lucida Grande',
|
||||
],
|
||||
[ 'Optima, Segoe, "Segoe UI", Candara, Calibri, Arial, sans-serif', 'Optima' ],
|
||||
[
|
||||
'"Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif',
|
||||
'Segoe UI',
|
||||
],
|
||||
[
|
||||
'Montserrat, "Segoe UI", "Helvetica Neue", Arial, sans-serif',
|
||||
'Montserrat',
|
||||
],
|
||||
[ 'Tahoma, Verdana, Segoe, sans-serif', 'Tahoma' ],
|
||||
[
|
||||
'"Trebuchet MS", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif',
|
||||
'Trebuchet MS',
|
||||
],
|
||||
[ 'Verdana, Geneva, sans-serif', 'Verdana' ],
|
||||
],
|
||||
],
|
||||
[
|
||||
'group',
|
||||
__( 'Serif:', 'robin-image-optimizer' ),
|
||||
[
|
||||
[
|
||||
'Baskerville, "Baskerville Old Face", "Hoefler Text", Garamond, "Times New Roman", serif',
|
||||
'Baskerville',
|
||||
],
|
||||
[ '"Big Caslon", "Book Antiqua", "Palatino Linotype", Georgia, serif', 'Big Caslon' ],
|
||||
[
|
||||
'"Bodoni MT", Didot, "Didot LT STD", "Hoefler Text", Garamond, "Times New Roman", serif',
|
||||
'Bodoni MT',
|
||||
],
|
||||
[
|
||||
'"Book Antiqua", Palatino, "Palatino Linotype", "Palatino LT STD", Georgia, serif',
|
||||
'Book Antiqua',
|
||||
],
|
||||
[
|
||||
'"Calisto MT", "Bookman Old Style", Bookman, "Goudy Old Style", Garamond, "Hoefler Text", "Bitstream Charter", Georgia, serif',
|
||||
'Calisto MT',
|
||||
],
|
||||
[ 'Cambria, Georgia, serif', 'Cambria' ],
|
||||
[ 'Didot, "Didot LT STD", "Hoefler Text", Garamond, "Times New Roman", serif', 'Didot' ],
|
||||
[
|
||||
'Garamond, Baskerville, "Baskerville Old Face", "Hoefler Text", "Times New Roman", serif',
|
||||
'Garamond',
|
||||
],
|
||||
[ 'Georgia, Times, "Times New Roman", serif', 'Georgia' ],
|
||||
[
|
||||
'"Goudy Old Style", Garamond, "Big Caslon", "Times New Roman", serif',
|
||||
'Goudy Old Style',
|
||||
],
|
||||
[
|
||||
'"Hoefler Text", "Baskerville old face", Garamond, "Times New Roman", serif',
|
||||
'Hoefler Text',
|
||||
],
|
||||
[ '"Lucida Bright", Georgia, serif', 'Lucida Bright' ],
|
||||
[
|
||||
'Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif',
|
||||
'Palatino',
|
||||
],
|
||||
[
|
||||
'Perpetua, Baskerville, "Big Caslon", "Palatino Linotype", Palatino, "URW Palladio L", "Nimbus Roman No9 L", serif',
|
||||
'Perpetua',
|
||||
],
|
||||
[
|
||||
'Rockwell, "Courier Bold", Courier, Georgia, Times, "Times New Roman", serif',
|
||||
'Rockwell',
|
||||
],
|
||||
[ '"Rockwell Extra Bold", "Rockwell Bold", monospace', 'Rockwell Extra Bold' ],
|
||||
[
|
||||
'TimesNewRoman, "Times New Roman", Times, Baskerville, Georgia, serif',
|
||||
'Times New Roman',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'group',
|
||||
__( 'Monospaced:', 'robin-image-optimizer' ),
|
||||
[
|
||||
[ '"Andale Mono", AndaleMono, monospace', 'Andale Mono' ],
|
||||
[ 'Consolas, monaco, monospace', 'Consolas' ],
|
||||
[
|
||||
'"Courier New", Courier, "Lucida Sans Typewriter", "Lucida Typewriter", monospace',
|
||||
'Courier New',
|
||||
],
|
||||
[
|
||||
'"Lucida Console", "Lucida Sans Typewriter", Monaco, "Bitstream Vera Sans Mono", monospace',
|
||||
'Lucida Console',
|
||||
],
|
||||
[
|
||||
'"Lucida Sans Typewriter", "Lucida Console", Monaco, "Bitstream Vera Sans Mono", monospace',
|
||||
'Lucida Sans Typewriter',
|
||||
],
|
||||
[ 'Monaco, Consolas, "Lucida Console", monospace', 'Monaco' ],
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
return $fonts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes \" in the font family value.
|
||||
*
|
||||
* @since 3.1.0
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getValuesToSave() {
|
||||
$values = parent::getValuesToSave();
|
||||
|
||||
$family_key = sanitize_key( $this->options['name'] ) . '__family';
|
||||
$values[ $family_key ] = sanitize_text_field( $values[ $family_key ] );
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
public function beforeControlsHtml() {
|
||||
}
|
||||
|
||||
public function afterControlsHtml() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the html markup of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<div class="factory-control-row">
|
||||
<?php $this->beforeControlsHtml(); ?>
|
||||
|
||||
<div class="factory-family-wrap">
|
||||
<?php $this->family->html(); ?>
|
||||
</div>
|
||||
<div class="factory-size-wrap">
|
||||
<?php $this->size->html(); ?>
|
||||
</div>
|
||||
<div class="factory-color-wrap">
|
||||
<?php $this->color->html(); ?>
|
||||
</div>
|
||||
|
||||
<?php $this->afterControlsHtml(); ?>
|
||||
</div>
|
||||
<div class="factory-picker-target"></div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Dropdown List Control
|
||||
*
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* value => a value to show in the control
|
||||
* default => a default value of the control if the "value" option is not specified
|
||||
* items => a callback to return items or an array of items to select
|
||||
*
|
||||
* @package core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_GoogleFontControl extends Wbcr_FactoryForms600_FontControl {
|
||||
|
||||
public $type = 'google-font';
|
||||
const APIKEY = 'AIzaSyB-3vazYv7Q-5QZA04bmSKFrWcw_VhC40w';
|
||||
|
||||
public function __construct( $options, $form, $provider = null ) {
|
||||
parent::__construct( $options, $form, $provider );
|
||||
$this->addCssClass( 'factory-font' );
|
||||
|
||||
$option_google_font_data = [
|
||||
'name' => $this->options['name'] . '__google_font_data',
|
||||
'cssClass' => 'factory-google-font-data',
|
||||
];
|
||||
|
||||
$this->google_font_data = new Wbcr_FactoryForms600_HiddenControl( $option_google_font_data, $form, $provider );
|
||||
$this->inner_controls[] = $this->google_font_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getDefaultFonts() {
|
||||
|
||||
$cache_fonts = get_transient( 'wbcr_factory_google_fonts' );
|
||||
|
||||
if ( ! empty( $cache_fonts ) ) {
|
||||
return $cache_fonts;
|
||||
}
|
||||
|
||||
$google_fonts = $this->getGoogleFonts();
|
||||
|
||||
$fonts = [
|
||||
[ 'inherit', '(' . __( 'Use default website font', 'robin-image-optimizer' ) . ')' ],
|
||||
];
|
||||
|
||||
$fontsCommon = [
|
||||
'group',
|
||||
__( 'Standard:', 'robin-image-optimizer' ),
|
||||
[
|
||||
|
||||
[ 'Arial, "Helvetica Neue", Helvetica, sans-serif', 'Arial' ],
|
||||
[ '"Helvetica Neue", Helvetica, Arial, sans-serif', 'Helvetica' ],
|
||||
[ 'Tahoma, Verdana, Segoe, sans-serif', 'Tahoma' ],
|
||||
[ 'Verdana, Geneva, sans-serif', 'Verdana' ],
|
||||
|
||||
],
|
||||
];
|
||||
|
||||
$fontsGoogleFonts = [ 'group', __( 'Google Fonts:', 'robin-image-optimizer' ), [] ];
|
||||
|
||||
foreach ( $google_fonts->items as $item ) {
|
||||
|
||||
$alt_font = $item->category;
|
||||
if ( in_array( $alt_font, [ 'handwriting', 'display' ] ) ) {
|
||||
$alt_font = 'serif';
|
||||
}
|
||||
|
||||
$listItem = [
|
||||
'title' => $item->family,
|
||||
'value' => $item->family . ', ' . $item->category,
|
||||
'hint' => '<em>Google Font</em>',
|
||||
'data' => [
|
||||
'google-font' => true,
|
||||
'family' => $item->family,
|
||||
'variants' => $item->variants,
|
||||
'subsets' => $item->subsets,
|
||||
],
|
||||
];
|
||||
|
||||
$fontsGoogleFonts[2][] = $listItem;
|
||||
}
|
||||
|
||||
$fonts[] = $fontsCommon;
|
||||
$fonts[] = $fontsGoogleFonts;
|
||||
|
||||
set_transient( 'wbcr_factory_google_fonts', $fonts, 60 * 60 * 6 );
|
||||
|
||||
return $fonts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|mixed|object
|
||||
*/
|
||||
protected function getGoogleFonts() {
|
||||
|
||||
$body = get_transient( 'wbcr_factory_google_fonts_raw' );
|
||||
if ( ! empty( $body ) ) {
|
||||
return $body;
|
||||
}
|
||||
|
||||
$response = wp_remote_get( sprintf( 'https://www.googleapis.com/webfonts/v1/webfonts?key=%s', self::APIKEY ) );
|
||||
|
||||
$this->error = false;
|
||||
$this->defailed_error = false;
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
|
||||
$this->error = __( 'Unable to retrieve the list of Google Fonts.', 'robin-image-optimizer' );
|
||||
$this->defailed_error = $response->get_error_message();
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
if ( ! isset( $response['body'] ) ) {
|
||||
|
||||
$this->error = __( 'Invalid response from the Google Fonts API.', 'robin-image-optimizer' );
|
||||
$this->defailed_error = $response['body'];
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
$body = json_decode( $response['body'] );
|
||||
|
||||
if ( empty( $body->items ) ) {
|
||||
|
||||
$this->error = __( 'Unexpected error. The list of Google Fonts is empty.', 'robin-image-optimizer' );
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
set_transient( 'wbcr_factory_google_fonts_raw', $body, 60 * 60 * 6 );
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
public function afterControlsHtml() {
|
||||
?>
|
||||
<?php $this->google_font_data->html(); ?>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Gradient picker Control
|
||||
*
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* title => Заголовок
|
||||
* colors => массив цветов для градиента
|
||||
* Пример: array("#000 0% 0.5", "#e70303 100% 1")
|
||||
* filldirection => Направление градиента(top, left)
|
||||
* Пример: 90deg
|
||||
* value => a value to show in the control
|
||||
* default => a default value of the control if the "value" option is not specified
|
||||
*
|
||||
* @package core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_GradientControl' ) ) {
|
||||
class Wbcr_FactoryForms600_GradientControl extends Wbcr_FactoryForms600_Control {
|
||||
|
||||
public $type = 'gradient';
|
||||
|
||||
/**
|
||||
* Shows the html markup of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
$name = $this->getNameOnForm();
|
||||
$value = esc_attr( $this->getValue() );
|
||||
|
||||
if ( ! empty( $value ) ) {
|
||||
|
||||
$values = json_decode( stripcslashes( htmlspecialchars_decode( $value ) ) );
|
||||
|
||||
$points = '';
|
||||
|
||||
foreach ( $values->color_points as $split_values ) {
|
||||
$points .= $split_values . ',';
|
||||
}
|
||||
|
||||
$points = rtrim( $points, ',' );
|
||||
|
||||
$this->addHtmlData( 'points', $points );
|
||||
$this->addHtmlData( 'directions', $values->filldirection );
|
||||
} else {
|
||||
$this->addHtmlData( 'directions', 'top' );
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
if( !window.factory ) {
|
||||
window.factory = {};
|
||||
}
|
||||
if( !window.factory.res ) {
|
||||
window.factory.res = {};
|
||||
}
|
||||
factory.res.resVertical = '<?php _e( 'vertical', 'robin-image-optimizer' ); ?>';
|
||||
factory.res.resHorizontal = '<?php _e( 'horizontal', 'robin-image-optimizer' ); ?>';
|
||||
</script>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<div class="factory-gradient-picker">
|
||||
<ul class="gradientPicker-pallets">
|
||||
<li class="factory-preset-gradient factory-primary-gradient" data-primary="#1bbc9d" data-secondary="#16a086"></li>
|
||||
<li class="factory-preset-gradient factory-primary-gradient" data-primary="#2fcc71" data-secondary="#27ae61"></li>
|
||||
<li class="factory-preset-gradient factory-primary-gradient" data-primary="#3598dc" data-secondary="#2a80b9"></li>
|
||||
<li class="factory-preset-gradient factory-primary-gradient" data-primary="#9c59b8" data-secondary="#8f44ad"></li>
|
||||
<li class="factory-preset-gradient factory-primary-gradient" data-primary="#34495e" data-secondary="#2d3e50"></li>
|
||||
<li class="factory-preset-gradient factory-primary-gradient" data-primary="#f1c40f" data-secondary="#f49c14"></li>
|
||||
<li class="factory-preset-gradient factory-primary-gradient" data-primary="#e84c3d" data-secondary="#c1392b"></li>
|
||||
<li class="factory-preset-gradient factory-primary-gradient" data-primary="#ecf0f1" data-secondary="#bec3c7"></li>
|
||||
</ul>
|
||||
<canvas class='gradientPicker-preview'></canvas>
|
||||
<div class='factory-points'></div>
|
||||
<div class='factory-color-picker-container'>
|
||||
<div class="factory-slider-container">
|
||||
<div class="factory-slider">
|
||||
<input type="text" class="factory-input-text factory-color-hex"/>
|
||||
|
||||
<div class="factory-bar"></div>
|
||||
<div class="factory-visible-value">100%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="factory-color-picker"></div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" id="<?php echo esc_attr( $name ); ?>" class="factory-result" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>">
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Hidden Input Control
|
||||
*
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* value => a value to show in the control
|
||||
* default => a default value of the control if the "value" option is not specified
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_HiddenControl' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_HiddenControl extends Wbcr_FactoryForms600_Control {
|
||||
|
||||
public $type = 'hidden';
|
||||
|
||||
/**
|
||||
* Shows the html markup of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
$value = esc_attr( $this->getValue() );
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
|
||||
$this->addHtmlAttr( 'id', $name_on_form );
|
||||
$this->addHtmlAttr( 'name', $name_on_form );
|
||||
$this->addHtmlAttr( 'value', $value );
|
||||
$this->addHtmlAttr( 'type', 'hidden' );
|
||||
|
||||
?>
|
||||
<input <?php $this->attrs(); ?>/>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains the class of Tab Control Holder.
|
||||
*
|
||||
* @package core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_AccordionItemHolder' ) ) {
|
||||
|
||||
/**
|
||||
* Tab Control Holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_AccordionItemHolder extends Wbcr_FactoryForms600_Holder {
|
||||
|
||||
/**
|
||||
* A holder type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'accordion-item';
|
||||
|
||||
/**
|
||||
* Here we should render a beginning html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRendering() {
|
||||
?>
|
||||
<h3><?php echo $this->options['title']; ?></h3>
|
||||
<div class="factory-accordion-item">
|
||||
<div class="inner-factory-accordion-item">
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we should render an end html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function afterRendering() {
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains the class of Tab Control Holder.
|
||||
*
|
||||
* @package core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_AccordionHolder' ) ) {
|
||||
/**
|
||||
* Tab Control Holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_AccordionHolder extends Wbcr_FactoryForms600_Holder {
|
||||
|
||||
/**
|
||||
* A holder type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'accordion';
|
||||
|
||||
/**
|
||||
* Here we should render a beginning html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRendering() {
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we should render an end html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function afterRendering() {
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains the class of Columns Holder.
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_ColumnsHolder' ) ) {
|
||||
/**
|
||||
* Columns Holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_ColumnsHolder extends Wbcr_FactoryForms600_Holder {
|
||||
|
||||
/**
|
||||
* A holder type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'columns';
|
||||
|
||||
public function __construct( $options, $form ) {
|
||||
$columns_items = [];
|
||||
|
||||
// calculates the number of columns
|
||||
|
||||
$this->columns_count = 0;
|
||||
|
||||
foreach ( $options['items'] as $item ) {
|
||||
$i = ( ! isset( $item['column'] )
|
||||
? 1
|
||||
: intval( $item['column'] ) ) - 1;
|
||||
$columns_items[ $i ][] = $item;
|
||||
|
||||
if ( $i > $this->columns_count ) {
|
||||
$this->columns_count = $i + 1;
|
||||
}
|
||||
}
|
||||
// calculates the number of rows
|
||||
|
||||
$this->rows_count = 0;
|
||||
foreach ( $columns_items as $items ) {
|
||||
$count = count( $items );
|
||||
if ( $count > $this->rows_count ) {
|
||||
$this->rows_count = $count;
|
||||
}
|
||||
}
|
||||
|
||||
// creates elements
|
||||
|
||||
parent::__construct( $options, $form );
|
||||
|
||||
// groups the created by columns
|
||||
|
||||
$element_index = 0;
|
||||
$this->columns = [];
|
||||
|
||||
foreach ( $columns_items as $column_index => $columnItems ) {
|
||||
$count = count( $columnItems );
|
||||
for ( $k = 0; $k < $count; $k++ ) {
|
||||
$this->columns[ $column_index ][] = $this->elements[ $element_index ];
|
||||
++$element_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function render() {
|
||||
$this->beforeRendering();
|
||||
|
||||
for ( $n = 0; $n < $this->rows_count; $n++ ) {
|
||||
|
||||
$this->form->layout->startRow( $n, $this->rows_count );
|
||||
|
||||
for ( $i = 0; $i < $this->columns_count; $i++ ) {
|
||||
$control = $this->columns[ $i ][ $n ];
|
||||
$this->form->layout->startColumn( $control, $i, $this->columns_count );
|
||||
$this->columns[ $i ][ $n ]->render();
|
||||
$this->form->layout->endColumn( $control, $i, $this->columns_count );
|
||||
}
|
||||
|
||||
$this->form->layout->endRow( $n, $this->rows_count );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains the class of Tab Control Holder.
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_ControlGroupItem' ) ) {
|
||||
|
||||
/**
|
||||
* Tab Control Holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_ControlGroupItem extends Wbcr_FactoryForms600_Holder {
|
||||
|
||||
/**
|
||||
* A holder type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'control-group-item';
|
||||
|
||||
|
||||
/**
|
||||
* Here we should render a beginning html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRendering() {
|
||||
$this->addCssClass( 'control-group-item' );
|
||||
$this->addCssClass( 'factory-control-group-item-' . $this->options['name'] );
|
||||
|
||||
if ( $this->parent->getValue() == $this->options['name'] ) {
|
||||
$this->addCssClass( 'current' );
|
||||
|
||||
foreach ( $this->elements as $val ) {
|
||||
$val->setOption( 'isActive', 1 );
|
||||
}
|
||||
} else {
|
||||
foreach ( $this->elements as $val ) {
|
||||
$val->setOption( 'isActive', 0 );
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we should render an end html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function afterRendering() {
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains the class of Tab Control Holder.
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_ControlGroupHolder' ) ) {
|
||||
|
||||
/**
|
||||
* Tab Control Holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_ControlGroupHolder extends Wbcr_FactoryForms600_ControlHolder {
|
||||
|
||||
/**
|
||||
* A holder type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'control-group';
|
||||
|
||||
|
||||
/**
|
||||
* Here we should render a beginning html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRendering() {
|
||||
$name = $this->getNameOnForm();
|
||||
$value = $this->getValue();
|
||||
|
||||
$title = $this->getOption( 'title', null );
|
||||
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<input type="hidden" name="<?php echo $name; ?>" id="<?php echo $name; ?>" class="factory-ui-control-group" value="<?php echo $value; ?>"/>
|
||||
|
||||
<?php if ( $title ) { ?>
|
||||
<strong class="factory-header"><?php echo $title; ?></strong>
|
||||
<?php } ?>
|
||||
|
||||
<ul class="factory-control-group-nav">
|
||||
<?php
|
||||
foreach ( $this->elements as $element ) :
|
||||
|
||||
if ( $element->options['type'] !== 'control-group-item' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$builder = new Wbcr_FactoryForms600_HtmlAttributeBuilder();
|
||||
|
||||
$builder->addCssClass( 'factory-control-group-nav-label' );
|
||||
$builder->addCssClass( 'factory-control-group-nav-label-' . $element->getOption( 'name' ) );
|
||||
$builder->addHtmlData( 'control-id', 'factory-control-group-item-' . $element->getOption( 'name' ) );
|
||||
$builder->addHtmlData( 'control-name', $element->getOption( 'name' ) );
|
||||
|
||||
if ( $value == $element->getOption( 'name' ) ) {
|
||||
$builder->addCssClass( 'current' );
|
||||
}
|
||||
|
||||
?>
|
||||
<li <?php $builder->printAttrs(); ?>><?php $element->title(); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<div class="factory-control-group-body">
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we should render an end html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function afterRendering() {
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains the class of Div Control Holder.
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_DivHolder' ) ) {
|
||||
/**
|
||||
* Div Control Holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_DivHolder extends Wbcr_FactoryForms600_Holder {
|
||||
|
||||
/**
|
||||
* A holder type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'div';
|
||||
|
||||
/**
|
||||
* Here we should render a beginning html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRendering() {
|
||||
|
||||
if ( isset( $this->options['class'] ) ) {
|
||||
$this->addCssClass( $this->options['class'] );
|
||||
}
|
||||
if ( isset( $this->options['id'] ) ) {
|
||||
$this->addHtmlAttr( 'id', $this->options['id'] );
|
||||
}
|
||||
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we should render an end html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function afterRendering() {
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains the class of Group Holder.
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_FormGroupHolder' ) ) {
|
||||
/**
|
||||
* Group Holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_FormGroupHolder extends Wbcr_FactoryForms600_Holder {
|
||||
|
||||
/**
|
||||
* A holder type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'form-group';
|
||||
|
||||
/**
|
||||
* Here we should render a beginning html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRendering() {
|
||||
|
||||
$this->addCssClass( 'factory-form-group-' . $this->getName() );
|
||||
$this->addHtmlAttr( 'id', 'factory-form-group-' . $this->getName() );
|
||||
|
||||
?>
|
||||
<fieldset <?php $this->attrs(); ?>>
|
||||
<?php if ( $this->hasTitle() ) { ?>
|
||||
<legend class='factory-legend'>
|
||||
<p class='factory-title'><?php $this->title(); ?></p>
|
||||
<?php if ( $this->hasHint() ) { ?>
|
||||
<p class='factory-hint'><?php echo $this->hint(); ?></p>
|
||||
<?php } ?>
|
||||
</legend>
|
||||
<?php } ?>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we should render an end html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function afterRendering() {
|
||||
?>
|
||||
</fieldset>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains the class of More Link Holder.
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_MoreLinkHolder' ) ) {
|
||||
|
||||
/**
|
||||
* Collapsed Group Holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_MoreLinkHolder extends Wbcr_FactoryForms600_Holder {
|
||||
|
||||
/**
|
||||
* A holder type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'more-link';
|
||||
|
||||
/**
|
||||
* Here we should render a beginning html of the tab.
|
||||
*
|
||||
* @return void
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function beforeRendering() {
|
||||
$count = isset( $this->options['count'] ) ? $this->options['count'] : 0;
|
||||
|
||||
$id = 'factory-more-link-' . $this->getName();
|
||||
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<div class="form-group">
|
||||
<div class="control-label col-sm-4"></div>
|
||||
<div class="control-group col-sm-8">
|
||||
<a href="#<?php echo $id; ?>" class="factory-more-link-show btn btn-default"><?php $this->title(); ?>
|
||||
(<?php echo $count; ?>)</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class='factory-more-link-content' id="<?php echo $id; ?>" style="display: none;">
|
||||
<a href="#<?php echo $id; ?>" class='factory-more-link-hide'><?php _e( 'hide extra options', 'robin-image-optimizer' ); ?></a>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we should render an end html of the tab.
|
||||
*
|
||||
* @return void
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function afterRendering() {
|
||||
?>
|
||||
</div></div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains the class of Tab Item Control Holder.
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_TabItemHolder' ) ) {
|
||||
/**
|
||||
* Tab Item Control Holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_TabItemHolder extends Wbcr_FactoryForms600_Holder {
|
||||
|
||||
/**
|
||||
* A holder type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'tab-item';
|
||||
|
||||
/**
|
||||
* Here we should render a beginning html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRendering() {
|
||||
|
||||
$this->addCssClass( 'tab-' . $this->getName() );
|
||||
$this->addHtmlAttr( 'id', $this->getName() );
|
||||
|
||||
$this->addCssClass( 'tab-pane' );
|
||||
|
||||
if ( isset( $this->options['isFirst'] ) && $this->options['isFirst'] ) {
|
||||
$this->addCssClass( 'active' );
|
||||
}
|
||||
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we should render an end html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function afterRendering() {
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
/**
|
||||
* The file contains the class of Tab Control Holder.
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_TabHolder' ) ) {
|
||||
|
||||
/**
|
||||
* Tab Control Holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Wbcr_FactoryForms600_TabHolder extends Wbcr_FactoryForms600_Holder {
|
||||
|
||||
/**
|
||||
* A holder type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'tab';
|
||||
|
||||
/**
|
||||
* An align of a tab (horizontal or vertical).
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $align = 'horizontal';
|
||||
|
||||
/**
|
||||
* Creates a new instance of control holder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param mixed[] $options A holder options.
|
||||
* @param FactoryForms600_Form $form A parent form.
|
||||
*/
|
||||
public function __construct( $options, $form ) {
|
||||
parent::__construct( $options, $form );
|
||||
$this->align = isset( $options['align'] )
|
||||
? $options['align']
|
||||
: 'horizontal';
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we should render a beginning html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRendering() {
|
||||
|
||||
$is_first_tab = true;
|
||||
$tab_class = $this->getOption( 'class' );
|
||||
|
||||
if ( ! empty( $tab_class ) ) {
|
||||
$this->addCssClass( $tab_class );
|
||||
}
|
||||
|
||||
$this->addCssClass( 'factory-align-' . $this->align );
|
||||
|
||||
?>
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<div class="factory-headers">
|
||||
<ul class="nav nav-tabs">
|
||||
<?php
|
||||
foreach ( $this->elements as $element ) {
|
||||
if ( $element->options['type'] !== 'tab-item' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tab_icon = '';
|
||||
$has_icon = isset( $element->options['icon'] );
|
||||
|
||||
if ( $has_icon ) {
|
||||
$tab_icon = $element->options['icon'];
|
||||
}
|
||||
|
||||
$builder = new Wbcr_FactoryForms600_HtmlAttributeBuilder();
|
||||
|
||||
$builder->addCssClass( 'factory-tab-item-header' );
|
||||
$builder->addCssClass( 'factory-tab-item-header-' . $element->getName() );
|
||||
|
||||
if ( $has_icon ) {
|
||||
$builder->addCssClass( 'factory-tab-item-header-with-icon' );
|
||||
}
|
||||
if ( $is_first_tab ) {
|
||||
$builder->addCssClass( 'active' );
|
||||
}
|
||||
|
||||
$builder->addHtmlData( 'tab-id', $element->getName() );
|
||||
$is_first_tab = false;
|
||||
|
||||
if ( $has_icon ) {
|
||||
?>
|
||||
<style>
|
||||
.factory-form-tab-item-header-<?php $element->name(); ?> a {
|
||||
background-image: url("<?php echo $tab_icon; ?>");
|
||||
}
|
||||
</style>
|
||||
<?php } ?>
|
||||
<li <?php $builder->printAttrs(); ?>>
|
||||
<a href="#<?php $element->name(); ?>" data-toggle="tab">
|
||||
<?php $element->title(); ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='tab-content factory-bodies'>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we should render an end html of the tab.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function afterRendering() {
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Integer Control
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* way => Тип значения 'slider' - слайдер, 'checkbox-slider' - чекбокс активирует слайдер, по умолчанию input
|
||||
* checkbox => Указывается если, 'way' имеет значение 'checkbox-slider'
|
||||
* Пример:
|
||||
* array(
|
||||
* 'on' => __('Show shadow', 'bizpanda'),
|
||||
* 'off' => __('Hide shadow', 'bizpanda'),
|
||||
* )
|
||||
* title => Заголовок контрола
|
||||
* slider-title => Заголовок слайдера( Только если 'way' имеет значение 'checkbox-slider' )
|
||||
* range => Диапазон значений, указывается если 'way' имеет значение 'slider' или 'checkbox-slider'
|
||||
* Пример: array(0,100)
|
||||
* units => Единицы измерения(px,pt,em,%)
|
||||
* isActive => Включение, отключение поля
|
||||
* value => a value to show in the control
|
||||
* default => a default value of the control if the "value" option is not specified
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_IntegerControl' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_IntegerControl extends Wbcr_FactoryForms600_Control {
|
||||
|
||||
public $type = 'integer';
|
||||
|
||||
/**
|
||||
* Converting string to integer.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return integer
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
$name = $this->getNameOnForm();
|
||||
$value = esc_attr( $this->getValue() );
|
||||
$step = 1;
|
||||
$range = $checkbox = [];
|
||||
$is_active = $this->getOption( 'isActive', 1 );
|
||||
$unit = esc_attr( $this->getOption( 'units' ) );
|
||||
|
||||
$way = $this->getOption( 'way' );
|
||||
|
||||
if ( empty( $way ) ) {
|
||||
$way = 'text';
|
||||
}
|
||||
|
||||
$has_slider = false;
|
||||
|
||||
if ( in_array( $way, [ 'slider', 'checkbox-slider' ] ) ) {
|
||||
$range = $this->getOption( 'range', [ 0, 99 ] );
|
||||
$slider_title = $this->getOption( 'slider-title' );
|
||||
$checkbox = $this->getOption( 'checkbox' );
|
||||
$step = $this->getOption( 'step', 1 );
|
||||
$has_slider = true;
|
||||
}
|
||||
|
||||
$this->addCssClass( 'factory-way-' . $way );
|
||||
|
||||
if ( $has_slider ) {
|
||||
$this->addCssClass( 'factory-has-slider' );
|
||||
}
|
||||
?>
|
||||
|
||||
<div <?php $this->attrs(); ?>>
|
||||
<?php if ( $has_slider ) { ?>
|
||||
|
||||
<?php if ( 'checkbox-slider' == $way ) { ?>
|
||||
|
||||
<div>
|
||||
<label for="<?php echo esc_attr( $name ); ?>_checker">
|
||||
<?php
|
||||
echo $is_active
|
||||
? $checkbox['off']
|
||||
: $checkbox['on'];
|
||||
?>
|
||||
</label><br>
|
||||
<input type="checkbox" id="<?php echo esc_attr( $name ); ?>_checker" class="factory-checkbox" name="<?php echo esc_attr( $name ); ?>_checker"
|
||||
<?php
|
||||
echo $is_active
|
||||
? 'checked'
|
||||
: ''
|
||||
?>
|
||||
>
|
||||
</div>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<div
|
||||
data-units="<?php echo esc_attr( $unit ); ?>"
|
||||
data-range-start="<?php echo esc_attr( $range[0] ); ?>"
|
||||
data-range-end="<?php echo esc_attr( $range[1] ); ?>"
|
||||
data-step="<?php echo esc_attr( $step ); ?>"
|
||||
<?php
|
||||
echo ! $is_active
|
||||
? ' style="display:none;"'
|
||||
: ''
|
||||
?>
|
||||
class="factory-slider-container factory-slider-container-<?php echo esc_attr( $name ); ?>">
|
||||
<?php if ( ! empty( $slider_title ) ) : ?>
|
||||
<label class="factory-title">
|
||||
<?php echo esc_html( $this->getOption( 'slider-title' ) ); ?>
|
||||
</label>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="factory-slider">
|
||||
<div class="factory-bar"></div>
|
||||
<span class="factory-visible-value">
|
||||
<?php echo esc_html( $value ); ?><?php echo esc_html( $unit ); ?>
|
||||
</span>
|
||||
</div>
|
||||
<input type="hidden" name="<?php echo esc_attr( $name ); ?>" class="factory-result" value="<?php echo esc_attr( $value ); ?>"/>
|
||||
</div>
|
||||
|
||||
<?php } else { ?>
|
||||
|
||||
<input type="number" id="<?php echo esc_attr( $name ); ?>" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>" class="factory-input-text"/>
|
||||
<span class="factory-units"><?php echo esc_html( $unit ); ?></span>
|
||||
|
||||
<?php } ?>
|
||||
</div><!-- .factory-integer -->
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Форматирует значение без единиц измерения
|
||||
*
|
||||
* @param string $values
|
||||
* @param string $unit
|
||||
* @return string
|
||||
*/
|
||||
public function valueFormatWithoutUnit( $values, $unit ) {
|
||||
if ( ! is_numeric( $values ) ) {
|
||||
return str_replace( $unit, '', $values );
|
||||
} else {
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Форматирует значение c единицами измерения
|
||||
*
|
||||
* @param string $values
|
||||
* @param string $unit
|
||||
* @return string
|
||||
*/
|
||||
public function valueFormatWithUnit( $values, $unit ) {
|
||||
if ( is_numeric( $values ) ) {
|
||||
return $values . $unit;
|
||||
} else {
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Multiselect List Control
|
||||
*
|
||||
* Main options:
|
||||
* name => a name of the control
|
||||
* value => a value to show in the control
|
||||
* default => a default value of the control if the "value" option is not specified
|
||||
* items => a callback to return items or an array of items to select
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_ListControl' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_ListControl extends Wbcr_FactoryForms600_Control {
|
||||
|
||||
public $type = 'list';
|
||||
|
||||
/**
|
||||
* Returns a set of available items for the list.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function getItems() {
|
||||
|
||||
$data = $this->getOption( 'data', [] );
|
||||
|
||||
// if the data options is a valid callback for an object method
|
||||
if ( ( is_array( $data ) && count( $data ) == 2 && is_object( $data[0] ) ) || is_string( $data ) ) {
|
||||
|
||||
return call_user_func( $data );
|
||||
}
|
||||
|
||||
// if the data options is an array of values
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if the data should be loaded via ajax.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return bool
|
||||
*/
|
||||
protected function isAjax() {
|
||||
|
||||
$data = $this->getOption( 'data', [] );
|
||||
|
||||
return is_array( $data ) && isset( $data['ajax'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the html markup of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
$way = $this->getOption( 'way', 'default' );
|
||||
$this->addHtmlData( 'way', $way );
|
||||
|
||||
if ( $this->isAjax() ) {
|
||||
|
||||
$data = $this->getOption( 'data', [] );
|
||||
$ajax_id = 'factory-list-' . rand( 1000000, 9999999 );
|
||||
|
||||
$value = $this->getValue( null, true );
|
||||
|
||||
if ( empty( $value ) || empty( $value[0] ) ) {
|
||||
$value = [];
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="factory-ajax-loader <?php echo $ajax_id . '-loader'; ?>"></div>
|
||||
<script>
|
||||
window['<?php echo esc_attr( $ajax_id ); ?>'] = {
|
||||
'loader': '.<?php echo esc_attr( $ajax_id ) . '-loader'; ?>',
|
||||
'url': '<?php echo esc_url( $data['url'] ); ?>',
|
||||
'data': <?php echo json_encode( $data['data'] ); ?>,
|
||||
'selected': <?php echo json_encode( $value ); ?>,
|
||||
'emptyList': '<?php echo esc_html( $this->getOption( 'empty', __( 'The list is empty.', 'robin-image-optimizer' ) ) ); ?>'
|
||||
};
|
||||
</script>
|
||||
<?php
|
||||
|
||||
$this->addHtmlData( 'ajax', true );
|
||||
$this->addHtmlData( 'ajax-data-id', $ajax_id );
|
||||
$this->addCssClass( 'factory-hidden' );
|
||||
}
|
||||
|
||||
if ( 'checklist' == $way ) {
|
||||
$this->checklistHtml();
|
||||
} else {
|
||||
$this->defaultHtml();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the Buttons Dropdown.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
protected function checklistHtml() {
|
||||
$items = $this->getItems();
|
||||
|
||||
$value = explode( ',', $this->getValue() );
|
||||
if ( empty( $value ) || empty( $value[0] ) ) {
|
||||
$value = [];
|
||||
}
|
||||
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
|
||||
$this->addCssClass( 'factory-checklist-way' );
|
||||
$this->addHtmlData( 'name', $name_on_form );
|
||||
|
||||
$errors_callback = $this->getOption( 'errors' );
|
||||
$errors = ! empty( $errors_callback )
|
||||
? call_user_func( $errors_callback )
|
||||
: [];
|
||||
|
||||
$is_empty = $this->isAjax() || empty( $items );
|
||||
$emptyList = $this->getOption( 'empty', __( 'The list is empty.', 'robin-image-optimizer' ) );
|
||||
|
||||
if ( $is_empty ) {
|
||||
$this->addCssClass( 'factory-empty' );
|
||||
}
|
||||
|
||||
?>
|
||||
<ul <?php $this->attrs(); ?>>
|
||||
<?php if ( $is_empty ) { ?>
|
||||
<li><?php echo esc_html( $emptyList ); ?></li>
|
||||
<?php } else { ?>
|
||||
<?php foreach ( $items as $item ) { ?>
|
||||
<li>
|
||||
<label for="factory-checklist-<?php echo esc_attr( $name_on_form ); ?>-<?php echo esc_attr( $item[0] ); ?>" class="
|
||||
<?php
|
||||
if ( ! empty( $errors[ $item[0] ] ) ) {
|
||||
echo 'factory-has-error';
|
||||
}
|
||||
?>
|
||||
">
|
||||
<?php if ( ! empty( $errors[ $item[0] ] ) ) { ?>
|
||||
<span class="factory-error">
|
||||
<i class="fa fa-exclamation-triangle"></i>
|
||||
<div class='factory-error-text'><?php echo esc_html( $errors[ $item[0] ] ); ?></div>
|
||||
</span>
|
||||
<?php } else { ?>
|
||||
<span>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="<?php echo esc_attr( $name_on_form ); ?>[]"
|
||||
value="<?php echo esc_attr( $item[0] ); ?>"
|
||||
id="factory-checklist-<?php echo esc_attr( $name_on_form ); ?>-<?php echo esc_attr( $item[0] ); ?>"
|
||||
<?php
|
||||
if ( in_array( $item[0], $value ) ) {
|
||||
echo 'checked="checked"';
|
||||
}
|
||||
?>
|
||||
/>
|
||||
</span>
|
||||
<?php } ?>
|
||||
|
||||
<span><?php echo esc_html( $item[1] ); ?></span>
|
||||
</label>
|
||||
</li>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the standart dropdown.
|
||||
*
|
||||
* @since 1.3.1
|
||||
* @return void
|
||||
*/
|
||||
protected function defaultHtml() {
|
||||
|
||||
$items = $this->getItems();
|
||||
$value = $this->getValue();
|
||||
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
|
||||
$this->addHtmlAttr( 'id', $name_on_form );
|
||||
$this->addHtmlAttr( 'name', $name_on_form );
|
||||
$this->addCssClass( 'form-control' );
|
||||
|
||||
?>
|
||||
<select multiple="multiple" <?php $this->attrs(); ?>/>
|
||||
<?php
|
||||
foreach ( $items as $item ) {
|
||||
if ( count( $item ) == 3 ) {
|
||||
?>
|
||||
<optgroup label="<?php echo esc_attr( $item[1] ); ?>">
|
||||
<?php foreach ( $item[2] as $subitem ) { ?>
|
||||
<?php
|
||||
$selected = ( $subitem[0] == $value )
|
||||
? 'selected="selected"'
|
||||
: '';
|
||||
?>
|
||||
<option value='<?php echo esc_attr( $subitem[0] ); ?>' <?php echo $selected; ?>>
|
||||
<?php echo esc_html( $subitem[1] ); ?>
|
||||
</option>
|
||||
<?php } ?>
|
||||
</optgroup>
|
||||
<?php
|
||||
} else {
|
||||
$selected = ( $item[0] == $value )
|
||||
? 'selected="selected"'
|
||||
: '';
|
||||
?>
|
||||
<option value='<?php echo esc_attr( $item[0] ); ?>' <?php echo $selected; ?>>
|
||||
<?php echo esc_html( $item[1] ); ?>
|
||||
</option>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Control multiple textbox
|
||||
*
|
||||
* @package factory-forms
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Wbcr_FactoryForms600_MultipleTextboxControl' ) ) {
|
||||
|
||||
class Wbcr_FactoryForms600_MultipleTextboxControl extends Wbcr_FactoryForms600_Control {
|
||||
|
||||
public $type = 'multiple-textbox';
|
||||
|
||||
/**
|
||||
* Preparing html attributes before rendering html of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
protected function beforeHtml() {
|
||||
|
||||
$name_on_form = $this->getNameOnForm();
|
||||
|
||||
if ( $this->getOption( 'maxLength', false ) ) {
|
||||
$this->addHtmlAttr( 'maxlength', intval( $this->getOption( 'maxLength' ) ) );
|
||||
}
|
||||
|
||||
if ( $this->getOption( 'placeholder', false ) ) {
|
||||
$this->addHtmlAttr( 'placeholder', $this->getOption( 'placeholder' ) );
|
||||
}
|
||||
|
||||
$this->addCssClass( 'form-control' );
|
||||
$this->addHtmlAttr( 'type', 'text' );
|
||||
// $this->addHtmlAttr('id', $name_on_form);
|
||||
$this->addCssClass( str_replace( '_', '-', $name_on_form ) );
|
||||
$this->addHtmlAttr( 'name', $name_on_form . '[]' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the html markup of the control.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
$values = $this->getValue();
|
||||
|
||||
if ( ! empty( $values ) ) {
|
||||
$values = explode( '{%spr%}', $values );
|
||||
} else {
|
||||
$values = [];
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="factory-multiple-textbox-group">
|
||||
<div class="factory-mtextbox-items">
|
||||
<?php if ( empty( $values ) ) : ?>
|
||||
<div class="factory-mtextbox-item">
|
||||
<input <?php $this->attrs(); ?>/>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<?php $counter = 0; ?>
|
||||
<?php foreach ( $values as $value ) : ?>
|
||||
<div class="factory-mtextbox-item">
|
||||
<input value="<?php echo esc_attr( $value ); ?>"<?php $this->attrs(); ?>/>
|
||||
<?php if ( $counter >= 1 ) : ?>
|
||||
<button class="btn btn-default btn-small factory-mtextbox-remove-item">
|
||||
<i class="fa fa-times" aria-hidden="true"></i></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php ++$counter; ?>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<button class="btn btn-default btn-small factory-mtextbox-add-item">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i> <?php _e( 'Add new', 'robin-image-optimizer' ); ?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a submit value of the control by a given name.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSubmitValue( $name, $subName ) {
|
||||
$name_on_form = $this->getNameOnForm( $name );
|
||||
|
||||
$value = isset( $_POST[ $name_on_form ] )
|
||||
? $_POST[ $name_on_form ]
|
||||
: null;
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
$value = array_map( 'sanitize_text_field', $value );
|
||||
$value = implode( '{%spr%}', $value );
|
||||
}
|
||||
|
||||
$value = sanitize_text_field( $value );
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user