Robin image optimizer — save money on image compression - Version 1.4.1

Version Description

(24.12.2019) = * Fixed: Some bugs * Added: ompatible with Wordpress 5.3

Download this release

Release Info

Developer alexkovalevv
Plugin Icon 128x128 Robin image optimizer — save money on image compression
Version 1.4.1
Comparing to
See all releases

Code changes from version 1.3.7 to 1.4.1

Files changed (208) hide show
  1. admin/activation.php +30 -2
  2. admin/ajax/bulk-optimization.php +4 -1
  3. admin/ajax/meta-migrations.php +1 -1
  4. admin/assets/css/base-statistic.css +658 -656
  5. admin/assets/css/base-statistic.css.map +1 -1
  6. admin/assets/css/base-statistic.less +3 -1
  7. admin/assets/js/bulk-optimization.js +16 -9
  8. admin/boot.php +15 -15
  9. admin/includes/classes/class-rio-optimize-template.php +4 -4
  10. admin/pages/class-rio-license.php +3 -3
  11. admin/pages/class-rio-log.php +4 -2
  12. admin/pages/class-rio-page.php +1 -1
  13. admin/pages/class-rio-settings.php +1 -1
  14. admin/pages/class-rio-statistic.php +1 -0
  15. includes/class-rio-plugin.php +62 -42
  16. includes/classes/class-rio-attachment.php +329 -232
  17. includes/classes/class-rio-image-statistic.php +129 -63
  18. includes/classes/class-rio-media-library.php +31 -53
  19. includes/classes/class-rio-views.php +4 -4
  20. includes/classes/index.php +1 -0
  21. includes/classes/logger/class-rio-logger.php +10 -6
  22. includes/classes/models/class-rio-process-queue-table.php +38 -5
  23. includes/functions.php +43 -8
  24. libs/addons/admin/ajax/folders.php +21 -5
  25. libs/addons/admin/assets/js/custom-folders.js +4 -4
  26. libs/addons/admin/boot.php +1 -1
  27. libs/addons/includes/classes/webp/class-webp-delivery.php +82 -18
  28. libs/addons/includes/classes/webp/class-webp-listener.php +10 -10
  29. libs/addons/includes/classes/webp/composer.lock +73 -73
  30. libs/addons/includes/classes/webp/vendor/autoload.php +1 -1
  31. libs/addons/includes/classes/webp/vendor/composer/ClassLoader.php +1 -1
  32. libs/addons/includes/classes/webp/vendor/composer/autoload_real.php +4 -4
  33. libs/addons/includes/classes/webp/vendor/composer/autoload_static.php +3 -3
  34. libs/addons/includes/classes/webp/vendor/composer/installed.json +8 -8
  35. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/README.md +6 -1
  36. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/composer.json +6 -4
  37. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/phpstan.neon +3 -0
  38. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/phpunit.xml.dist +9 -1
  39. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/{src → src-vendor}/simple_html_dom/simple_html_dom.inc +0 -0
  40. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src/ImageUrlReplacer.php +23 -5
  41. libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src/PictureTags.php +6 -6
  42. libs/addons/includes/functions.php +110 -0
  43. libs/addons/views/modal-select-custom-folders.php +1 -1
  44. libs/addons/views/part-bulk-optimization-table-folders.php +1 -1
  45. libs/class-rio-relative-to-abs-uri.php +183 -0
  46. libs/factory/adverts/boot.php +50 -0
  47. libs/factory/adverts/includes/class-base.php +319 -0
  48. libs/factory/adverts/includes/class-dashboard-widget.php +125 -0
  49. libs/factory/adverts/includes/class-rest-request.php +197 -0
  50. libs/factory/adverts/includes/index.php +2 -0
  51. libs/factory/adverts/index.php +2 -0
  52. libs/factory/{core/langs/wbcr_factory_412-ru_RU.mo → adverts/langs/wbcr_factory_adverts_105-ru_RU.mo} +0 -0
  53. libs/factory/adverts/langs/wbcr_factory_adverts_105-ru_RU.po +83 -0
  54. libs/factory/bootstrap/assets/css-min/bootstrap.accordion.min.css +1 -1
  55. libs/factory/bootstrap/assets/css-min/bootstrap.blue.min.css +1 -1
  56. libs/factory/bootstrap/assets/css-min/bootstrap.coffee.min.css +1 -1
  57. libs/factory/bootstrap/assets/css-min/bootstrap.core.min.css +2 -2
  58. libs/factory/bootstrap/assets/css-min/bootstrap.ectoplasm.min.css +1 -1
  59. libs/factory/bootstrap/assets/css-min/bootstrap.form-group.min.css +1 -1
  60. libs/factory/bootstrap/assets/css-min/bootstrap.light.min.css +1 -1
  61. libs/factory/bootstrap/assets/css-min/bootstrap.midnight.min.css +1 -1
  62. libs/factory/bootstrap/assets/css-min/bootstrap.ocean.min.css +1 -1
  63. libs/factory/bootstrap/assets/css-min/bootstrap.separator.min.css +1 -1
  64. libs/factory/bootstrap/assets/css-min/bootstrap.sunrise.min.css +1 -1
  65. libs/factory/bootstrap/assets/css-min/control.checkbox.min.css +1 -1
  66. libs/factory/bootstrap/assets/css-min/control.dropdown.min.css +1 -1
  67. libs/factory/bootstrap/assets/css-min/control.multiple-textbox.min.css +1 -1
  68. libs/factory/bootstrap/assets/css-min/holder.more-link.min.css +1 -1
  69. libs/factory/bootstrap/assets/css-min/index.php +0 -0
  70. libs/factory/bootstrap/assets/images/index.php +0 -0
  71. libs/factory/bootstrap/assets/index.php +0 -0
  72. libs/factory/bootstrap/assets/js-min/bootstrap.dropdown.min.js +1 -1
  73. libs/factory/bootstrap/assets/js-min/control.checkbox.min.js +1 -1
  74. libs/factory/bootstrap/assets/js-min/control.dropdown.min.js +1 -1
  75. libs/factory/bootstrap/assets/js-min/control.list.min.js +1 -1
  76. libs/factory/bootstrap/assets/js-min/control.multiple-textbox.min.js +1 -1
  77. libs/factory/bootstrap/assets/js-min/index.php +0 -0
  78. libs/factory/bootstrap/boot.php +45 -36
  79. libs/factory/bootstrap/includes/functions.php +204 -260
  80. libs/factory/bootstrap/includes/index.php +2 -0
  81. libs/factory/bootstrap/index.php +2 -0
  82. libs/factory/clearfy/assets/css/clearfy-base.css +24 -24
  83. libs/factory/clearfy/assets/css/clearfy-base.css.map +1 -0
  84. libs/factory/clearfy/assets/css/index.php +0 -0
  85. libs/factory/clearfy/assets/index.php +0 -0
  86. libs/factory/clearfy/assets/js/globals.js +15 -15
  87. libs/factory/clearfy/assets/js/index.php +0 -0
  88. libs/factory/clearfy/assets/js/license-manager.js +14 -18
  89. libs/factory/clearfy/boot.php +20 -19
  90. libs/factory/clearfy/includes/ajax-handlers.php +44 -32
  91. libs/factory/clearfy/includes/check-clearfy-compatibility.php +0 -306
  92. libs/factory/clearfy/includes/class-clearfy-configurate.php +0 -120
  93. libs/factory/clearfy/includes/class-clearfy-helpers.php +0 -370
  94. libs/factory/clearfy/includes/class-configurate.php +116 -0
  95. libs/factory/clearfy/includes/class-helpers.php +266 -0
  96. libs/factory/clearfy/langs/index.php +0 -0
  97. libs/factory/clearfy/langs/{wbcr_factory_clearfy_208-ru_RU.mo → wbcr_factory_clearfy_216-ru_RU.mo} +0 -0
  98. libs/factory/clearfy/langs/{wbcr_factory_clearfy_208-ru_RU.po → wbcr_factory_clearfy_216-ru_RU.po} +0 -0
  99. libs/factory/clearfy/pages/class-clearfy-more-features.php +0 -148
  100. libs/factory/clearfy/pages/class-clearfy-pages.php +0 -385
  101. libs/factory/clearfy/pages/{class-clearfy-license.php → class-page-license.php} +107 -77
  102. libs/factory/clearfy/pages/class-page-more-features.php +170 -0
  103. libs/factory/clearfy/pages/class-pages.php +439 -0
  104. libs/factory/core/README.md +3 -0
  105. libs/factory/core/boot.php +30 -30
  106. libs/factory/core/includes/activation/class-factory-activator.php +13 -12
  107. libs/factory/core/includes/activation/class-factory-update.php +12 -11
  108. libs/factory/core/includes/activation/index.php +2 -0
  109. libs/factory/core/includes/assets-managment/class-factory-assets-list.php +32 -31
  110. libs/factory/core/includes/assets-managment/class-factory-script-list.php +43 -43
  111. libs/factory/core/includes/assets-managment/class-factory-style-list.php +22 -22
  112. libs/factory/core/includes/assets-managment/index.php +2 -0
  113. libs/factory/core/includes/class-check-compatibility.php +95 -101
  114. libs/factory/core/includes/class-factory-migrations.php +201 -145
  115. libs/factory/core/includes/class-factory-notices.php +115 -112
  116. libs/factory/core/includes/class-factory-options.php +207 -135
  117. libs/factory/core/includes/class-factory-plugin-abstract.php +335 -185
  118. libs/factory/core/includes/class-factory-plugin-base.php +300 -143
  119. libs/factory/core/includes/class-factory-requests.php +34 -27
  120. libs/factory/core/includes/class-factory-requirements.php +66 -62
  121. libs/factory/core/includes/entities/class-factory-paths.php +7 -8
  122. libs/factory/core/includes/entities/class-factory-support.php +31 -32
  123. libs/factory/core/includes/functions.php +52 -52
  124. libs/factory/core/includes/index.php +2 -0
  125. libs/factory/core/includes/premium/class-factory-license-interface.php +12 -12
  126. libs/factory/core/includes/premium/class-factory-manager.php +39 -37
  127. libs/factory/core/includes/premium/class-factory-provider-abstract.php +84 -85
  128. libs/factory/core/includes/premium/index.php +2 -0
  129. libs/factory/core/includes/updates/class-factory-premium-upgrader.php +266 -238
  130. libs/factory/core/includes/updates/class-factory-upgrader.php +29 -60
  131. libs/factory/core/includes/updates/index.php +2 -0
  132. libs/factory/core/includes/updates/repositories/class-factory-repository-abstract.php +17 -17
  133. libs/factory/core/includes/updates/repositories/class-factory-wordpress.php +17 -17
  134. libs/factory/core/index.php +2 -0
  135. libs/factory/core/langs/index.php +2 -0
  136. libs/factory/core/langs/wbcr_factory_424-ru_RU.mo +0 -0
  137. libs/factory/core/langs/{wbcr_factory_412-ru_RU.po → wbcr_factory_424-ru_RU.po} +0 -0
  138. libs/factory/forms/assets/css/index.php +0 -0
  139. libs/factory/forms/assets/index.php +0 -0
  140. libs/factory/forms/boot.php +251 -251
  141. libs/factory/forms/controls/checkbox.php +4 -4
  142. libs/factory/forms/controls/color-and-opacity.php +4 -4
  143. libs/factory/forms/controls/color.php +2 -2
  144. libs/factory/forms/controls/customs/html.php +2 -2
  145. libs/factory/forms/controls/customs/index.php +2 -0
  146. libs/factory/forms/controls/customs/separator.php +2 -2
  147. libs/factory/forms/controls/datepicker-range.php +4 -4
  148. libs/factory/forms/controls/dropdown-and-colors.php +6 -6
  149. libs/factory/forms/controls/dropdown.php +5 -5
  150. libs/factory/forms/controls/font.php +11 -11
  151. libs/factory/forms/controls/google-font.php +8 -8
  152. libs/factory/forms/controls/gradient.php +4 -4
  153. libs/factory/forms/controls/hidden.php +2 -2
  154. libs/factory/forms/controls/holders/accordion-item.php +2 -2
  155. libs/factory/forms/controls/holders/accordion.php +2 -2
  156. libs/factory/forms/controls/holders/columns.php +2 -2
  157. libs/factory/forms/controls/holders/control-group-item.php +2 -2
  158. libs/factory/forms/controls/holders/control-group.php +3 -3
  159. libs/factory/forms/controls/holders/div.php +2 -2
  160. libs/factory/forms/controls/holders/form-group.php +2 -2
  161. libs/factory/forms/controls/holders/index.php +2 -0
  162. libs/factory/forms/controls/holders/more-link.php +2 -2
  163. libs/factory/forms/controls/holders/tab-item.php +2 -2
  164. libs/factory/forms/controls/holders/tab.php +4 -4
  165. libs/factory/forms/controls/index.php +2 -0
  166. libs/factory/forms/controls/integer.php +2 -2
  167. libs/factory/forms/controls/list.php +4 -4
  168. libs/factory/forms/controls/multiple-textbox.php +3 -3
  169. libs/factory/forms/controls/paddings-editor.php +3 -3
  170. libs/factory/forms/controls/pattern.php +9 -9
  171. libs/factory/forms/controls/radio-colors.php +2 -2
  172. libs/factory/forms/controls/radio.php +2 -2
  173. libs/factory/forms/controls/textarea.php +2 -2
  174. libs/factory/forms/controls/textbox.php +2 -2
  175. libs/factory/forms/controls/url.php +3 -3
  176. libs/factory/forms/controls/wp-editor.php +3 -3
  177. libs/factory/forms/includes/complex-control.class.php +4 -4
  178. libs/factory/forms/includes/control-holder.class.php +5 -5
  179. libs/factory/forms/includes/control.class.php +5 -5
  180. libs/factory/forms/includes/custom-element.class.php +2 -2
  181. libs/factory/forms/includes/form-element.class.php +7 -7
  182. libs/factory/forms/includes/form-layout.class.php +5 -5
  183. libs/factory/forms/includes/form.class.php +39 -39
  184. libs/factory/forms/includes/holder.class.php +6 -6
  185. libs/factory/forms/includes/html-builder.class.php +2 -2
  186. libs/factory/forms/includes/index.php +2 -0
  187. libs/factory/forms/includes/providers/index.php +2 -0
  188. libs/factory/forms/includes/providers/meta-value-provider.class.php +2 -2
  189. libs/factory/forms/includes/providers/options-value-provider.class.php +3 -3
  190. libs/factory/forms/includes/providers/value-provider.interface.php +2 -2
  191. libs/factory/forms/index.php +2 -0
  192. libs/factory/forms/langs/index.php +0 -0
  193. libs/factory/forms/langs/{wbcr_factory_forms_412-ru_RU.mo → wbcr_factory_forms_422-ru_RU.mo} +0 -0
  194. libs/factory/forms/langs/{wbcr_factory_forms_412-ru_RU.po → wbcr_factory_forms_422-ru_RU.po} +0 -0
  195. libs/factory/forms/layouts/bootstrap-3/bootstrap-3.php +7 -7
  196. libs/factory/forms/layouts/bootstrap-3/index.php +2 -0
  197. libs/factory/forms/layouts/index.php +2 -0
  198. libs/factory/freemius/boot.php +28 -18
  199. libs/factory/freemius/includes/class-freemius-api.php +7 -7
  200. libs/factory/freemius/includes/entities/class-freemius-entity.php +1 -1
  201. libs/factory/freemius/includes/entities/class-freemius-license.php +2 -2
  202. libs/factory/freemius/includes/entities/class-freemius-plugin.php +1 -1
  203. libs/factory/freemius/includes/entities/class-freemius-scope.php +1 -1
  204. libs/factory/freemius/includes/entities/class-freemius-site.php +1 -1
  205. libs/factory/freemius/includes/entities/class-freemius-user.php +1 -1
  206. libs/factory/freemius/includes/entities/index.php +2 -0
  207. libs/factory/freemius/includes/index.php +2 -0
  208. libs/factory/freemius/includes/licensing/class-freemius-provider.php +9 -11
admin/activation.php CHANGED
@@ -5,7 +5,7 @@
5
  *
6
  * @author Webcraftic <wordpress.webraftic@gmail.com>
7
  * @copyright (c) 09.09.2017, Webcraftic
8
- * @see Factory412_Activator
9
  * @version 1.0
10
  */
11
 
@@ -14,7 +14,7 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  exit;
15
  }
16
 
17
- class WIO_Activation extends Wbcr_Factory412_Activator {
18
 
19
  /**
20
  * Runs activation actions.
@@ -36,11 +36,39 @@ class WIO_Activation extends Wbcr_Factory412_Activator {
36
  WRIO_Logger::info( 'Premium plugin installation complete!' );
37
  }
38
 
 
 
 
 
 
 
 
 
 
 
 
39
  RIO_Process_Queue::try_create_plugin_tables();
40
 
 
 
41
  WRIO_Logger::info( 'Parent plugin installation complete!' );
42
  }
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  /**
45
  * Runs activation actions.
46
  *
5
  *
6
  * @author Webcraftic <wordpress.webraftic@gmail.com>
7
  * @copyright (c) 09.09.2017, Webcraftic
8
+ * @see Factory424_Activator
9
  * @version 1.0
10
  */
11
 
14
  exit;
15
  }
16
 
17
+ class WIO_Activation extends Wbcr_Factory424_Activator {
18
 
19
  /**
20
  * Runs activation actions.
36
  WRIO_Logger::info( 'Premium plugin installation complete!' );
37
  }
38
 
39
+ $db_version = RIO_Process_Queue::get_db_version();
40
+ $plugin_version_in_db = $this->get_plugin_version_in_db();
41
+ $current_plugin_version = $this->plugin->getPluginVersion();
42
+
43
+ $create_table_log_message = "Plugin installation: try create plugin tables.\r\n";
44
+ $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-DB Version: {$db_version}\r\n";
45
+ $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-Plugin Version in DB: {$plugin_version_in_db}\r\n";
46
+ $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-Current Plugin Version: {$current_plugin_version}";
47
+
48
+ WRIO_Logger::info( $create_table_log_message );
49
+
50
  RIO_Process_Queue::try_create_plugin_tables();
51
 
52
+ WbcrFactoryClearfy216_Helpers::flushPageCache();
53
+
54
  WRIO_Logger::info( 'Parent plugin installation complete!' );
55
  }
56
 
57
+ /**
58
+ * Get previous plugin version
59
+ *
60
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
61
+ * @since 1.3.8
62
+ * @return number
63
+ */
64
+ public function get_plugin_version_in_db() {
65
+ if ( WRIO_Plugin::app()->isNetworkActive() ) {
66
+ return get_site_option( WRIO_Plugin::app()->getOptionName( 'plugin_version' ), 0 );
67
+ }
68
+
69
+ return get_option( WRIO_Plugin::app()->getOptionName( 'plugin_version' ), 0 );
70
+ }
71
+
72
  /**
73
  * Runs activation actions.
74
  *
admin/ajax/bulk-optimization.php CHANGED
@@ -227,6 +227,7 @@ add_action( 'wp_ajax_wbcr-rio-check-servers-status', function () {
227
  $return_data = [ 'server_name' => $server_name ];
228
 
229
  $server_url = wrio_get_server_url( $server_name );
 
230
 
231
  $method = 'POST';
232
  if ( $server_name == 'server_4' ) {
@@ -239,7 +240,8 @@ add_action( 'wp_ajax_wbcr-rio-check-servers-status', function () {
239
  }
240
 
241
  $request = wp_remote_request( $api_url, [
242
- 'method' => $method
 
243
  ] );
244
 
245
  if ( is_wp_error( $request ) ) {
@@ -266,3 +268,4 @@ add_action( 'wp_ajax_wbcr-rio-check-servers-status', function () {
266
 
267
  wp_send_json_success( $return_data );
268
  } );
 
227
  $return_data = [ 'server_name' => $server_name ];
228
 
229
  $server_url = wrio_get_server_url( $server_name );
230
+ $headers = [];
231
 
232
  $method = 'POST';
233
  if ( $server_name == 'server_4' ) {
240
  }
241
 
242
  $request = wp_remote_request( $api_url, [
243
+ 'method' => $method,
244
+ 'headers' => $headers
245
  ] );
246
 
247
  if ( is_wp_error( $request ) ) {
268
 
269
  wp_send_json_success( $return_data );
270
  } );
271
+
admin/ajax/meta-migrations.php CHANGED
@@ -157,7 +157,7 @@ function wbcr_rio_migrate_postmeta_to_process_queue() {
157
  WRIO_Logger::info( 'Succefull migrated all items. Finishing-up...' );
158
 
159
  // Assumed to be 2 after 010105.php migration
160
- WRIO_Plugin::app()->updateOption( 'db_version', 2 );
161
 
162
  $need_more_time = false;
163
  $message = __( 'Finishing-up...', 'robin-image-optimizer' );
157
  WRIO_Logger::info( 'Succefull migrated all items. Finishing-up...' );
158
 
159
  // Assumed to be 2 after 010105.php migration
160
+ RIO_Process_Queue::update_db_version(2);
161
 
162
  $need_more_time = false;
163
  $message = __( 'Finishing-up...', 'robin-image-optimizer' );
admin/assets/css/base-statistic.css CHANGED
@@ -1,657 +1,659 @@
1
- /**
2
- * Styles for the Widget to be displayed in the Clearfy plugin
3
-
4
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
5
- * @copyright Webcraftic 13.06.2018
6
- */
7
- #WBCR {
8
- /* Doughnut */
9
- /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
10
- .wio-overview-chart-container {
11
- float: none;
12
- margin-right: 0;
13
- }
14
- }
15
-
16
- @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
17
- .wio-overview-chart-container {
18
- float: none;
19
- margin-right: 0;
20
- }
21
-
22
- .wio-doughnut-legend {
23
- margin-top: 18px;
24
- }
25
-
26
- .wio-global-optim-phrase {
27
- padding-top: 0;
28
- width: auto;
29
- }
30
- }*/
31
- }
32
- #WBCR .wio-clear {
33
- clear: both;
34
- }
35
- #WBCR #io_folders_statistic-wbcr_clearfy-tab,
36
- #WBCR #io_nextgen_gallery_statistic-wbcr_clearfy-tab {
37
- display: none !important;
38
- }
39
- #WBCR .wrio-statistic-nav {
40
- margin: 0;
41
- background: #efefef;
42
- }
43
- #WBCR .wrio-statistic-nav ul {
44
- margin: 0;
45
- }
46
- #WBCR .wrio-statistic-nav ul li {
47
- position: relative;
48
- display: inline-block;
49
- margin: 0 0 0 0;
50
- background: #ffffff;
51
- box-shadow: 0 -2px 0 #eaeaea;
52
- }
53
- #WBCR .wrio-statistic-nav ul li:hover {
54
- background: #f7f7f7;
55
- }
56
- #WBCR .wrio-statistic-nav ul li.active {
57
- background: #f7f7f7;
58
- border-top: 1px solid #d4d4d4;
59
- border-left: 1px solid #d4d4d4;
60
- border-right: 1px solid #d4d4d4;
61
- border-bottom: 1px solid #f7f7f7;
62
- margin-bottom: -1px;
63
- }
64
- #WBCR .wrio-statistic-nav ul li.active a {
65
- color: #222;
66
- }
67
- #WBCR .wrio-statistic-nav ul li.active a .wrio-statistic-tab-percent {
68
- border: 2px dashed #8bc34a;
69
- color: #5e8237;
70
- }
71
- #WBCR .wrio-statistic-nav ul li.active .dashicons,
72
- #WBCR .wrio-statistic-nav ul li.active .dashicons-before:before {
73
- color: #ff8b66;
74
- }
75
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab {
76
- display: block;
77
- padding: 10px 20px 10px 20px;
78
- text-decoration: none;
79
- color: #d4d4d4;
80
- font-size: 22px;
81
- line-height: 2;
82
- }
83
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:active,
84
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:focus {
85
- background: 0;
86
- box-shadow: none;
87
- outline: none;
88
- }
89
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons,
90
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons-before:before {
91
- display: inline-block;
92
- width: 30px;
93
- height: 30px;
94
- font-size: 30px;
95
- line-height: 1.5;
96
- margin-right: 15px;
97
- color: #d4d4d4;
98
- }
99
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .wrio-statistic-tab-percent {
100
- display: inline-block;
101
- width: 42px;
102
- height: 42px;
103
- border-radius: 100px;
104
- border: 2px dashed #e4e4e4;
105
- padding: 5px;
106
- margin-left: 30px;
107
- font-size: 14px;
108
- font-weight: 600;
109
- text-align: center;
110
- color: #bdbdbd;
111
- }
112
- #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab-premium-label:after {
113
- display: inline-block;
114
- position: absolute;
115
- content: 'PRO';
116
- background: #ff5722;
117
- border-radius: 4px;
118
- color: #fff;
119
- font-size: 10px;
120
- line-height: 1;
121
- font-style: normal;
122
- padding: 4px 6px;
123
- margin-left: 4px;
124
- vertical-align: top;
125
- top: 10px;
126
- left: auto;
127
- right: 10px;
128
- z-index: 11;
129
- }
130
- #WBCR .wrio-table {
131
- width: 100%;
132
- table-layout: fixed;
133
- box-sizing: border-box;
134
- border-spacing: 3px;
135
- background: #fff;
136
- border-top: 2px dashed #cac9c9;
137
- }
138
- #WBCR .wrio-table th,
139
- #WBCR .wrio-table td {
140
- padding: 16px 10px;
141
- text-align: center;
142
- }
143
- #WBCR .wrio-table th {
144
- background: #f3f3f3;
145
- color: #777777;
146
- box-shadow: 0 1px 0 #d8d8d8;
147
- }
148
- #WBCR .wrio-table th:nth-child(2n+1) {
149
- background: #f9f9f9;
150
- }
151
- #WBCR .wrio-table tr.wrio-error {
152
- background-color: #ffe9e9 !important;
153
- }
154
- #WBCR .wrio-table .wrio-table-spinner {
155
- background: url("../img/quick-start-loader.gif") center center no-repeat;
156
- }
157
- #WBCR .wrio-table .wrio-table-highlighter {
158
- display: inline-block;
159
- padding: 3px 7px;
160
- background: #f3f3f3;
161
- }
162
- #WBCR .wrio-table .wbcr-rio-server-success {
163
- color: #8CC152;
164
- }
165
- #WBCR .wrio-table .wbcr-rio-server-error {
166
- color: #fb5d49;
167
- }
168
- #WBCR .wrio-table .wbcr-rio-server-warning {
169
- color: #ffb635;
170
- }
171
- #WBCR .wrio-table.wbcr-rio-folders-table td:nth-child(3) {
172
- text-align: left;
173
- }
174
- #WBCR .wrio-servers {
175
- padding: 40px 20px;
176
- }
177
- #WBCR .wrio-servers label span {
178
- display: block;
179
- font-weight: normal;
180
- font-size: 12px;
181
- color: #b7b2b2;
182
- }
183
- #WBCR .wrio-servers #wrio-change-optimization-server {
184
- position: relative;
185
- max-width: 400px;
186
- margin-right: 15px;
187
- margin-bottom: 0;
188
- border: 1px solid #d2d0d0;
189
- background: #efefef;
190
- }
191
- #WBCR .wrio-servers .wrio-servers-info {
192
- margin: 0 0 0;
193
- padding: 20px;
194
- background: #fff;
195
- }
196
- #WBCR .wrio-servers .wrio-server-status-wrap {
197
- margin-top: 8px;
198
- }
199
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status {
200
- background: transparent;
201
- color: #fff;
202
- padding: 3px 5px;
203
- border-radius: 4px;
204
- }
205
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-down {
206
- background: #ff5722;
207
- }
208
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-stable {
209
- background: #8bc34a;
210
- }
211
- #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-server-check-proccess {
212
- display: inline-block;
213
- height: 10px;
214
- width: 30px;
215
- background: url("../img/quick-start-loader.gif") center no-repeat;
216
- }
217
- #WBCR .wio-columns {
218
- overflow: hidden;
219
- padding: 15px 0;
220
- counter-reset: cols;
221
- }
222
- #WBCR .wio-columns [class^="col-"] {
223
- float: left;
224
- -webkit-box-sizing: border-box;
225
- -moz-box-sizing: border-box;
226
- box-sizing: border-box;
227
- }
228
- #WBCR .wio-columns .col-1-3 {
229
- width: 33.333%;
230
- padding-left: 28px;
231
- }
232
- #WBCR .wio-columns .col-2-3 {
233
- width: 66.666%;
234
- padding-left: 28px;
235
- }
236
- #WBCR .wio-columns .col-1-2 {
237
- width: 50%;
238
- padding: 0 20px;
239
- }
240
- #WBCR .wio-columns .col-statistics.col-statistics {
241
- width: 60%;
242
- }
243
- #WBCR .wio-columns .col-chart.col-chart {
244
- width: 40%;
245
- position: relative;
246
- padding: 20px;
247
- font-size: 12px;
248
- text-transform: uppercase;
249
- background: #f1f1f1b3;
250
- color: #abacaf;
251
- font-weight: bold;
252
- border-radius: 5px;
253
- margin-top: 10px;
254
- text-align: left;
255
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
256
- }
257
- #WBCR .wio-col {
258
- float: left;
259
- width: 50%;
260
- box-sizing: border-box;
261
- -webkit-flex-basis: 50%;
262
- -ms-flex-preferred-size: 50%;
263
- flex-basis: 50%;
264
- }
265
- #WBCR .wio-col {
266
- padding-right: 20px;
267
- }
268
- #WBCR .wio-col + .wio-col {
269
- padding-right: 0;
270
- padding-left: 50px;
271
- }
272
- #WBCR .wio-col:target {
273
- animation: wiohello 1s 3 linear backwards;
274
- }
275
- #WBCR .wio-number-you-optimized {
276
- margin-bottom: 1.35em;
277
- overflow: hidden;
278
- }
279
- #WBCR .wio-number-you-optimized #wio-total-optimized-attachments-pct {
280
- color: #828282;
281
- }
282
- #WBCR .wio-number-you-optimized .wio-number {
283
- display: table-cell;
284
- padding-right: 15px;
285
- font-size: 48px;
286
- font-weight: bold;
287
- line-height: 1;
288
- vertical-align: middle;
289
- white-space: nowrap;
290
- color: #828282;
291
- }
292
- #WBCR .wio-number-you-optimized .wio-text {
293
- display: table-cell;
294
- vertical-align: middle;
295
- overflow: hidden;
296
- font-size: 12px;
297
- color: #828282;
298
- }
299
- #WBCR .wio-number-you-optimized > p {
300
- display: table;
301
- }
302
- #WBCR .wio-bars {
303
- padding-right: 15px;
304
- }
305
- #WBCR .wio-bars p {
306
- font-size: 12px;
307
- margin-bottom: 5px;
308
- }
309
- #WBCR .wio-bars + .wio-number-you-optimized {
310
- border-bottom: 0;
311
- padding-top: 0.85em;
312
- }
313
- #WBCR .wio-bars + .wio-number-you-optimized p {
314
- color: #72a53b;
315
- }
316
- #WBCR .wio-bar-negative .wio-progress {
317
- background: #D2D3D6;
318
- }
319
- #WBCR .wio-bar-negative .wio-barnb {
320
- color: #9d9fa5;
321
- }
322
- #WBCR .wio-progress {
323
- height: 8px;
324
- transition: width .3s;
325
- /*.wio-bar-negative {
326
- width: 92% !important;
327
- }*/
328
- }
329
- #WBCR .wio-bar-positive .wio-progress {
330
- background: #8CC152;
331
- }
332
- #WBCR .wio-bar-positive .wio-barnb {
333
- color: #72a53b;
334
- }
335
- #WBCR .wio-bar-primary .wio-progress {
336
- background: #8CC152;
337
- }
338
- #WBCR .wio-bar-primary .wio-barnb {
339
- color: #72a53b;
340
- }
341
- #WBCR .wio-right-outside-number .wio-barnb {
342
- display: block;
343
- margin-right: -5.25em;
344
- text-align: right;
345
- font-weight: bold;
346
- line-height: .8;
347
- }
348
- #WBCR .wio-chart {
349
- position: relative;
350
- top: 1px;
351
- display: inline-block;
352
- vertical-align: middle;
353
- }
354
- #WBCR .wio-chart-container {
355
- position: relative;
356
- display: inline-block;
357
- margin-right: 5px;
358
- }
359
- #WBCR .wio-chart-container canvas {
360
- display: block;
361
- }
362
- #WBCR .wio-overview-chart-container {
363
- float: left;
364
- margin-right: 20px;
365
- }
366
- #WBCR .wio-chart-percent {
367
- position: absolute;
368
- left: 0;
369
- right: 0;
370
- top: 50%;
371
- margin-top: -0.5em;
372
- line-height: 0.8;
373
- text-align: center;
374
- font-size: 54px;
375
- font-weight: bold;
376
- color: #afafaf;
377
- }
378
- #WBCR .wio-chart-percent span {
379
- font-size: 20px;
380
- vertical-align: super;
381
- }
382
- #WBCR #wio-overview-chart-legend {
383
- overflow: hidden;
384
- }
385
- #WBCR .wio-doughnut-legend li {
386
- display: inline-block;
387
- position: relative;
388
- margin-bottom: 15px;
389
- border-radius: 5px;
390
- padding: 3px 8px 2px 31px;
391
- font-size: 9px;
392
- cursor: default;
393
- -webkit-transition: background-color 200ms ease-in-out;
394
- -moz-transition: background-color 200ms ease-in-out;
395
- -o-transition: background-color 200ms ease-in-out;
396
- transition: background-color 200ms ease-in-out;
397
- }
398
- #WBCR .wio-doughnut-legend li span {
399
- display: block;
400
- position: absolute;
401
- left: 0;
402
- top: 0;
403
- width: 25px;
404
- height: 25px;
405
- border-radius: 50%;
406
- }
407
- #WBCR .wio-optimize-button {
408
- min-width: 180px;
409
- padding: 12px 30px;
410
- background: #c9deb2;
411
- color: #586549;
412
- border: 0;
413
- box-shadow: none;
414
- font-size: 14px;
415
- text-transform: uppercase !important;
416
- font-weight: bold;
417
- border-radius: 4px;
418
- outline: none;
419
- }
420
- #WBCR .wio-optimize-button:active {
421
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
422
- }
423
- #WBCR .wio-optimize-button:disabled {
424
- background: #e2edd6;
425
- color: #a5b295;
426
- }
427
- #WBCR .wio-optimize-button.wio-running {
428
- color: #a57b3c;
429
- background: #fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
430
- padding-left: 50px;
431
- }
432
- #WBCR .wio-global-optim-phrase {
433
- width: 180px;
434
- padding-top: 20px;
435
- font-size: 14px;
436
- text-align: center;
437
- }
438
- #WBCR .wio-total-percent {
439
- color: #587f2e;
440
- }
441
- #WBCR #wio-start-msg-top,
442
- #WBCR #wio-start-msg-right,
443
- #WBCR #wio-start-msg-complete {
444
- display: none;
445
- }
446
- #WBCR .wio-text-left {
447
- text-align: left;
448
- }
449
- #WBCR span.wio-num {
450
- display: inline !important;
451
- position: inherit !important;
452
- }
453
- #WBCR .wio-image-optimize-board {
454
- padding-bottom: 0 !important;
455
- }
456
- #WBCR .wio-page-statistic {
457
- padding-left: 40px;
458
- }
459
- #WBCR .wio-page-statistic .wio-chart-percent {
460
- margin-top: -1.1em;
461
- }
462
- #WBCR .wrio-optimization-progress {
463
- background: none;
464
- padding: 0;
465
- /*button {
466
- padding: 5px 10px;
467
- border: 0;
468
- font-size: 11px;
469
- text-transform: uppercase !important;
470
- font-weight: bold;
471
- border-radius: 4px;
472
- outline: none;
473
- background: @greyButtonBg;
474
- color: @greyButtonColor;
475
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
476
-
477
- &:active {
478
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
479
- }
480
-
481
- &.wbcr-rio-loading {
482
- width: 56px;
483
- font-size: 0;
484
- background: @greyButtonBg url("../img/quick-start-loader.gif") center no-repeat;
485
- }
486
-
487
- &.wbcr-rio-selected {
488
- background: #f3efe2;
489
- color: #d8d8d8;
490
-
491
- &:active {
492
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
493
- }
494
- }
495
- }*/
496
- }
497
- #WBCR .wrio-optimization-progress h4 {
498
- font-size: 15px;
499
- font-weight: 700;
500
- }
501
- #WBCR .wrio-optimization-progress .wbcr-rio-warning-message {
502
- padding: 20px;
503
- background: #efefef;
504
- font-size: 15px;
505
- color: #b7b7b7;
506
- font-style: italic;
507
- }
508
- #WBCR .wio-widget {
509
- padding: 0 !important;
510
- }
511
- #WBCR .wio-widget .wio-chart-percent {
512
- font-size: 44px;
513
- line-height: 1;
514
- }
515
- #WBCR .wio-widget .wio-bars {
516
- width: 60%;
517
- margin-left: 155px;
518
- }
519
- #WBCR .wio-widget .col-chart.col-chart {
520
- width: 100%;
521
- }
522
- #WBCR .wio-widget .col-controls {
523
- width: 45%;
524
- padding-left: 5px;
525
- padding-top: 110px;
526
- }
527
- #WBCR .wio-widget .wio-doughnut-legend {
528
- /*padding-top:30px;*/
529
- text-align: left;
530
- }
531
- #WBCR .wio-widget .wio-widget-bottom {
532
- display: table;
533
- padding-top: 20px !important;
534
- width: 100%;
535
- text-align: right;
536
- }
537
- #WBCR .wio-widget .wio-widget-bottom li {
538
- display: table-cell;
539
- }
540
- #WBCR .wio-widget .wio-widget-bottom li:first-child {
541
- text-align: left;
542
- }
543
- #WBCR .factory-checkbox.wrio-checkbox-premium-label:after {
544
- display: inline-block;
545
- position: relative;
546
- content: 'PRO';
547
- background: #ff5722;
548
- border-radius: 4px;
549
- color: #fff;
550
- font-size: 10px;
551
- line-height: 1;
552
- font-style: normal;
553
- padding: 4px 6px;
554
- margin-left: 4px;
555
- vertical-align: top;
556
- top: -8px;
557
- left: -10px;
558
- right: auto;
559
- z-index: 11;
560
- }
561
- #WBCR .factory-checkbox-disabled input,
562
- #WBCR .factory-checkbox-disabled button {
563
- pointer-events: none;
564
- cursor: not-allowed;
565
- opacity: .65;
566
- filter: alpha(opacity=65);
567
- -webkit-box-shadow: none;
568
- box-shadow: none;
569
- }
570
- #WBCR #wrio-webp-options h3,
571
- #WBCR #wrio-error-log-options h3 {
572
- font-size: 14px;
573
- margin: 0 0 10px 0;
574
- font-weight: 600;
575
- color: #565656;
576
- }
577
- #WBCR #wrio-webp-options .wrio-webp-options-info,
578
- #WBCR #wrio-error-log-options .wrio-webp-options-info {
579
- color: #8a8787;
580
- font-size: 12px;
581
- }
582
- #WBCR #wrio-webp-options ul,
583
- #WBCR #wrio-error-log-options ul {
584
- padding-left: 0;
585
- }
586
- #WBCR #wrio-webp-options ul li:after,
587
- #WBCR #wrio-error-log-options ul li:after {
588
- content: '';
589
- display: block;
590
- clear: both;
591
- }
592
- #WBCR #wrio-webp-options ul li label,
593
- #WBCR #wrio-error-log-options ul li label {
594
- font-weight: 600;
595
- }
596
- #WBCR #wrio-webp-options ul li .wrio-webp-options-radio,
597
- #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio,
598
- #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox,
599
- #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox {
600
- display: block;
601
- float: left;
602
- margin-top: 2px;
603
- margin-right: 8px;
604
- }
605
- #WBCR #wrio-webp-options ul li .wrio-webp-options-radio:focus,
606
- #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio:focus,
607
- #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox:focus,
608
- #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox:focus {
609
- outline: none;
610
- box-shadow: none;
611
- }
612
- #WBCR #wrio-webp-options ul li .wrio-webp-options-info,
613
- #WBCR #wrio-error-log-options ul li .wrio-webp-options-info,
614
- #WBCR #wrio-webp-options ul li .wrio-error-log-options-info,
615
- #WBCR #wrio-error-log-options ul li .wrio-error-log-options-info {
616
- padding-left: 25px;
617
- }
618
- @media (max-width: 830px) {
619
- #WBCR .wio [class^="col-"] {
620
- float: none;
621
- margin-bottom: 1.5em;
622
- }
623
- #WBCR .wio .col-1-3,
624
- #WBCR .wio .col-1-2 {
625
- width: auto;
626
- padding: 0 28px;
627
- clear: both;
628
- padding-top: 1em;
629
- }
630
- }
631
- @keyframes wiohello {
632
- 0%,
633
- 100% {
634
- background: #FFF;
635
- }
636
- 50% {
637
- background: #F4F7F9;
638
- }
639
- }
640
- @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
641
- #WBCR .wio-columns .col-statistics.col-statistics,
642
- #WBCR .wio-columns .col-chart.col-chart {
643
- width: 50%;
644
- }
645
- }
646
- @media (max-width: 808px) {
647
- #WBCR .wio-columns .col-statistics.col-statistics,
648
- #WBCR .wio-columns .col-chart.col-chart {
649
- width: auto;
650
- float: none;
651
- padding: 0;
652
- }
653
- #WBCR .wio-columns .col-chart.col-chart {
654
- margin-top: 3em;
655
- }
656
- }
 
 
657
  /*# sourceMappingURL=base-statistic.css.map */
1
+ /**
2
+ * Styles for the Widget to be displayed in the Clearfy plugin
3
+
4
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
5
+ * @copyright Webcraftic 13.06.2019
6
+ */
7
+ #WBCR {
8
+ /* Doughnut */
9
+ /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
10
+ .wio-overview-chart-container {
11
+ float: none;
12
+ margin-right: 0;
13
+ }
14
+ }
15
+
16
+ @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
17
+ .wio-overview-chart-container {
18
+ float: none;
19
+ margin-right: 0;
20
+ }
21
+
22
+ .wio-doughnut-legend {
23
+ margin-top: 18px;
24
+ }
25
+
26
+ .wio-global-optim-phrase {
27
+ padding-top: 0;
28
+ width: auto;
29
+ }
30
+ }*/
31
+ }
32
+ #WBCR .wio-clear {
33
+ clear: both;
34
+ }
35
+ #WBCR #io_folders_statistic-wbcr_clearfy-tab,
36
+ #WBCR #io_nextgen_gallery_statistic-wbcr_clearfy-tab {
37
+ display: none !important;
38
+ }
39
+ #WBCR .wrio-statistic-nav {
40
+ margin: 0;
41
+ background: #efefef;
42
+ }
43
+ #WBCR .wrio-statistic-nav ul {
44
+ margin: 0;
45
+ }
46
+ #WBCR .wrio-statistic-nav ul li {
47
+ position: relative;
48
+ display: inline-block;
49
+ margin: 0 0 0 0;
50
+ background: #ffffff;
51
+ box-shadow: 0 -2px 0 #eaeaea;
52
+ }
53
+ #WBCR .wrio-statistic-nav ul li:hover {
54
+ background: #f7f7f7;
55
+ }
56
+ #WBCR .wrio-statistic-nav ul li.active {
57
+ background: #f7f7f7;
58
+ border-top: 1px solid #d4d4d4;
59
+ border-left: 1px solid #d4d4d4;
60
+ border-right: 1px solid #d4d4d4;
61
+ border-bottom: 1px solid #f7f7f7;
62
+ margin-bottom: -1px;
63
+ }
64
+ #WBCR .wrio-statistic-nav ul li.active a {
65
+ color: #222;
66
+ }
67
+ #WBCR .wrio-statistic-nav ul li.active a .wrio-statistic-tab-percent {
68
+ border: 2px dashed #8bc34a;
69
+ color: #5e8237;
70
+ }
71
+ #WBCR .wrio-statistic-nav ul li.active .dashicons,
72
+ #WBCR .wrio-statistic-nav ul li.active .dashicons-before:before {
73
+ color: #ff8b66;
74
+ }
75
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab {
76
+ display: block;
77
+ padding: 10px 20px 10px 20px;
78
+ text-decoration: none;
79
+ color: #d4d4d4;
80
+ font-size: 22px;
81
+ line-height: 2;
82
+ }
83
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:active,
84
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab:focus {
85
+ background: 0;
86
+ box-shadow: none;
87
+ outline: none;
88
+ }
89
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons,
90
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .dashicons-before:before {
91
+ display: inline-block;
92
+ width: 30px;
93
+ height: 30px;
94
+ font-size: 30px;
95
+ line-height: 1.5;
96
+ margin-right: 15px;
97
+ color: #d4d4d4;
98
+ }
99
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab .wrio-statistic-tab-percent {
100
+ display: inline-block;
101
+ width: 42px;
102
+ height: 42px;
103
+ border-radius: 100px;
104
+ border: 2px dashed #e4e4e4;
105
+ padding: 5px;
106
+ margin-left: 30px;
107
+ font-size: 14px;
108
+ font-weight: 600;
109
+ text-align: center;
110
+ color: #bdbdbd;
111
+ }
112
+ #WBCR .wrio-statistic-nav ul li .wrio-statistic-tab-premium-label:after {
113
+ display: inline-block;
114
+ position: absolute;
115
+ content: 'PRO';
116
+ background: #ff5722;
117
+ border-radius: 4px;
118
+ color: #fff;
119
+ font-size: 10px;
120
+ line-height: 1;
121
+ font-style: normal;
122
+ padding: 4px 6px;
123
+ margin-left: 4px;
124
+ vertical-align: top;
125
+ top: 10px;
126
+ left: auto;
127
+ right: 10px;
128
+ z-index: 11;
129
+ }
130
+ #WBCR .wrio-table {
131
+ width: 100%;
132
+ table-layout: fixed;
133
+ box-sizing: border-box;
134
+ border-spacing: 3px;
135
+ background: #fff;
136
+ border-top: 2px dashed #cac9c9;
137
+ }
138
+ #WBCR .wrio-table th,
139
+ #WBCR .wrio-table td {
140
+ padding: 16px 10px;
141
+ text-align: center;
142
+ }
143
+ #WBCR .wrio-table th {
144
+ background: #f3f3f3;
145
+ color: #777777;
146
+ box-shadow: 0 1px 0 #d8d8d8;
147
+ }
148
+ #WBCR .wrio-table th:nth-child(2n+1) {
149
+ background: #f9f9f9;
150
+ }
151
+ #WBCR .wrio-table tr.wrio-error {
152
+ background-color: #ffe9e9 !important;
153
+ }
154
+ #WBCR .wrio-table .wrio-table-spinner {
155
+ background: url("../img/quick-start-loader.gif") center center no-repeat;
156
+ }
157
+ #WBCR .wrio-table .wrio-table-highlighter {
158
+ display: inline-block;
159
+ padding: 3px 7px;
160
+ background: #f3f3f3;
161
+ }
162
+ #WBCR .wrio-table .wbcr-rio-server-success {
163
+ color: #8CC152;
164
+ }
165
+ #WBCR .wrio-table .wbcr-rio-server-error {
166
+ color: #fb5d49;
167
+ }
168
+ #WBCR .wrio-table .wbcr-rio-server-warning {
169
+ color: #ffb635;
170
+ }
171
+ #WBCR .wrio-table.wbcr-rio-folders-table td:nth-child(3) {
172
+ text-align: left;
173
+ }
174
+ #WBCR .wrio-servers {
175
+ padding: 40px 20px;
176
+ }
177
+ #WBCR .wrio-servers label span {
178
+ display: block;
179
+ font-weight: normal;
180
+ font-size: 12px;
181
+ color: #b7b2b2;
182
+ }
183
+ #WBCR .wrio-servers #wrio-change-optimization-server {
184
+ position: relative;
185
+ display: inline-block;
186
+ max-width: 400px;
187
+ margin-right: 15px;
188
+ margin-bottom: 0;
189
+ border: 1px solid #d2d0d0;
190
+ background: #efefef;
191
+ }
192
+ #WBCR .wrio-servers .wrio-servers-info {
193
+ margin: 0 0 0;
194
+ padding: 20px;
195
+ background: #fff;
196
+ }
197
+ #WBCR .wrio-servers .wrio-server-status-wrap {
198
+ display: inline-block;
199
+ margin-top: 8px;
200
+ }
201
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status {
202
+ background: transparent;
203
+ color: #fff;
204
+ padding: 3px 5px;
205
+ border-radius: 4px;
206
+ }
207
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-down {
208
+ background: #ff5722;
209
+ }
210
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-stable {
211
+ background: #8bc34a;
212
+ }
213
+ #WBCR .wrio-servers .wrio-server-status-wrap .wrio-server-status.wrio-server-check-proccess {
214
+ display: inline-block;
215
+ height: 10px;
216
+ width: 30px;
217
+ background: url("../img/quick-start-loader.gif") center no-repeat;
218
+ }
219
+ #WBCR .wio-columns {
220
+ overflow: hidden;
221
+ padding: 15px 0;
222
+ counter-reset: cols;
223
+ }
224
+ #WBCR .wio-columns [class^="col-"] {
225
+ float: left;
226
+ -webkit-box-sizing: border-box;
227
+ -moz-box-sizing: border-box;
228
+ box-sizing: border-box;
229
+ }
230
+ #WBCR .wio-columns .col-1-3 {
231
+ width: 33.333%;
232
+ padding-left: 28px;
233
+ }
234
+ #WBCR .wio-columns .col-2-3 {
235
+ width: 66.666%;
236
+ padding-left: 28px;
237
+ }
238
+ #WBCR .wio-columns .col-1-2 {
239
+ width: 50%;
240
+ padding: 0 20px;
241
+ }
242
+ #WBCR .wio-columns .col-statistics.col-statistics {
243
+ width: 60%;
244
+ }
245
+ #WBCR .wio-columns .col-chart.col-chart {
246
+ width: 40%;
247
+ position: relative;
248
+ padding: 20px;
249
+ font-size: 12px;
250
+ text-transform: uppercase;
251
+ background: #f1f1f1b3;
252
+ color: #abacaf;
253
+ font-weight: bold;
254
+ border-radius: 5px;
255
+ margin-top: 10px;
256
+ text-align: left;
257
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
258
+ }
259
+ #WBCR .wio-col {
260
+ float: left;
261
+ width: 50%;
262
+ box-sizing: border-box;
263
+ -webkit-flex-basis: 50%;
264
+ -ms-flex-preferred-size: 50%;
265
+ flex-basis: 50%;
266
+ }
267
+ #WBCR .wio-col {
268
+ padding-right: 20px;
269
+ }
270
+ #WBCR .wio-col + .wio-col {
271
+ padding-right: 0;
272
+ padding-left: 50px;
273
+ }
274
+ #WBCR .wio-col:target {
275
+ animation: wiohello 1s 3 linear backwards;
276
+ }
277
+ #WBCR .wio-number-you-optimized {
278
+ margin-bottom: 1.35em;
279
+ overflow: hidden;
280
+ }
281
+ #WBCR .wio-number-you-optimized #wio-total-optimized-attachments-pct {
282
+ color: #828282;
283
+ }
284
+ #WBCR .wio-number-you-optimized .wio-number {
285
+ display: table-cell;
286
+ padding-right: 15px;
287
+ font-size: 48px;
288
+ font-weight: bold;
289
+ line-height: 1;
290
+ vertical-align: middle;
291
+ white-space: nowrap;
292
+ color: #828282;
293
+ }
294
+ #WBCR .wio-number-you-optimized .wio-text {
295
+ display: table-cell;
296
+ vertical-align: middle;
297
+ overflow: hidden;
298
+ font-size: 12px;
299
+ color: #828282;
300
+ }
301
+ #WBCR .wio-number-you-optimized > p {
302
+ display: table;
303
+ }
304
+ #WBCR .wio-bars {
305
+ padding-right: 15px;
306
+ }
307
+ #WBCR .wio-bars p {
308
+ font-size: 12px;
309
+ margin-bottom: 5px;
310
+ }
311
+ #WBCR .wio-bars + .wio-number-you-optimized {
312
+ border-bottom: 0;
313
+ padding-top: 0.85em;
314
+ }
315
+ #WBCR .wio-bars + .wio-number-you-optimized p {
316
+ color: #72a53b;
317
+ }
318
+ #WBCR .wio-bar-negative .wio-progress {
319
+ background: #D2D3D6;
320
+ }
321
+ #WBCR .wio-bar-negative .wio-barnb {
322
+ color: #9d9fa5;
323
+ }
324
+ #WBCR .wio-progress {
325
+ height: 8px;
326
+ transition: width 0.3s;
327
+ /*.wio-bar-negative {
328
+ width: 92% !important;
329
+ }*/
330
+ }
331
+ #WBCR .wio-bar-positive .wio-progress {
332
+ background: #8CC152;
333
+ }
334
+ #WBCR .wio-bar-positive .wio-barnb {
335
+ color: #72a53b;
336
+ }
337
+ #WBCR .wio-bar-primary .wio-progress {
338
+ background: #8CC152;
339
+ }
340
+ #WBCR .wio-bar-primary .wio-barnb {
341
+ color: #72a53b;
342
+ }
343
+ #WBCR .wio-right-outside-number .wio-barnb {
344
+ display: block;
345
+ margin-right: -5.25em;
346
+ text-align: right;
347
+ font-weight: bold;
348
+ line-height: 0.8;
349
+ }
350
+ #WBCR .wio-chart {
351
+ position: relative;
352
+ top: 1px;
353
+ display: inline-block;
354
+ vertical-align: middle;
355
+ }
356
+ #WBCR .wio-chart-container {
357
+ position: relative;
358
+ display: inline-block;
359
+ margin-right: 5px;
360
+ }
361
+ #WBCR .wio-chart-container canvas {
362
+ display: block;
363
+ }
364
+ #WBCR .wio-overview-chart-container {
365
+ float: left;
366
+ margin-right: 20px;
367
+ }
368
+ #WBCR .wio-chart-percent {
369
+ position: absolute;
370
+ left: 0;
371
+ right: 0;
372
+ top: 50%;
373
+ margin-top: -0.5em;
374
+ line-height: 0.8;
375
+ text-align: center;
376
+ font-size: 54px;
377
+ font-weight: bold;
378
+ color: #afafaf;
379
+ }
380
+ #WBCR .wio-chart-percent span {
381
+ font-size: 20px;
382
+ vertical-align: super;
383
+ }
384
+ #WBCR #wio-overview-chart-legend {
385
+ overflow: hidden;
386
+ }
387
+ #WBCR .wio-doughnut-legend li {
388
+ display: inline-block;
389
+ position: relative;
390
+ margin-bottom: 15px;
391
+ border-radius: 5px;
392
+ padding: 3px 8px 2px 31px;
393
+ font-size: 9px;
394
+ cursor: default;
395
+ -webkit-transition: background-color 200ms ease-in-out;
396
+ -moz-transition: background-color 200ms ease-in-out;
397
+ -o-transition: background-color 200ms ease-in-out;
398
+ transition: background-color 200ms ease-in-out;
399
+ }
400
+ #WBCR .wio-doughnut-legend li span {
401
+ display: block;
402
+ position: absolute;
403
+ left: 0;
404
+ top: 0;
405
+ width: 25px;
406
+ height: 25px;
407
+ border-radius: 50%;
408
+ }
409
+ #WBCR .wio-optimize-button {
410
+ min-width: 180px;
411
+ padding: 12px 30px;
412
+ background: #c9deb2;
413
+ color: #586549;
414
+ border: 0;
415
+ box-shadow: none;
416
+ font-size: 14px;
417
+ text-transform: uppercase !important;
418
+ font-weight: bold;
419
+ border-radius: 4px;
420
+ outline: none;
421
+ }
422
+ #WBCR .wio-optimize-button:active {
423
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
424
+ }
425
+ #WBCR .wio-optimize-button:disabled {
426
+ background: #e2edd6;
427
+ color: #a5b295;
428
+ }
429
+ #WBCR .wio-optimize-button.wio-running {
430
+ color: #a57b3c;
431
+ background: #fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
432
+ padding-left: 50px;
433
+ }
434
+ #WBCR .wio-global-optim-phrase {
435
+ width: 180px;
436
+ padding-top: 20px;
437
+ font-size: 14px;
438
+ text-align: center;
439
+ }
440
+ #WBCR .wio-total-percent {
441
+ color: #587f2e;
442
+ }
443
+ #WBCR #wio-start-msg-top,
444
+ #WBCR #wio-start-msg-right,
445
+ #WBCR #wio-start-msg-complete {
446
+ display: none;
447
+ }
448
+ #WBCR .wio-text-left {
449
+ text-align: left;
450
+ }
451
+ #WBCR span.wio-num {
452
+ display: inline !important;
453
+ position: inherit !important;
454
+ }
455
+ #WBCR .wio-image-optimize-board {
456
+ padding-bottom: 0 !important;
457
+ }
458
+ #WBCR .wio-page-statistic {
459
+ padding-left: 40px;
460
+ }
461
+ #WBCR .wio-page-statistic .wio-chart-percent {
462
+ margin-top: -1.1em;
463
+ }
464
+ #WBCR .wrio-optimization-progress {
465
+ background: none;
466
+ padding: 0;
467
+ /*button {
468
+ padding: 5px 10px;
469
+ border: 0;
470
+ font-size: 11px;
471
+ text-transform: uppercase !important;
472
+ font-weight: bold;
473
+ border-radius: 4px;
474
+ outline: none;
475
+ background: @greyButtonBg;
476
+ color: @greyButtonColor;
477
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
478
+
479
+ &:active {
480
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
481
+ }
482
+
483
+ &.wbcr-rio-loading {
484
+ width: 56px;
485
+ font-size: 0;
486
+ background: @greyButtonBg url("../img/quick-start-loader.gif") center no-repeat;
487
+ }
488
+
489
+ &.wbcr-rio-selected {
490
+ background: #f3efe2;
491
+ color: #d8d8d8;
492
+
493
+ &:active {
494
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
495
+ }
496
+ }
497
+ }*/
498
+ }
499
+ #WBCR .wrio-optimization-progress h4 {
500
+ font-size: 15px;
501
+ font-weight: 700;
502
+ }
503
+ #WBCR .wrio-optimization-progress .wbcr-rio-warning-message {
504
+ padding: 20px;
505
+ background: #efefef;
506
+ font-size: 15px;
507
+ color: #b7b7b7;
508
+ font-style: italic;
509
+ }
510
+ #WBCR .wio-widget {
511
+ padding: 0 !important;
512
+ }
513
+ #WBCR .wio-widget .wio-chart-percent {
514
+ font-size: 44px;
515
+ line-height: 1;
516
+ }
517
+ #WBCR .wio-widget .wio-bars {
518
+ width: 60%;
519
+ margin-left: 155px;
520
+ }
521
+ #WBCR .wio-widget .col-chart.col-chart {
522
+ width: 100%;
523
+ }
524
+ #WBCR .wio-widget .col-controls {
525
+ width: 45%;
526
+ padding-left: 5px;
527
+ padding-top: 110px;
528
+ }
529
+ #WBCR .wio-widget .wio-doughnut-legend {
530
+ /*padding-top:30px;*/
531
+ text-align: left;
532
+ }
533
+ #WBCR .wio-widget .wio-widget-bottom {
534
+ display: table;
535
+ padding-top: 20px !important;
536
+ width: 100%;
537
+ text-align: right;
538
+ }
539
+ #WBCR .wio-widget .wio-widget-bottom li {
540
+ display: table-cell;
541
+ }
542
+ #WBCR .wio-widget .wio-widget-bottom li:first-child {
543
+ text-align: left;
544
+ }
545
+ #WBCR .factory-checkbox.wrio-checkbox-premium-label:after {
546
+ display: inline-block;
547
+ position: relative;
548
+ content: 'PRO';
549
+ background: #ff5722;
550
+ border-radius: 4px;
551
+ color: #fff;
552
+ font-size: 10px;
553
+ line-height: 1;
554
+ font-style: normal;
555
+ padding: 4px 6px;
556
+ margin-left: 4px;
557
+ vertical-align: top;
558
+ top: -8px;
559
+ left: -10px;
560
+ right: auto;
561
+ z-index: 11;
562
+ }
563
+ #WBCR .factory-checkbox-disabled input,
564
+ #WBCR .factory-checkbox-disabled button {
565
+ pointer-events: none;
566
+ cursor: not-allowed;
567
+ opacity: 0.65;
568
+ filter: alpha(opacity=65);
569
+ -webkit-box-shadow: none;
570
+ box-shadow: none;
571
+ }
572
+ #WBCR #wrio-webp-options h3,
573
+ #WBCR #wrio-error-log-options h3 {
574
+ font-size: 14px;
575
+ margin: 0 0 10px 0;
576
+ font-weight: 600;
577
+ color: #565656;
578
+ }
579
+ #WBCR #wrio-webp-options .wrio-webp-options-info,
580
+ #WBCR #wrio-error-log-options .wrio-webp-options-info {
581
+ color: #8a8787;
582
+ font-size: 12px;
583
+ }
584
+ #WBCR #wrio-webp-options ul,
585
+ #WBCR #wrio-error-log-options ul {
586
+ padding-left: 0;
587
+ }
588
+ #WBCR #wrio-webp-options ul li:after,
589
+ #WBCR #wrio-error-log-options ul li:after {
590
+ content: '';
591
+ display: block;
592
+ clear: both;
593
+ }
594
+ #WBCR #wrio-webp-options ul li label,
595
+ #WBCR #wrio-error-log-options ul li label {
596
+ font-weight: 600;
597
+ }
598
+ #WBCR #wrio-webp-options ul li .wrio-webp-options-radio,
599
+ #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio,
600
+ #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox,
601
+ #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox {
602
+ display: block;
603
+ float: left;
604
+ margin-top: 2px;
605
+ margin-right: 8px;
606
+ }
607
+ #WBCR #wrio-webp-options ul li .wrio-webp-options-radio:focus,
608
+ #WBCR #wrio-error-log-options ul li .wrio-webp-options-radio:focus,
609
+ #WBCR #wrio-webp-options ul li .wrio-error-log-options-checkbox:focus,
610
+ #WBCR #wrio-error-log-options ul li .wrio-error-log-options-checkbox:focus {
611
+ outline: none;
612
+ box-shadow: none;
613
+ }
614
+ #WBCR #wrio-webp-options ul li .wrio-webp-options-info,
615
+ #WBCR #wrio-error-log-options ul li .wrio-webp-options-info,
616
+ #WBCR #wrio-webp-options ul li .wrio-error-log-options-info,
617
+ #WBCR #wrio-error-log-options ul li .wrio-error-log-options-info {
618
+ padding-left: 25px;
619
+ }
620
+ @media (max-width: 830px) {
621
+ #WBCR .wio [class^="col-"] {
622
+ float: none;
623
+ margin-bottom: 1.5em;
624
+ }
625
+ #WBCR .wio .col-1-3,
626
+ #WBCR .wio .col-1-2 {
627
+ width: auto;
628
+ padding: 0 28px;
629
+ clear: both;
630
+ padding-top: 1em;
631
+ }
632
+ }
633
+ @keyframes wiohello {
634
+ 0%,
635
+ 100% {
636
+ background: #FFF;
637
+ }
638
+ 50% {
639
+ background: #F4F7F9;
640
+ }
641
+ }
642
+ @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
643
+ #WBCR .wio-columns .col-statistics.col-statistics,
644
+ #WBCR .wio-columns .col-chart.col-chart {
645
+ width: 50%;
646
+ }
647
+ }
648
+ @media (max-width: 808px) {
649
+ #WBCR .wio-columns .col-statistics.col-statistics,
650
+ #WBCR .wio-columns .col-chart.col-chart {
651
+ width: auto;
652
+ float: none;
653
+ padding: 0;
654
+ }
655
+ #WBCR .wio-columns .col-chart.col-chart {
656
+ margin-top: 3em;
657
+ }
658
+ }
659
  /*# sourceMappingURL=base-statistic.css.map */
admin/assets/css/base-statistic.css.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["base-statistic.less"],"names":[],"mappings":";;;;;;AAuBA;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,KAoBE;EACE,WAAA;;AArBJ,KA2BE;AA3BF,KA2B0C;EACtC,wBAAA;;AA5BJ,KAiCE;EACE,SAAA;EAEA,mBAAA;;AApCJ,KAiCE,oBAKE;EACE,SAAA;;AAvCN,KAiCE,oBAKE,GAGE;EACE,kBAAA;EACA,qBAAA;EAEA,eAAA;EACA,mBAAA;EACA,4BAAA;;AAEA,KAhBN,oBAKE,GAGE,GAQG;EACC,mBAAA;;AAGF,KApBN,oBAKE,GAGE,GAYG;EAEC,mBAAA;EACA,6BAAA;EACA,8BAAA;EACA,+BAAA;EACA,gCAAA;EACA,mBAAA;;AAPF,KApBN,oBAKE,GAGE,GAYG,OASC;EACE,WAAA;;AAVJ,KApBN,oBAKE,GAGE,GAYG,OASC,EAGE;EACE,0BAAA;EACA,cAAA;;AAdN,KApBN,oBAKE,GAGE,GAYG,OAkBC;AAlBF,KApBN,oBAKE,GAGE,GAYG,OAkBa,kBAAiB;EAC3B,cAAA;;AAxEZ,KAiCE,oBAKE,GAGE,GAmCE;EACE,cAAA;EACA,4BAAA;EACA,qBAAA;EACA,cAAA;EACA,eAAA;EACA,cAAA;;AAEA,KAnDR,oBAKE,GAGE,GAmCE,oBAQG;AAAS,KAnDlB,oBAKE,GAGE,GAmCE,oBAQa;EACT,aAAA;EACA,gBAAA;EACA,aAAA;;AAvFZ,KAiCE,oBAKE,GAGE,GAmCE,oBAcE;AA1FV,KAiCE,oBAKE,GAGE,GAmCE,oBAcc,kBAAiB;EAC3B,qBAAA;EACA,WAAA;EACA,YAAA;EACA,eAAA;EACA,gBAAA;EACA,kBAAA;EACA,cAAA;;AAjGZ,KAiCE,oBAKE,GAGE,GAmCE,oBAyBE;EACE,qBAAA;EACA,WAAA;EACA,YAAA;EACA,oBAAA;EACA,0BAAA;EACA,YAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,kBAAA;EACA,cAAA;;AAhHZ,KAiCE,oBAKE,GAGE,GA2EE,kCAAiC;EAlHrC,qBAAA;EACA,kBAAA;EACA,SAAS,KAAT;EACA,mBAAA;EACA,kBAAA;EACA,WAAA;EACA,eAAA;EACA,cAAA;EACA,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,mBAAA;EACA,SAAA;EACA,UAAA;EACA,WAAA;EACA,WAAA;;AAjBJ,KA4HE;EACE,WAAA;EACA,mBAAA;EACA,sBAAA;EACA,mBAAA;EACA,gBAAA;EACA,8BAAA;;AAlIJ,KA4HE,YAQE;AApIJ,KA4HE,YAQM;EACF,kBAAA;EACA,kBAAA;;AAtIN,KA4HE,YAaE;EACE,mBAAA;EACA,cAAA;EACA,2BAAA;;AAEA,KAlBJ,YAaE,GAKG,UAAU;EACT,mBAAA;;AA/IR,KA4HE,YAuBE,GAAE;EACA,oCAAA;;AApJN,KA4HE,YA2BE;EACE,gBAAgB,wDAAhB;;AAxJN,KA4HE,YA+BE;EACE,qBAAA;EACA,gBAAA;EACA,mBAAA;;AA9JN,KA4HE,YAqCE;EACE,cAAA;;AAlKN,KA4HE,YAyCE;EACE,cAAA;;AAtKN,KA4HE,YA6CE;EACE,cAAA;;AAGF,KAjDF,YAiDG,uBACC,GAAE,UAAU;EACV,gBAAA;;AA/KR,KAoLE;EACE,kBAAA;;AArLJ,KAoLE,cAGE,MACE;EACE,cAAA;EACA,mBAAA;EACA,eAAA;EACA,cAAA;;AA5LR,KAoLE,cAYE;EACE,kBAAA;EACA,gBAAA;EACA,kBAAA;EACA,gBAAA;EACA,yBAAA;EACA,mBAAA;;AAtMN,KAoLE,cAqBE;EACE,aAAA;EACA,aAAA;EACA,gBAAA;;AA5MN,KAoLE,cA2BE;EACE,eAAA;;AAhNN,KAoLE,cA2BE,yBAGE;EACE,uBAAA;EACA,WAAA;EACA,gBAAA;EACA,kBAAA;;AAEA,KApCN,cA2BE,yBAGE,oBAMG;EACC,mBAAA;;AAGF,KAxCN,cA2BE,yBAGE,oBAUG;EACC,mBAAA;;AAGF,KA5CN,cA2BE,yBAGE,oBAcG;EACC,qBAAA;EACA,YAAA;EACA,WAAA;EACA,gBAAgB,iDAAhB;;AApOV,KA0OE;EACE,gBAAA;EACA,eAAA;EACA,mBAAA;;AA7OJ,KA0OE,aAKE;EACE,WAAA;EACA,8BAAA;EACA,2BAAA;EACA,sBAAA;;AAnPN,KA0OE,aAYE;EACE,cAAA;EACA,kBAAA;;AAxPN,KA0OE,aAiBE;EACE,cAAA;EACA,kBAAA;;AA7PN,KA0OE,aAsBE;EACE,UAAA;EACA,eAAA;;AAlQN,KA0OE,aA2BE,gBAAe;EACb,UAAA;;AAtQN,KA0OE,aA+BE,WAAU;EACR,UAAA;EACA,kBAAA;EACA,aAAA;EACA,eAAA;EACA,yBAAA;EACA,qBAAA;EACA,cAAA;EACA,iBAAA;EACA,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,wCAAA;;AArRN,KAyRE;EACE,WAAA;EACA,UAAA;EACA,sBAAA;EACA,uBAAA;EACA,4BAAA;EACA,eAAA;;AA/RJ,KAkSE;EACE,mBAAA;;AAnSJ,KAsSE,SAAS;EACP,gBAAA;EACA,kBAAA;;AAxSJ,KA2SE,SAAQ;EACN,yCAAA;;AA5SJ,KA+SE;EACE,qBAAA;EACA,gBAAA;;AAjTJ,KA+SE,0BAIE;EACE,cAAA;;AApTN,KA+SE,0BAQE;EACE,mBAAA;EACA,mBAAA;EACA,eAAA;EACA,iBAAA;EACA,cAAA;EACA,sBAAA;EACA,mBAAA;EACA,cAAA;;AA/TN,KA+SE,0BAmBE;EACE,mBAAA;EACA,sBAAA;EACA,gBAAA;EACA,eAAA;EACA,cAAA;;AAGF,KA3BF,0BA2BI;EACA,cAAA;;AA3UN,KA+UE;EACE,mBAAA;;AAhVJ,KAmVE,UAAU;EACR,eAAA;EACA,kBAAA;;AArVJ,KAwVE,UAAU;EACR,gBAAA;EACA,mBAAA;;AA1VJ,KA6VE,UAAU,4BAA4B;EACpC,cAAA;;AA9VJ,KAiWE,kBACE;EACE,mBAAA;;AAnWN,KAiWE,kBAKE;EACE,cAAA;;AAvWN,KA2WE;EACE,WAAA;EACA,qBAAA;;;;;AA7WJ,KAoXE,kBACE;EACE,mBAAA;;AAtXN,KAoXE,kBAKE;EACE,cAAA;;AA1XN,KA8XE,iBACE;EACE,mBAAA;;AAhYN,KA8XE,iBAKE;EACE,cAAA;;AApYN,KAwYE,0BAA0B;EACxB,cAAA;EACA,qBAAA;EACA,iBAAA;EACA,iBAAA;EACA,eAAA;;AA7YJ,KAkZE;EACE,kBAAA;EACA,QAAA;EACA,qBAAA;EACA,sBAAA;;AAtZJ,KAyZE;EACE,kBAAA;EACA,qBAAA;EACA,iBAAA;;AA5ZJ,KA+ZE,qBAAqB;EACnB,cAAA;;AAhaJ,KAmaE;EACE,WAAA;EACA,kBAAA;;AAraJ,KAwaE;EACE,kBAAA;EACA,OAAA;EACA,QAAA;EACA,QAAA;EACA,kBAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,iBAAA;EACA,cAAA;;AAlbJ,KAqbE,mBAAmB;EACjB,eAAA;EACA,qBAAA;;AAvbJ,KA0bE;EACE,gBAAA;;AA3bJ,KA8bE,qBAAqB;EACnB,qBAAA;EACA,kBAAA;EACA,mBAAA;EACA,kBAAA;EACA,yBAAA;EACA,cAAA;EACA,eAAA;EACA,sDAAA;EACA,mDAAA;EACA,iDAAA;EACA,8CAAA;;AAzcJ,KA4cE,qBAAqB,GAAG;EACtB,cAAA;EACA,kBAAA;EACA,OAAA;EACA,MAAA;EACA,WAAA;EACA,YAAA;EACA,kBAAA;;AAndJ,KAsdE;EACE,gBAAA;EACA,kBAAA;EACA,mBAAA;EACA,cAAA;EACA,SAAA;EACA,gBAAA;EACA,eAAA;EACA,oCAAA;EACA,iBAAA;EACA,kBAAA;EACA,aAAA;;AAEA,KAbF,qBAaG;EACC,8CAAA;;AAGF,KAjBF,qBAiBG;EACC,mBAAA;EACA,cAAA;;AAGF,KAtBF,qBAsBG;EACC,cAAA;EACA,wBAAgC,mDAAhC;EACA,kBAAA;;AA/eN,KAmfE;EACE,YAAA;EACA,iBAAA;EACA,eAAA;EACA,kBAAA;;AAvfJ,KA0fE;EACE,cAAA;;AA3fJ,KA8fE;AA9fF,KA8fsB;AA9ftB,KA8f4C;EACxC,aAAA;;AA/fJ,KAkgBE;EACE,gBAAA;;AAngBJ,KAsgBE,KAAI;EACF,0BAAA;EACA,4BAAA;;AAxgBJ,KA8gBE;EACE,4BAAA;;AA/gBJ,KAkhBE;EACE,kBAAA;;AAnhBJ,KAkhBE,oBAGE;EACE,kBAAA;;AAthBN,KA0hBE;EAEE,gBAAA;EACA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA7hBJ,KA0hBE,4BAKE;EACE,eAAA;EACA,gBAAA;;AAjiBN,KA0hBE,4BA0CE;EACE,aAAA;EACA,mBAAA;EACA,eAAA;EACA,cAAA;EACA,kBAAA;;AAzkBN,KA6kBE;EACE,qBAAA;;AA9kBJ,KA6kBE,YAGE;EACE,eAAA;EACA,cAAA;;AAllBN,KA6kBE,YAQE;EACE,UAAA;EACA,kBAAA;;AAvlBN,KA6kBE,YAaE,WAAU;EACR,WAAA;;AA3lBN,KA6kBE,YAiBE;EACE,UAAA;EACA,iBAAA;EACA,kBAAA;;AAjmBN,KA6kBE,YAuBE;;EAEE,gBAAA;;AAtmBN,KA6kBE,YA4BE;EACE,cAAA;EACA,4BAAA;EACA,WAAA;EACA,iBAAA;;AA7mBN,KA6kBE,YAmCE,mBAAmB;EACjB,mBAAA;;AAjnBN,KA6kBE,YAuCE,mBAAmB,GAAE;EACnB,gBAAA;;AAOF,KADF,kBACG,4BAA4B;EA1nB7B,qBAAA;EACA,kBAAA;EACA,SAAS,KAAT;EACA,mBAAA;EACA,kBAAA;EACA,WAAA;EACA,eAAA;EACA,cAAA;EACA,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,mBAAA;EACA,SAAA;EACA,WAAA;EACA,WAAA;EACA,WAAA;;AAjBJ,KAioBE,2BACE;AAloBJ,KAioBE,2BACS;EACL,oBAAA;EACA,mBAAA;EACA,YAAA;EACA,yBAAA;EACA,wBAAA;EACA,gBAAA;;AAxoBN,KA4oBE,mBACE;AA7oBJ,KA4oBsB,wBAClB;EACE,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,cAAA;;AAjpBN,KA4oBE,mBAQE;AAppBJ,KA4oBsB,wBAQlB;EACE,cAAA;EACA,eAAA;;AAtpBN,KA4oBE,mBAaE;AAzpBJ,KA4oBsB,wBAalB;EACE,eAAA;;AAGE,KAjBN,mBAaE,GAGE,GACG;AAAD,KAjBc,wBAalB,GAGE,GACG;EACC,SAAS,EAAT;EACA,cAAA;EACA,WAAA;;AAhqBV,KA4oBE,mBAaE,GAGE,GAOE;AAnqBR,KA4oBsB,wBAalB,GAGE,GAOE;EACE,gBAAA;;AApqBV,KA4oBE,mBAaE,GAGE,GAWE;AAvqBR,KA4oBsB,wBAalB,GAGE,GAWE;AAvqBR,KA4oBE,mBAaE,GAGE,GAW4B;AAvqBlC,KA4oBsB,wBAalB,GAGE,GAW4B;EACxB,cAAA;EACA,WAAA;EACA,eAAA;EACA,iBAAA;;AAEA,KAjCR,mBAaE,GAGE,GAWE,yBAMG;AAAD,KAjCY,wBAalB,GAGE,GAWE,yBAMG;AAAD,KAjCR,mBAaE,GAGE,GAW4B,iCAMvB;AAAD,KAjCY,wBAalB,GAGE,GAW4B,iCAMvB;EACC,aAAA;EACA,gBAAA;;AA/qBZ,KA4oBE,mBAaE,GAGE,GAuBE;AAnrBR,KA4oBsB,wBAalB,GAGE,GAuBE;AAnrBR,KA4oBE,mBAaE,GAGE,GAuB2B;AAnrBjC,KA4oBsB,wBAalB,GAGE,GAuB2B;EACvB,kBAAA;;AAWR,QAA0B;EAqE5B,KApEI,KAAK;IACH,WAAA;IACA,oBAAA;;EAkEN,KA/DI,KAAK;EA+DT,KA9DI,KAAK;IACH,WAAA;IACA,eAAA;IACA,WAAA;IACA,gBAAA;;;AAIJ;EACE;EAAI;IACF,gBAAA;;EAEF;IACE,mBAAA;;;AAIJ,QAA2B,wBAAuB,qBAAsB;EA6C1E,KA5CI,aACE,gBAAe;EA2CrB,KA5CI,aACkC,WAAU;IACxC,UAAA;;;AAMN,QAA0B;EAoC5B,KAnCI,aACE,gBAAe;EAkCrB,KAnCI,aACkC,WAAU;IACxC,WAAA;IACA,WAAA;IACA,UAAA;;EA+BR,KAnCI,aAOE,WAAU;IACR,eAAA","file":"base-statistic.css"}
1
+ {"version":3,"sources":["base-statistic.less"],"names":[],"mappings":";;;;;;AAuBA;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,KAoBE;EACE,WAAA;;AArBJ,KA2BE;AA3BF,KA2B0C;EACtC,wBAAA;;AA5BJ,KAiCE;EACE,SAAA;EAEA,mBAAA;;AApCJ,KAiCE,oBAKE;EACE,SAAA;;AAvCN,KAiCE,oBAKE,GAGE;EACE,kBAAA;EACA,qBAAA;EAEA,eAAA;EACA,mBAAA;EACA,4BAAA;;AAEA,KAhBN,oBAKE,GAGE,GAQG;EACC,mBAAA;;AAGF,KApBN,oBAKE,GAGE,GAYG;EAEC,mBAAA;EACA,6BAAA;EACA,8BAAA;EACA,+BAAA;EACA,gCAAA;EACA,mBAAA;;AAPF,KApBN,oBAKE,GAGE,GAYG,OASC;EACE,WAAA;;AAVJ,KApBN,oBAKE,GAGE,GAYG,OASC,EAGE;EACE,0BAAA;EACA,cAAA;;AAdN,KApBN,oBAKE,GAGE,GAYG,OAkBC;AAlBF,KApBN,oBAKE,GAGE,GAYG,OAkBa,kBAAiB;EAC3B,cAAA;;AAxEZ,KAiCE,oBAKE,GAGE,GAmCE;EACE,cAAA;EACA,4BAAA;EACA,qBAAA;EACA,cAAA;EACA,eAAA;EACA,cAAA;;AAEA,KAnDR,oBAKE,GAGE,GAmCE,oBAQG;AAAS,KAnDlB,oBAKE,GAGE,GAmCE,oBAQa;EACT,aAAA;EACA,gBAAA;EACA,aAAA;;AAvFZ,KAiCE,oBAKE,GAGE,GAmCE,oBAcE;AA1FV,KAiCE,oBAKE,GAGE,GAmCE,oBAcc,kBAAiB;EAC3B,qBAAA;EACA,WAAA;EACA,YAAA;EACA,eAAA;EACA,gBAAA;EACA,kBAAA;EACA,cAAA;;AAjGZ,KAiCE,oBAKE,GAGE,GAmCE,oBAyBE;EACE,qBAAA;EACA,WAAA;EACA,YAAA;EACA,oBAAA;EACA,0BAAA;EACA,YAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,kBAAA;EACA,cAAA;;AAhHZ,KAiCE,oBAKE,GAGE,GA2EE,kCAAiC;EAlHrC,qBAAA;EACA,kBAAA;EACA,SAAS,KAAT;EACA,mBAAA;EACA,kBAAA;EACA,WAAA;EACA,eAAA;EACA,cAAA;EACA,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,mBAAA;EACA,SAAA;EACA,UAAA;EACA,WAAA;EACA,WAAA;;AAjBJ,KA4HE;EACE,WAAA;EACA,mBAAA;EACA,sBAAA;EACA,mBAAA;EACA,gBAAA;EACA,8BAAA;;AAlIJ,KA4HE,YAQE;AApIJ,KA4HE,YAQM;EACF,kBAAA;EACA,kBAAA;;AAtIN,KA4HE,YAaE;EACE,mBAAA;EACA,cAAA;EACA,2BAAA;;AAEA,KAlBJ,YAaE,GAKG,UAAU;EACT,mBAAA;;AA/IR,KA4HE,YAuBE,GAAE;EACA,yBAAA;;AApJN,KA4HE,YA2BE;EACE,gBAAgB,wDAAhB;;AAxJN,KA4HE,YA+BE;EACE,qBAAA;EACA,gBAAA;EACA,mBAAA;;AA9JN,KA4HE,YAqCE;EACE,cAAA;;AAlKN,KA4HE,YAyCE;EACE,cAAA;;AAtKN,KA4HE,YA6CE;EACE,cAAA;;AAGF,KAjDF,YAiDG,uBACC,GAAE,UAAU;EACV,gBAAA;;AA/KR,KAoLE;EACE,kBAAA;;AArLJ,KAoLE,cAGE,MACE;EACE,cAAA;EACA,mBAAA;EACA,eAAA;EACA,cAAA;;AA5LR,KAoLE,cAYE;EACE,kBAAA;EACA,qBAAA;EACA,gBAAA;EACA,kBAAA;EACA,gBAAA;EACA,yBAAA;EACA,mBAAA;;AAvMN,KAoLE,cAsBE;EACE,aAAA;EACA,aAAA;EACA,gBAAA;;AA7MN,KAoLE,cA4BE;EACE,qBAAA;EACA,eAAA;;AAlNN,KAoLE,cA4BE,yBAIE;EACE,uBAAA;EACA,WAAA;EACA,gBAAA;EACA,kBAAA;;AAEA,KAtCN,cA4BE,yBAIE,oBAMG;EACC,mBAAA;;AAGF,KA1CN,cA4BE,yBAIE,oBAUG;EACC,mBAAA;;AAGF,KA9CN,cA4BE,yBAIE,oBAcG;EACC,qBAAA;EACA,YAAA;EACA,WAAA;EACA,gBAAgB,iDAAhB;;AAtOV,KA4OE;EACE,gBAAA;EACA,eAAA;EACA,mBAAA;;AA/OJ,KA4OE,aAKE;EACE,WAAA;EACA,8BAAA;EACA,2BAAA;EACA,sBAAA;;AArPN,KA4OE,aAYE;EACE,cAAA;EACA,kBAAA;;AA1PN,KA4OE,aAiBE;EACE,cAAA;EACA,kBAAA;;AA/PN,KA4OE,aAsBE;EACE,UAAA;EACA,eAAA;;AApQN,KA4OE,aA2BE,gBAAe;EACb,UAAA;;AAxQN,KA4OE,aA+BE,WAAU;EACR,UAAA;EACA,kBAAA;EACA,aAAA;EACA,eAAA;EACA,yBAAA;EACA,qBAAA;EACA,cAAA;EACA,iBAAA;EACA,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,wCAAA;;AAvRN,KA2RE;EACE,WAAA;EACA,UAAA;EACA,sBAAA;EACA,uBAAA;EACA,4BAAA;EACA,eAAA;;AAjSJ,KAoSE;EACE,mBAAA;;AArSJ,KAwSE,SAAS;EACP,gBAAA;EACA,kBAAA;;AA1SJ,KA6SE,SAAQ;EACN,yCAAA;;AA9SJ,KAiTE;EACE,qBAAA;EACA,gBAAA;;AAnTJ,KAiTE,0BAIE;EACE,cAAA;;AAtTN,KAiTE,0BAQE;EACE,mBAAA;EACA,mBAAA;EACA,eAAA;EACA,iBAAA;EACA,cAAA;EACA,sBAAA;EACA,mBAAA;EACA,cAAA;;AAjUN,KAiTE,0BAmBE;EACE,mBAAA;EACA,sBAAA;EACA,gBAAA;EACA,eAAA;EACA,cAAA;;AAGF,KA3BF,0BA2BI;EACA,cAAA;;AA7UN,KAiVE;EACE,mBAAA;;AAlVJ,KAqVE,UAAU;EACR,eAAA;EACA,kBAAA;;AAvVJ,KA0VE,UAAU;EACR,gBAAA;EACA,mBAAA;;AA5VJ,KA+VE,UAAU,4BAA4B;EACpC,cAAA;;AAhWJ,KAmWE,kBACE;EACE,mBAAA;;AArWN,KAmWE,kBAKE;EACE,cAAA;;AAzWN,KA6WE;EACE,WAAA;EACA,sBAAA;;;;;AA/WJ,KAsXE,kBACE;EACE,mBAAA;;AAxXN,KAsXE,kBAKE;EACE,cAAA;;AA5XN,KAgYE,iBACE;EACE,mBAAA;;AAlYN,KAgYE,iBAKE;EACE,cAAA;;AAtYN,KA0YE,0BAA0B;EACxB,cAAA;EACA,qBAAA;EACA,iBAAA;EACA,iBAAA;EACA,gBAAA;;AA/YJ,KAoZE;EACE,kBAAA;EACA,QAAA;EACA,qBAAA;EACA,sBAAA;;AAxZJ,KA2ZE;EACE,kBAAA;EACA,qBAAA;EACA,iBAAA;;AA9ZJ,KAiaE,qBAAqB;EACnB,cAAA;;AAlaJ,KAqaE;EACE,WAAA;EACA,kBAAA;;AAvaJ,KA0aE;EACE,kBAAA;EACA,OAAA;EACA,QAAA;EACA,QAAA;EACA,kBAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,iBAAA;EACA,cAAA;;AApbJ,KAubE,mBAAmB;EACjB,eAAA;EACA,qBAAA;;AAzbJ,KA4bE;EACE,gBAAA;;AA7bJ,KAgcE,qBAAqB;EACnB,qBAAA;EACA,kBAAA;EACA,mBAAA;EACA,kBAAA;EACA,yBAAA;EACA,cAAA;EACA,eAAA;EACA,sDAAA;EACA,mDAAA;EACA,iDAAA;EACA,8CAAA;;AA3cJ,KA8cE,qBAAqB,GAAG;EACtB,cAAA;EACA,kBAAA;EACA,OAAA;EACA,MAAA;EACA,WAAA;EACA,YAAA;EACA,kBAAA;;AArdJ,KAwdE;EACE,gBAAA;EACA,kBAAA;EACA,mBAAA;EACA,cAAA;EACA,SAAA;EACA,gBAAA;EACA,eAAA;EACA,oCAAA;EACA,iBAAA;EACA,kBAAA;EACA,aAAA;;AAEA,KAbF,qBAaG;EACC,8CAAA;;AAGF,KAjBF,qBAiBG;EACC,mBAAA;EACA,cAAA;;AAGF,KAtBF,qBAsBG;EACC,cAAA;EACA,wBAAgC,mDAAhC;EACA,kBAAA;;AAjfN,KAqfE;EACE,YAAA;EACA,iBAAA;EACA,eAAA;EACA,kBAAA;;AAzfJ,KA4fE;EACE,cAAA;;AA7fJ,KAggBE;AAhgBF,KAggBsB;AAhgBtB,KAggB4C;EACxC,aAAA;;AAjgBJ,KAogBE;EACE,gBAAA;;AArgBJ,KAwgBE,KAAI;EACF,0BAAA;EACA,4BAAA;;AA1gBJ,KAghBE;EACE,4BAAA;;AAjhBJ,KAohBE;EACE,kBAAA;;AArhBJ,KAohBE,oBAGE;EACE,kBAAA;;AAxhBN,KA4hBE;EAEE,gBAAA;EACA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA/hBJ,KA4hBE,4BAKE;EACE,eAAA;EACA,gBAAA;;AAniBN,KA4hBE,4BA0CE;EACE,aAAA;EACA,mBAAA;EACA,eAAA;EACA,cAAA;EACA,kBAAA;;AA3kBN,KA+kBE;EACE,qBAAA;;AAhlBJ,KA+kBE,YAGE;EACE,eAAA;EACA,cAAA;;AAplBN,KA+kBE,YAQE;EACE,UAAA;EACA,kBAAA;;AAzlBN,KA+kBE,YAaE,WAAU;EACR,WAAA;;AA7lBN,KA+kBE,YAiBE;EACE,UAAA;EACA,iBAAA;EACA,kBAAA;;AAnmBN,KA+kBE,YAuBE;;EAEE,gBAAA;;AAxmBN,KA+kBE,YA4BE;EACE,cAAA;EACA,4BAAA;EACA,WAAA;EACA,iBAAA;;AA/mBN,KA+kBE,YAmCE,mBAAmB;EACjB,mBAAA;;AAnnBN,KA+kBE,YAuCE,mBAAmB,GAAE;EACnB,gBAAA;;AAOF,KADF,kBACG,4BAA4B;EA5nB7B,qBAAA;EACA,kBAAA;EACA,SAAS,KAAT;EACA,mBAAA;EACA,kBAAA;EACA,WAAA;EACA,eAAA;EACA,cAAA;EACA,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,mBAAA;EACA,SAAA;EACA,WAAA;EACA,WAAA;EACA,WAAA;;AAjBJ,KAmoBE,2BACE;AApoBJ,KAmoBE,2BACS;EACL,oBAAA;EACA,mBAAA;EACA,aAAA;EACA,yBAAA;EACA,wBAAA;EACA,gBAAA;;AA1oBN,KA8oBE,mBACE;AA/oBJ,KA8oBsB,wBAClB;EACE,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,cAAA;;AAnpBN,KA8oBE,mBAQE;AAtpBJ,KA8oBsB,wBAQlB;EACE,cAAA;EACA,eAAA;;AAxpBN,KA8oBE,mBAaE;AA3pBJ,KA8oBsB,wBAalB;EACE,eAAA;;AAGE,KAjBN,mBAaE,GAGE,GACG;AAAD,KAjBc,wBAalB,GAGE,GACG;EACC,SAAS,EAAT;EACA,cAAA;EACA,WAAA;;AAlqBV,KA8oBE,mBAaE,GAGE,GAOE;AArqBR,KA8oBsB,wBAalB,GAGE,GAOE;EACE,gBAAA;;AAtqBV,KA8oBE,mBAaE,GAGE,GAWE;AAzqBR,KA8oBsB,wBAalB,GAGE,GAWE;AAzqBR,KA8oBE,mBAaE,GAGE,GAW4B;AAzqBlC,KA8oBsB,wBAalB,GAGE,GAW4B;EACxB,cAAA;EACA,WAAA;EACA,eAAA;EACA,iBAAA;;AAEA,KAjCR,mBAaE,GAGE,GAWE,yBAMG;AAAD,KAjCY,wBAalB,GAGE,GAWE,yBAMG;AAAD,KAjCR,mBAaE,GAGE,GAW4B,iCAMvB;AAAD,KAjCY,wBAalB,GAGE,GAW4B,iCAMvB;EACC,aAAA;EACA,gBAAA;;AAjrBZ,KA8oBE,mBAaE,GAGE,GAuBE;AArrBR,KA8oBsB,wBAalB,GAGE,GAuBE;AArrBR,KA8oBE,mBAaE,GAGE,GAuB2B;AArrBjC,KA8oBsB,wBAalB,GAGE,GAuB2B;EACvB,kBAAA;;AAWR,QAA0B;EAA1B,KACE,KAAK;IACH,WAAA;IACA,oBAAA;;EAHJ,KAME,KAAK;EANP,KAOE,KAAK;IACH,WAAA;IACA,eAAA;IACA,WAAA;IACA,gBAAA;;;AAIJ;EACE;EAAI;IACF,gBAAA;;EAEF;IACE,mBAAA;;;AAIJ,QAA2B,wBAAuB,qBAAsB;EAAxE,KACE,aACE,gBAAe;EAFnB,KACE,aACkC,WAAU;IACxC,UAAA;;;AAMN,QAA0B;EAA1B,KACE,aACE,gBAAe;EAFnB,KACE,aACkC,WAAU;IACxC,WAAA;IACA,WAAA;IACA,UAAA;;EALN,KACE,aAOE,WAAU;IACR,eAAA","file":"base-statistic.css"}
admin/assets/css/base-statistic.less CHANGED
@@ -2,7 +2,7 @@
2
  * Styles for the Widget to be displayed in the Clearfy plugin
3
 
4
  * @author Alex Kovalev <alex.kovalevv@gmail.com>
5
- * @copyright Webcraftic 13.06.2018
6
  */
7
 
8
  @positiveColor: #8CC152;
@@ -215,6 +215,7 @@
215
 
216
  #wrio-change-optimization-server {
217
  position: relative;
 
218
  max-width: 400px;
219
  margin-right: 15px;
220
  margin-bottom: 0;
@@ -229,6 +230,7 @@
229
  }
230
 
231
  .wrio-server-status-wrap {
 
232
  margin-top: 8px;
233
 
234
  .wrio-server-status {
2
  * Styles for the Widget to be displayed in the Clearfy plugin
3
 
4
  * @author Alex Kovalev <alex.kovalevv@gmail.com>
5
+ * @copyright Webcraftic 13.06.2019
6
  */
7
 
8
  @positiveColor: #8CC152;
215
 
216
  #wrio-change-optimization-server {
217
  position: relative;
218
+ display: inline-block;
219
  max-width: 400px;
220
  margin-right: 15px;
221
  margin-bottom: 0;
230
  }
231
 
232
  .wrio-server-status-wrap {
233
+ display: inline-block;
234
  margin-top: 8px;
235
 
236
  .wrio-server-status {
admin/assets/js/bulk-optimization.js CHANGED
@@ -24,10 +24,13 @@ jQuery(function($) {
24
  },
25
 
26
  registerEvents: function() {
27
- var self = this;
 
28
 
29
  $('#wrio-change-optimization-server').on('change', function() {
30
  $(this).prop('disabled', true);
 
 
31
  self.checkServerStatus();
32
  });
33
 
@@ -84,15 +87,18 @@ jQuery(function($) {
84
  serverStatus.removeClass('wrio-server-check-proccess');
85
 
86
  if( !response || !response.data || !response.success ) {
 
 
 
87
  if( !response || !response.data ) {
88
- console.log('[Error]: Response error');
89
  console.log(response);
90
- return;
91
  }
 
92
  serverStatus.addClass('wrio-down');
93
- console.log(self.i18n.server_status_down);
94
  serverStatus.text(self.i18n.server_status_down);
95
  self.serverDown = true;
 
 
96
  } else {
97
  serverStatus.addClass('wrio-stable');
98
  serverStatus.text(self.i18n.server_status_stable);
@@ -289,10 +295,10 @@ jQuery(function($) {
289
  throwError: function(error_message) {
290
  this.stop();
291
 
292
- var noticeId = $.wbcr_factory_clearfy_208.app.showNotice(error_message, 'danger');
293
 
294
  setTimeout(function() {
295
- $.wbcr_factory_clearfy_208.app.hideNotice(noticeId);
296
  }, 10000);
297
  },
298
 
@@ -386,8 +392,8 @@ jQuery(function($) {
386
  trEl.addClass('wrio-error');
387
  }
388
 
389
- var preview = $('<img width="40" height="40" src="' + value.url + '" alt="">'),
390
- previewUrl = $('<a href="' + value.url + '">' + value.file_name + '</a>');
391
 
392
  tableEl.prepend(trEl);
393
 
@@ -395,7 +401,8 @@ jQuery(function($) {
395
  trEl.append(tdEl.clone().append(previewUrl));
396
 
397
  if( 'error' === value.type ) {
398
- trEl.append(tdEl.clone().attr('colspan', '5').text("Error: " + value.error_msg));
 
399
  } else {
400
  trEl.append(tdEl.clone().text(value.original_size));
401
  trEl.append(tdEl.clone().text(value.optimized_size));
24
  },
25
 
26
  registerEvents: function() {
27
+ var self = this,
28
+ selectedServer = $("#wrio-change-optimization-server option:selected");
29
 
30
  $('#wrio-change-optimization-server').on('change', function() {
31
  $(this).prop('disabled', true);
32
+
33
+ selectedServer = $(this).find('option:selected');
34
  self.checkServerStatus();
35
  });
36
 
87
  serverStatus.removeClass('wrio-server-check-proccess');
88
 
89
  if( !response || !response.data || !response.success ) {
90
+ console.log('[Error]: Response error');
91
+ response.data && response.data.error && console.log(response.data.error);
92
+
93
  if( !response || !response.data ) {
 
94
  console.log(response);
 
95
  }
96
+
97
  serverStatus.addClass('wrio-down');
 
98
  serverStatus.text(self.i18n.server_status_down);
99
  self.serverDown = true;
100
+
101
+ return;
102
  } else {
103
  serverStatus.addClass('wrio-stable');
104
  serverStatus.text(self.i18n.server_status_stable);
295
  throwError: function(error_message) {
296
  this.stop();
297
 
298
+ var noticeId = $.wbcr_factory_clearfy_216.app.showNotice(error_message, 'danger');
299
 
300
  setTimeout(function() {
301
+ $.wbcr_factory_clearfy_216.app.hideNotice(noticeId);
302
  }, 10000);
303
  },
304
 
392
  trEl.addClass('wrio-error');
393
  }
394
 
395
+ var preview = $('<img width="40" height="40" src="' + value.thumbnail_url + '" alt="">'),
396
+ previewUrl = $('<a href="' + value.url + '" target="_blank">' + value.file_name + '</a>');
397
 
398
  tableEl.prepend(trEl);
399
 
401
  trEl.append(tdEl.clone().append(previewUrl));
402
 
403
  if( 'error' === value.type ) {
404
+ var colspan = value.scope !== 'custom-folders' ? '6' : '5';
405
+ trEl.append(tdEl.clone().attr('colspan', colspan).text("Error: " + value.error_msg));
406
  } else {
407
  trEl.append(tdEl.clone().text(value.original_size));
408
  trEl.append(tdEl.clone().text(value.optimized_size));
admin/boot.php CHANGED
@@ -73,7 +73,7 @@ add_action( 'admin_enqueue_scripts', function () {
73
 
74
  wp_enqueue_script( 'wrio-meta-migrations', WRIO_PLUGIN_URL . '/admin/assets/js/meta-migrations.js', [
75
  'jquery',
76
- 'wbcr-factory-clearfy-208-global'
77
  ], WRIO_Plugin::app()->getPluginVersion() );
78
  } );
79
 
@@ -97,7 +97,7 @@ add_action( 'admin_enqueue_scripts', function () {
97
  *
98
  * @see RIO_Process_Queue for further information about new table.
99
  */
100
- add_action( "wbcr_factory_notices_000_list", function ( $notices ) {
101
 
102
  if ( ! current_user_can( 'update_plugins' ) || ! wbcr_rio_has_meta_to_migrate() ) {
103
  return $notices;
@@ -126,8 +126,8 @@ add_action( "wbcr_factory_notices_000_list", function ( $notices ) {
126
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
127
  * @since 1.3.0
128
  *
129
- * @param Wbcr_Factory412_Plugin $plugin
130
- * @param Wbcr_FactoryPages412_ImpressiveThemplate $obj
131
  *
132
  * @see wbcr_rio_migrate_postmeta_to_process_queue() for further information about AJAX processing function.
133
  * @see wbcr_rio_has_meta_to_migrate() used to check whether to show notice or not.
@@ -146,11 +146,11 @@ add_action( 'wbcr/factory/pages/impressive/print_all_notices', function ( $plugi
146
  * Flush configuration after saving the settings
147
  *
148
  * @param WHM_Plugin $plugin
149
- * @param Wbcr_FactoryPages412_ImpressiveThemplate $obj
150
  *
151
  * @return bool
152
  */
153
- /*add_action('wbcr_factory_412_imppage_after_form_save', function ($plugin, $obj) {
154
  $is_rio = WRIO_Plugin::app()->getPluginName() == $plugin->getPluginName();
155
 
156
  if( $is_rio ) {
@@ -174,14 +174,14 @@ function wio_rating_widget_url( $page_url, $plugin_name ) {
174
  return $page_url;
175
  }
176
 
177
- add_filter( 'wbcr_factory_pages_412_imppage_rating_widget_url', 'wio_rating_widget_url', 10, 2 );
178
 
179
  /**
180
  * Widget with the offer to buy Clearfy Business
181
  *
182
  * @param array $widgets
183
  * @param string $position
184
- * @param Wbcr_Factory412_Plugin $plugin
185
  */
186
  add_filter( 'wbcr/factory/pages/impressive/widgets', function ( $widgets, $position, $plugin ) {
187
  if ( $plugin->getPluginName() == WRIO_Plugin::app()->getPluginName() ) {
@@ -191,27 +191,27 @@ add_filter( 'wbcr/factory/pages/impressive/widgets', function ( $widgets, $posit
191
  unset( $widgets['donate_widget'] );
192
 
193
  if ( $position == 'right' ) {
194
- unset( $widgets['businnes_suggetion'] );
195
  unset( $widgets['rating_widget'] );
196
  unset( $widgets['info_widget'] );
197
  }
198
 
199
- if ( $position == 'bottom' ) {
200
  $widgets['support'] = wrio_get_sidebar_support_widget();
201
- }
202
 
203
  return $widgets;
204
  } else {
205
  if ( $position == 'right' ) {
206
  unset( $widgets['info_widget'] );
207
  unset( $widgets['rating_widget'] );
208
- $widgets['support'] = wrio_get_sidebar_support_widget();
209
  }
210
  }
211
 
212
- if ( $position == 'bottom' ) {
213
- $widgets['donate_widget'] = wrio_get_sidebar_premium_widget();
214
- }
215
  }
216
 
217
  return $widgets;
73
 
74
  wp_enqueue_script( 'wrio-meta-migrations', WRIO_PLUGIN_URL . '/admin/assets/js/meta-migrations.js', [
75
  'jquery',
76
+ 'wbcr-factory-clearfy-216-global'
77
  ], WRIO_Plugin::app()->getPluginVersion() );
78
  } );
79
 
97
  *
98
  * @see RIO_Process_Queue for further information about new table.
99
  */
100
+ add_action( "wbcr/factory/admin_notices", function ( $notices ) {
101
 
102
  if ( ! current_user_can( 'update_plugins' ) || ! wbcr_rio_has_meta_to_migrate() ) {
103
  return $notices;
126
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
127
  * @since 1.3.0
128
  *
129
+ * @param Wbcr_Factory424_Plugin $plugin
130
+ * @param Wbcr_FactoryPages424_ImpressiveThemplate $obj
131
  *
132
  * @see wbcr_rio_migrate_postmeta_to_process_queue() for further information about AJAX processing function.
133
  * @see wbcr_rio_has_meta_to_migrate() used to check whether to show notice or not.
146
  * Flush configuration after saving the settings
147
  *
148
  * @param WHM_Plugin $plugin
149
+ * @param Wbcr_FactoryPages424_ImpressiveThemplate $obj
150
  *
151
  * @return bool
152
  */
153
+ /*add_action('wbcr_factory_424_imppage_after_form_save', function ($plugin, $obj) {
154
  $is_rio = WRIO_Plugin::app()->getPluginName() == $plugin->getPluginName();
155
 
156
  if( $is_rio ) {
174
  return $page_url;
175
  }
176
 
177
+ add_filter( 'wbcr_factory_pages_424_imppage_rating_widget_url', 'wio_rating_widget_url', 10, 2 );
178
 
179
  /**
180
  * Widget with the offer to buy Clearfy Business
181
  *
182
  * @param array $widgets
183
  * @param string $position
184
+ * @param Wbcr_Factory424_Plugin $plugin
185
  */
186
  add_filter( 'wbcr/factory/pages/impressive/widgets', function ( $widgets, $position, $plugin ) {
187
  if ( $plugin->getPluginName() == WRIO_Plugin::app()->getPluginName() ) {
191
  unset( $widgets['donate_widget'] );
192
 
193
  if ( $position == 'right' ) {
194
+ unset( $widgets['business_suggetion'] );
195
  unset( $widgets['rating_widget'] );
196
  unset( $widgets['info_widget'] );
197
  }
198
 
199
+ /*if ( $position == 'bottom' ) {
200
  $widgets['support'] = wrio_get_sidebar_support_widget();
201
+ }*/
202
 
203
  return $widgets;
204
  } else {
205
  if ( $position == 'right' ) {
206
  unset( $widgets['info_widget'] );
207
  unset( $widgets['rating_widget'] );
208
+ //$widgets['support'] = wrio_get_sidebar_support_widget();
209
  }
210
  }
211
 
212
+ //if ( $position == 'bottom' ) {
213
+ //$widgets['donate_widget'] = wrio_get_sidebar_premium_widget();
214
+ //}
215
  }
216
 
217
  return $widgets;
admin/includes/classes/class-rio-optimize-template.php CHANGED
@@ -26,12 +26,12 @@ class WIO_OptimizePageTemplate {
26
  /**
27
  * Выводит контент страницы с учётом мультисайта
28
  *
29
- * @param Wbcr_FactoryClearfy208_PageBase $page
30
  *
31
  * @throws Exception
32
  */
33
 
34
- /*public function showPageContent( Wbcr_FactoryClearfy208_PageBase $page ) {
35
  do_action( 'wbcr/rio/multisite_current_blog' );
36
  $this->pageContent( $page );
37
  do_action( 'wbcr/rio/multisite_restore_blog' );
@@ -174,7 +174,7 @@ class WIO_OptimizePageTemplate {
174
  class="wio-reoptimize button-wio-manual-override-upload"
175
  data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
176
  <span class="dashicons dashicons-admin-generic"></span><span
177
- class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'Normal', 'robin-image-optimizer' ); ?>
178
  <span class="wio-hide-if-small"></span>
179
  </a>
180
  <?php endif; ?>
@@ -184,7 +184,7 @@ class WIO_OptimizePageTemplate {
184
  class="wio-reoptimize button-wio-manual-override-upload"
185
  data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
186
  <span class="dashicons dashicons-admin-generic"></span><span
187
- class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'Medium', 'robin-image-optimizer' ); ?>
188
  <span class="wio-hide-if-small"></span>
189
  </a>
190
  <?php endif; ?>
26
  /**
27
  * Выводит контент страницы с учётом мультисайта
28
  *
29
+ * @param Wbcr_FactoryClearfy216_PageBase $page
30
  *
31
  * @throws Exception
32
  */
33
 
34
+ /*public function showPageContent( Wbcr_FactoryClearfy216_PageBase $page ) {
35
  do_action( 'wbcr/rio/multisite_current_blog' );
36
  $this->pageContent( $page );
37
  do_action( 'wbcr/rio/multisite_restore_blog' );
174
  class="wio-reoptimize button-wio-manual-override-upload"
175
  data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
176
  <span class="dashicons dashicons-admin-generic"></span><span
177
+ class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'lossless', 'robin-image-optimizer' ); ?>
178
  <span class="wio-hide-if-small"></span>
179
  </a>
180
  <?php endif; ?>
184
  class="wio-reoptimize button-wio-manual-override-upload"
185
  data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
186
  <span class="dashicons dashicons-admin-generic"></span><span
187
+ class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'lossy', 'robin-image-optimizer' ); ?>
188
  <span class="wio-hide-if-small"></span>
189
  </a>
190
  <?php endif; ?>
admin/pages/class-rio-license.php CHANGED
@@ -9,7 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) {
9
  *
10
  * @author Alexander Teshabaev <sasha.tesh@gmail.com>
11
  */
12
- class WRIO_License_Page extends Wbcr_FactoryClearfy208_LicensePage {
13
 
14
  /**
15
  * {@inheritdoc}
@@ -43,9 +43,9 @@ class WRIO_License_Page extends Wbcr_FactoryClearfy208_LicensePage {
43
 
44
  /**
45
  * {@inheritdoc}
46
- * @param Wbcr_Factory412_Plugin $plugin
47
  */
48
- public function __construct( Wbcr_Factory412_Plugin $plugin ) {
49
  $this->menu_title = __( 'License', 'robin-image-optimizer' );
50
  $this->page_menu_short_description = __( 'Product activation', 'robin-image-optimizer' );
51
 
9
  *
10
  * @author Alexander Teshabaev <sasha.tesh@gmail.com>
11
  */
12
+ class WRIO_License_Page extends Wbcr_FactoryClearfy216_LicensePage {
13
 
14
  /**
15
  * {@inheritdoc}
43
 
44
  /**
45
  * {@inheritdoc}
46
+ * @param Wbcr_Factory424_Plugin $plugin
47
  */
48
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
49
  $this->menu_title = __( 'License', 'robin-image-optimizer' );
50
  $this->page_menu_short_description = __( 'Product activation', 'robin-image-optimizer' );
51
 
admin/pages/class-rio-log.php CHANGED
@@ -49,6 +49,8 @@ class WRIO_LogPage extends WRIO_Page {
49
  public function assets( $scripts, $styles ) {
50
  parent::assets( $scripts, $styles );
51
 
 
 
52
  // Add Clearfy styles for HMWP pages
53
  if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
54
  $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
@@ -104,10 +106,10 @@ class WRIO_LogPage extends WRIO_Page {
104
 
105
  jQuery('#wbcr-log-viewer').html('');
106
  jQuery('#wbcr-log-size').text('0B');
107
- jQuery.wbcr_factory_clearfy_208.app.showNotice(data.message, data.type);
108
  },
109
  error: function(jqXHR, textStatus, errorThrown) {
110
- jQuery.wbcr_factory_clearfy_208.app.showNotice('Error: ' + errorThrown + ', status: ' + textStatus, 'danger');
111
  btn.html(currentBtnText);
112
  }
113
  });
49
  public function assets( $scripts, $styles ) {
50
  parent::assets( $scripts, $styles );
51
 
52
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
53
+
54
  // Add Clearfy styles for HMWP pages
55
  if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
56
  $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
106
 
107
  jQuery('#wbcr-log-viewer').html('');
108
  jQuery('#wbcr-log-size').text('0B');
109
+ jQuery.wbcr_factory_clearfy_216.app.showNotice(data.message, data.type);
110
  },
111
  error: function(jqXHR, textStatus, errorThrown) {
112
+ jQuery.wbcr_factory_clearfy_216.app.showNotice('Error: ' + errorThrown + ', status: ' + textStatus, 'danger');
113
  btn.html(currentBtnText);
114
  }
115
  });
admin/pages/class-rio-page.php CHANGED
@@ -18,7 +18,7 @@ if ( ! defined( 'ABSPATH' ) ) {
18
  * @copyright (c) 2018, Webcraftic
19
  * @version 1.0
20
  */
21
- class WRIO_Page extends Wbcr_FactoryClearfy208_PageBase {
22
 
23
  /**
24
  * {@inheritdoc}
18
  * @copyright (c) 2018, Webcraftic
19
  * @version 1.0
20
  */
21
+ class WRIO_Page extends Wbcr_FactoryClearfy216_PageBase {
22
 
23
  /**
24
  * {@inheritdoc}
admin/pages/class-rio-settings.php CHANGED
@@ -44,7 +44,7 @@ class WRIO_SettingsPage extends WRIO_Page {
44
  *
45
  * @since 1.0.0
46
  * @return void
47
- * @see Wbcr_FactoryPages412_AdminPage
48
  *
49
  */
50
  public function assets( $scripts, $styles ) {
44
  *
45
  * @since 1.0.0
46
  * @return void
47
+ * @see Wbcr_FactoryPages424_AdminPage
48
  *
49
  */
50
  public function assets( $scripts, $styles ) {
admin/pages/class-rio-statistic.php CHANGED
@@ -226,6 +226,7 @@ class WRIO_StatisticPage extends WRIO_Page {
226
  */
227
  protected function get_i18n() {
228
  return [
 
229
  'server_down_warning' => __( 'Your selected optimization server is down. This means that you cannot optimize images through this server. Try selecting another optimization server.', 'robin-image-optimizer' ),
230
  'server_status_down' => __( 'down', 'robin-image-optimizer' ),
231
  'server_status_stable' => __( 'stable', 'robin-image-optimizer' ),
226
  */
227
  protected function get_i18n() {
228
  return [
229
+ 'premium_server_disabled' => __( 'You cannot use the premium server on a free plan. You must activate the license to use all the features of the premium version.', 'robin-image-optimizer' ),
230
  'server_down_warning' => __( 'Your selected optimization server is down. This means that you cannot optimize images through this server. Try selecting another optimization server.', 'robin-image-optimizer' ),
231
  'server_status_down' => __( 'down', 'robin-image-optimizer' ),
232
  'server_status_stable' => __( 'stable', 'robin-image-optimizer' ),
includes/class-rio-plugin.php CHANGED
@@ -11,23 +11,37 @@ if ( ! defined( 'ABSPATH' ) ) {
11
  * @copyright (c) 19.02.2018, Webcraftic
12
  * @version 1.0
13
  */
14
- class WRIO_Plugin extends Wbcr_Factory412_Plugin {
15
 
16
  /**
17
- * @var Wbcr_Factory412_Plugin
 
18
  */
19
  private static $app;
20
 
21
  /**
 
 
 
 
 
 
 
 
 
 
 
22
  * @param string $plugin_path
23
  * @param array $data
24
  *
25
- * @throws Exception
26
  */
27
  public function __construct( $plugin_path, $data ) {
28
- self::$app = $this;
29
  parent::__construct( $plugin_path, $data );
30
 
 
 
 
31
  $this->includes();
32
 
33
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
@@ -47,6 +61,50 @@ class WRIO_Plugin extends Wbcr_Factory412_Plugin {
47
  add_action( 'plugins_loaded', [ $this, 'pluginsLoaded' ] );
48
  }
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  /**
51
  * Подключаем модули классы и функции
52
  */
@@ -86,15 +144,6 @@ class WRIO_Plugin extends Wbcr_Factory412_Plugin {
86
  new WRIO_Logger();
87
  }
88
 
89
- /**
90
- * Статический метод для быстрого доступа к информации о плагине, а также часто использумых методах.
91
- *
92
- * @return Wbcr_Factory412_Plugin
93
- */
94
- public static function app() {
95
- return self::$app;
96
- }
97
-
98
  /**
99
  * Инициализируем активацию плагина
100
  */
@@ -125,34 +174,5 @@ class WRIO_Plugin extends Wbcr_Factory412_Plugin {
125
  self::app()->registerPage( 'WRIO_LogPage', $admin_path . '/class-rio-log.php' );
126
  }
127
  }
128
-
129
- /**
130
- * Подключаем функции бекенда
131
- *
132
- * @throws Exception
133
- */
134
- public function pluginsLoaded() {
135
- if ( is_admin() || wrio_doing_cron() || wrio_doing_rest_api() ) {
136
- $media_library = WRIO_Media_Library::get_instance();
137
- $media_library->initHooks();
138
- }
139
-
140
- if ( is_admin() ) {
141
- require_once( WRIO_PLUGIN_DIR . '/admin/boot.php' );
142
- //require_once( WRIO_PLUGIN_DIR . '/admin/includes/classes/class-rio-nextgen-landing.php' );
143
-
144
- $this->registerPages();
145
- }
146
-
147
- if ( wrio_doing_cron() || wrio_doing_rest_api() ) {
148
- $media_library = WRIO_Media_Library::get_instance();
149
- $media_library->initHooks();
150
- }
151
-
152
- if ( wrio_is_license_activate() ) {
153
- require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
154
- wrio_premium_load();
155
- }
156
- }
157
  }
158
 
11
  * @copyright (c) 19.02.2018, Webcraftic
12
  * @version 1.0
13
  */
14
+ class WRIO_Plugin extends Wbcr_Factory424_Plugin {
15
 
16
  /**
17
+ * @see self::app()
18
+ * @var Wbcr_Factory424_Plugin
19
  */
20
  private static $app;
21
 
22
  /**
23
+ * @since 3.1.0
24
+ * @var array
25
+ */
26
+ private $plugin_data;
27
+
28
+ /**
29
+ * Конструктор
30
+ *
31
+ * Применяет конструктор родительского класса и записывает экземпляр текущего класса в свойство $app.
32
+ * Подробнее о свойстве $app см. self::app()
33
+ *
34
  * @param string $plugin_path
35
  * @param array $data
36
  *
37
+ * @throws \Exception
38
  */
39
  public function __construct( $plugin_path, $data ) {
 
40
  parent::__construct( $plugin_path, $data );
41
 
42
+ self::$app = $this;
43
+ $this->plugin_data = $data;
44
+
45
  $this->includes();
46
 
47
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
61
  add_action( 'plugins_loaded', [ $this, 'pluginsLoaded' ] );
62
  }
63
 
64
+ /**
65
+ * Статический метод для быстрого доступа к интерфейсу плагина.
66
+ *
67
+ * Позволяет разработчику глобально получить доступ к экземпляру класса плагина в любом месте
68
+ * плагина, но при этом разработчик не может вносить изменения в основной класс плагина.
69
+ *
70
+ * Используется для получения настроек плагина, информации о плагине, для доступа к вспомогательным
71
+ * классам.
72
+ *
73
+ * @return \Wbcr_Factory424_Plugin|\WRIO_Plugin
74
+ */
75
+ public static function app() {
76
+ return self::$app;
77
+ }
78
+
79
+ /**
80
+ * Подключаем функции бекенда
81
+ *
82
+ * @throws Exception
83
+ */
84
+ public function pluginsLoaded() {
85
+ if ( is_admin() || wrio_doing_cron() || wrio_doing_rest_api() ) {
86
+ $media_library = WRIO_Media_Library::get_instance();
87
+ $media_library->initHooks();
88
+ }
89
+
90
+ if ( is_admin() ) {
91
+ require_once( WRIO_PLUGIN_DIR . '/admin/boot.php' );
92
+ //require_once( WRIO_PLUGIN_DIR . '/admin/includes/classes/class-rio-nextgen-landing.php' );
93
+
94
+ $this->registerPages();
95
+ }
96
+
97
+ if ( wrio_doing_cron() || wrio_doing_rest_api() ) {
98
+ $media_library = WRIO_Media_Library::get_instance();
99
+ $media_library->initHooks();
100
+ }
101
+
102
+ if ( wrio_is_license_activate() ) {
103
+ require_once( WRIO_PLUGIN_DIR . '/libs/addons/robin-image-optimizer-premium.php' );
104
+ wrio_premium_load();
105
+ }
106
+ }
107
+
108
  /**
109
  * Подключаем модули классы и функции
110
  */
144
  new WRIO_Logger();
145
  }
146
 
 
 
 
 
 
 
 
 
 
147
  /**
148
  * Инициализируем активацию плагина
149
  */
174
  self::app()->registerPage( 'WRIO_LogPage', $admin_path . '/class-rio-log.php' );
175
  }
176
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  }
178
 
includes/classes/class-rio-attachment.php CHANGED
@@ -8,104 +8,186 @@ if ( ! defined( 'ABSPATH' ) ) {
8
  /**
9
  * Класс для работы с WordPress attachment.
10
  *
11
- * @author Eugene Jokerov <jokerov@gmail.com>
12
  * @copyright (c) 2018, Webcraftic
13
- * @version 1.0
14
  */
15
  class WIO_Attachment {
16
-
17
  /**
18
  * @var int
19
  */
20
  private $id;
21
-
 
22
  /**
23
  * @var array meta-данные
24
  */
25
  private $attachment_meta;
26
-
27
  /**
28
  * @var array массив с данными о папке uploads
29
  */
30
  private $wp_upload_dir;
31
-
32
  /**
33
  * @var string
34
  */
35
  private $url;
36
-
37
  /**
38
  * @var string
39
  */
40
  private $path;
41
-
42
  /**
43
  * @var RIO_Process_Queue
44
  */
45
  private $optimization_data;
46
-
47
  /**
48
  * Инициализация аттачмента
49
  *
50
- * @param int $attachment_id Номер аттачмента из медиабиблиотеки
51
- * @param array|false $attachment_meta метаданные аттачмента. Ключи массива аналогичны функции wp_get_attachment_metadata
52
  */
53
  public function __construct( $attachment_id, $attachment_meta = false ) {
54
  $this->id = $attachment_id;
55
  $this->wp_upload_dir = wp_upload_dir();
56
  $this->attachment_meta = $attachment_meta;
57
-
58
  if ( ! $attachment_meta ) {
59
  // some meta can be missing due to: https://wordpress.stackexchange.com/q/330174/149161
60
  $this->attachment_meta = wp_get_attachment_metadata( $this->id );
61
  }
62
-
63
- if ( $this->attachment_meta && isset( $this->attachment_meta['file'] ) ) {
64
- $this->url = trailingslashit( $this->wp_upload_dir['baseurl'] ) . $this->attachment_meta['file'];
65
- $this->path = wp_normalize_path( trailingslashit( $this->wp_upload_dir['basedir'] ) . $this->attachment_meta['file'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
 
 
 
67
  }
68
-
69
  /**
70
  * Актуализирует мета данные аттачмента и загружает актуальные мета данные и данные по оптимизации из базы.
71
  */
72
- public function reload() {
73
- $this->attachment_meta = wp_get_attachment_metadata( $this->id );
74
- $this->optimization_data = new RIO_Process_Queue( array(
 
 
 
75
  'object_id' => $this->id,
76
  'object_name' => '',
77
  'item_type' => 'attachment',
78
- ) );
79
  $this->optimization_data->load();
 
80
  }
81
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  /**
83
  * Добавляем сообщение в лог файл.
84
  *
85
- * @param string $message Текст сообщения об ошибке.
86
  */
87
  public function writeLog( $message ) {
88
-
89
  $char = "\t-> ";
90
  $nl = PHP_EOL;
91
-
92
  $error = sprintf( 'Error to optimize attachment (ID: #%s). Message: "%s"', $this->id, trim( $message ) ) . $nl;
93
  $error .= $char . sprintf( "Attachment optimized? %s", ( $this->isOptimized() ? 'Yes' : 'No' ) ) . $nl;
94
  $error .= $char . sprintf( "Should be resized? %s", ( $this->isNeedResize() ? 'Yes' : 'No' ) ) . $nl;
95
  $error .= $char . sprintf( "Original size: %sx%s", $this->attachment_meta['width'], $this->attachment_meta['height'] ) . $nl;
96
  $error .= $char . sprintf( "Relative path: %s", $this->attachment_meta['file'] ) . $nl;
97
  $error .= $char . sprintf( "Server used: %s", WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' ) ) . $nl;
98
-
99
  if ( ! empty( $this->attachment_meta['sizes'] ) ) {
100
  $error .= $char . ' Additional sizes:' . $nl;
101
  foreach ( $this->attachment_meta['sizes'] as $size_type => $size_info ) {
102
  $error .= "\t" . $char . sprintf( 'Type: %s, size: %sx%s, MIME type: %s', $size_type, $size_info['width'], $size_info['height'], $size_info['mime-type'] ) . $nl;
103
  }
104
  }
105
-
106
  WRIO_Logger::error( $error );
107
  }
108
-
109
  /**
110
  * Возвращает объект с информацией об оптимизации
111
  *
@@ -113,243 +195,258 @@ class WIO_Attachment {
113
  */
114
  public function getOptimizationData() {
115
  if ( ! isset( $optimization_data ) ) {
116
- $this->optimization_data = new RIO_Process_Queue( array(
117
  'object_id' => $this->id,
118
  'object_name' => '',
119
  'item_type' => 'attachment',
120
- ) );
121
  $this->optimization_data->load();
122
  }
123
-
124
  return $this->optimization_data;
125
  }
126
-
127
  /**
128
  * Оптимизация аттачмента.
129
  *
130
- * @param string $optimization_level Уровень оптимизации изображения.
131
  *
132
  * @return array
133
  */
134
  public function optimize( $optimization_level = '' ) {
135
- $optimize_results = array(
136
  'original_size' => 0,
137
  'optimized_size' => 0,
138
- );
139
-
140
  if ( empty( $optimization_level ) ) {
141
  $optimization_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
142
  }
143
-
144
  if ( $optimization_level == 'custom' ) {
145
  $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
146
  $optimization_level = intval( $custom_quality );
147
  }
148
-
149
  $optimization_data = $this->getOptimizationData();
150
- $results = array(
151
  'original_size' => 0,
152
  'final_size' => 0,
153
  'original_mime_type' => '',
154
  'final_mime_type' => '',
155
- );
156
  $results['processing_level'] = $optimization_level;
157
-
158
- $path = $this->get( 'path' );
159
-
160
- // проверяем наличие основного файла, если его нет, то исключаем из дальнейшей обработки
161
- if ( ! file_exists( $path ) ) {
 
 
 
 
 
162
  $results['result_status'] = 'error';
163
- $extra_data = array(
 
 
 
 
 
 
 
 
 
164
  'error' => 'path',
165
- 'error_msg' => sprintf( 'File path %s', ( empty( $path ) ) ? 'is empty' : $path . ' does not exist' ),
166
- );
167
- $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
 
168
  $optimization_data->configure( $results );
169
  $optimization_data->save();
170
-
171
  WRIO_Logger::error( sprintf( 'Failed to find original attachment #%s located in %s. Skipping optimization. This may be caused due to bug in %s function, which returns false for attachment meta', $this->id, empty( $path ) ? '*empty path*' : $path, 'wp_get_attachment_metadata()' ) );
172
-
173
  return $optimize_results;
174
  }
175
-
176
  // сначала бекапим
177
  $is_image_backuped = $this->backup();
178
-
179
  if ( is_wp_error( $is_image_backuped ) ) {
180
  $error_msg = $is_image_backuped->get_error_message();
181
  $this->writeLog( $error_msg );
182
-
183
  $results['result_status'] = 'error';
184
- $extra_data = array(
185
  'error' => 'backup',
186
  'error_msg' => 'Failed to backup',
187
- );
188
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
189
  $optimization_data->configure( $results );
190
  $optimization_data->save();
191
-
192
  WRIO_Logger::error( sprintf( 'Failed to make backup of original attachment #%s. Skipping optimization.', $this->id ) );
193
-
194
  return $optimize_results;
195
  }
196
-
197
  $results['is_backed_up'] = $is_image_backuped;
198
-
199
- $original_main_size = filesize( $path );
200
-
201
  // если файл большой - изменяем размер
202
  if ( $this->isNeedResize() ) {
203
  $this->resize();
204
  }
205
-
206
  $image_processor = WIO_OptimizationTools::getImageProcessor();
207
-
208
  clearstatcache(); // на всякий случай очистим кеш файловой статистики
209
-
210
- $optimized_img_data = $image_processor->process( array(
211
  'image_url' => $this->get( 'url' ),
212
  'image_path' => $this->get( 'path' ),
213
  'quality' => $image_processor->quality( $optimization_level ),
214
  'save_exif' => WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false ),
215
- ) );
216
-
217
  // проверяем на ошибку
218
  if ( is_wp_error( $optimized_img_data ) ) {
219
  $error_msg = $optimized_img_data->get_error_message();
220
  $this->writeLog( $error_msg );
221
-
222
  $results['result_status'] = 'error';
223
-
224
- $extra_data = array(
225
  'error' => 'optimization',
226
  'error_msg' => $error_msg,
227
- );
228
-
229
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
230
-
231
  $optimization_data->configure( $results );
232
  $optimization_data->save();
233
-
234
  WRIO_Logger::error( sprintf( 'Failed to process (url: %s, path: %s, quality: %s) as error was returned: %s', $this->get( 'url' ), $this->get( 'path' ), $image_processor->quality( $optimization_level ), $error_msg ) );
235
-
236
  return $optimize_results;
237
  }
238
-
239
  $results['original_mime_type'] = '';
240
  $results['final_mime_type'] = '';
241
-
242
  // отложенная оптимизация
243
  if ( isset( $optimized_img_data['status'] ) && $optimized_img_data['status'] == 'processing' ) {
244
  $results['result_status'] = 'processing';
245
  $results['original_size'] = 0;
246
  $results['final_size'] = 0;
247
-
248
- $extra_data = array(
249
  'main_optimized_data' => $optimized_img_data,
250
  'thumbnails_optimized_data' => $this->optimizeImageSizes(),
251
- );
252
-
253
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
254
-
255
  $optimization_data->configure( $results );
256
  $optimization_data->save();
257
  $optimize_results['processing'] = 1;
258
-
259
  return $optimize_results;
260
  }
261
-
262
  //скачиваем и заменяем главную картинку
263
  $image_downloaded = $this->replaceOriginalFile( $optimized_img_data );
264
-
265
  // некоторые провайдеры не отдают оптимизированный размер, поэтому после замены файла получаем его сами
266
  if ( ! $optimized_img_data['optimized_size'] ) {
267
  clearstatcache();
268
  $optimized_img_data['optimized_size'] = filesize( $this->get( 'path' ) );
269
  }
270
-
271
  // при отрицательной оптимизации ставим значение оригинала
272
  if ( $optimized_img_data['optimized_size'] > $original_main_size ) {
273
  $optimized_img_data['optimized_size'] = $original_main_size;
274
  }
275
-
276
  if ( $image_downloaded ) {
277
  //просчитываем статистику
278
  $optimize_results['original_size'] += $original_main_size;
279
  $optimize_results['optimized_size'] += $optimized_img_data['optimized_size'];
280
  $thumbnails_count = 0;
281
-
282
  // оптимизируем дополнительные размеры
283
  $optimized_img_sizes_data = $this->optimizeImageSizes();
284
-
285
  // добавляем к статистике данные по оптимизации доп размеров
286
  if ( ! empty( $optimized_img_sizes_data ) ) {
287
  $optimize_results['original_size'] += $optimized_img_sizes_data['original_size'];
288
  $optimize_results['optimized_size'] += $optimized_img_sizes_data['optimized_size'];
289
  $thumbnails_count = $optimized_img_sizes_data['thumbnails_count'];
290
  }
291
-
292
  $results['result_status'] = 'success';
293
  $results['final_size'] = $optimize_results['optimized_size'];
294
  $results['original_size'] = $optimize_results['original_size'];
295
-
296
- $extra_data = array(
297
  'thumbnails_count' => $thumbnails_count,
298
  'original_main_size' => $original_main_size,
299
- );
300
-
301
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
302
  $mime_type = '';
303
-
304
  if ( function_exists( 'wp_get_image_mime' ) ) {
305
  $mime_type = wp_get_image_mime( $this->get( 'path' ) );
306
  } else {
307
  WRIO_Logger::error( 'App is missing wp_get_image_mime() function, unable to get MIME type' );
308
  }
309
-
310
  $results['original_mime_type'] = $mime_type;
311
  $results['final_mime_type'] = $mime_type;
312
  $optimization_data->configure( $results );
313
  } else {
314
  $error_msg = 'Failed to get optimized image from remote server';
315
  $this->writeLog( $error_msg );
316
-
317
  $results['result_status'] = 'error';
318
-
319
- $extra_data = array(
320
  'error' => 'download',
321
  'error_msg' => $error_msg,
322
- );
323
-
324
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
325
  $optimization_data->configure( $results );
326
  }
327
-
328
  $optimization_data->save();
329
-
330
  return $optimize_results;
331
  }
332
-
333
  /**
334
  * Отложенная оптимизация аттачмента
335
  *
336
  * @return bool|array
337
  */
338
  public function deferredOptimization() {
339
- $results = array(
340
  'original_size' => 0,
341
  'optimized_size' => 0,
342
  'optimized_count' => 0,
343
  'processing' => 1,
344
- );
345
-
346
  $image_processor = WIO_OptimizationTools::getImageProcessor();
347
  $optimization_data = $this->getOptimizationData();
348
-
349
  if ( $optimization_data->get_result_status() != 'processing' ) {
350
  return false;
351
  }
352
-
353
  // проверяем главную картинку
354
  /**
355
  * @var RIO_Attachment_Extra_Data $extra_data
@@ -357,7 +454,7 @@ class WIO_Attachment {
357
  $extra_data = $optimization_data->get_extra_data();
358
  $main_optimized_data = $extra_data->get_main_optimized_data();
359
  $main_image_url = '';
360
-
361
  if ( ! $main_optimized_data['optimized_img_url'] ) {
362
  $main_image_url = $image_processor->checkDeferredOptimization( $main_optimized_data );
363
  if ( $main_image_url ) {
@@ -365,11 +462,11 @@ class WIO_Attachment {
365
  $extra_data->set_main_optimized_data( $main_optimized_data );
366
  }
367
  }
368
-
369
  $thumbnails_processed = true;
370
  $thumbnails = (array) $extra_data->get_thumbnails_optimized_data();
371
  $thumbnails = json_decode( json_encode( $thumbnails ), true ); // рекурсивная конвертация объекта в массив
372
-
373
  if ( is_array( $thumbnails['thumbnails'] ) ) {
374
  foreach ( $thumbnails['thumbnails'] as &$thumbnail_optimized_data ) {
375
  if ( ! $thumbnail_optimized_data['optimized_img_url'] ) {
@@ -383,7 +480,7 @@ class WIO_Attachment {
383
  }
384
  $extra_data->set_thumbnails_optimized_data( $thumbnails );
385
  }
386
-
387
  // когда все файлы получены - сохраняем и возвращаем результат
388
  if ( $main_image_url && $thumbnails_processed ) {
389
  $original_size = 0;
@@ -391,80 +488,80 @@ class WIO_Attachment {
391
  $thumbnails_count = 0;
392
  $original_main_size = filesize( $this->get( 'path' ) );
393
  $original_size = $original_size + $original_main_size;
394
-
395
- $this->replaceOriginalFile( array(
396
  'optimized_img_url' => $main_image_url,
397
- ) );
398
-
399
  clearstatcache();
400
-
401
  $optimized_main_size = filesize( $this->get( 'path' ) );
402
-
403
  // при отрицательной оптимизации ставим значение оригинала
404
  if ( $optimized_main_size > $original_main_size ) {
405
  $optimized_main_size = $original_main_size;
406
  }
407
-
408
  $optimized_size = $optimized_size + $optimized_main_size;
409
-
410
  if ( is_array( $thumbnails['thumbnails'] ) ) {
411
  foreach ( $thumbnails['thumbnails'] as $thumbnail_size => $thumbnail ) {
412
  $thumbnail_file = $this->getImageSizePath( $thumbnail_size );
413
  $original_thumbnail_size = filesize( $thumbnail_file );
414
  $original_size = $original_size + $original_thumbnail_size;
415
-
416
- $this->replaceOriginalFile( array(
417
  'optimized_img_url' => $thumbnail['optimized_img_url'],
418
- ), $thumbnail_size );
419
-
420
  clearstatcache();
421
-
422
  $optimized_thumbnail_size = filesize( $thumbnail_file );
423
-
424
  // при отрицательной оптимизации ставим значение оригинала
425
  if ( $optimized_thumbnail_size > $original_thumbnail_size ) {
426
  $optimized_thumbnail_size = $original_thumbnail_size;
427
  }
428
-
429
  $optimized_size = $optimized_size + $optimized_thumbnail_size;
430
-
431
  $thumbnails_count ++;
432
  }
433
  }
434
-
435
  $mime_type = '';
436
  if ( function_exists( 'wp_get_image_mime' ) ) {
437
  $mime_type = wp_get_image_mime( $this->get( 'path' ) );
438
  }
439
-
440
- $optimization_data->configure( array(
441
  'final_size' => $optimized_size,
442
  'original_size' => $original_size,
443
  'result_status' => 'success',
444
  'original_mime_type' => $mime_type,
445
  'final_mime_type' => $mime_type,
446
- ) );
447
-
448
  $extra_data->set_original_main_size( $original_main_size );
449
  $extra_data->set_thumbnails_count( $thumbnails_count );
450
-
451
  // удаляем промежуточные данные
452
  $extra_data->set_main_optimized_data( null );
453
  $extra_data->set_thumbnails_optimized_data( null );
454
  $extra_data->set_main_optimized_data( null );
455
-
456
  $results['optimized_count'] = 1;
457
  $results['original_size'] = $original_size;
458
  $results['optimized_size'] = $optimized_size;
459
-
460
  unset( $results['processing'] );
461
  }
462
  $optimization_data->set_extra_data( $extra_data );
463
  $optimization_data->save();
464
-
465
  return $results;
466
  }
467
-
468
  /**
469
  * Метод проверяет, оптимизирован ли аттачмент
470
  *
@@ -475,10 +572,10 @@ class WIO_Attachment {
475
  if ( $optimization_data->is_optimized() ) {
476
  return true;
477
  }
478
-
479
  return false;
480
  }
481
-
482
  /**
483
  * Возвращает все размеры аттачмента, которые нужно оптимизировать
484
  *
@@ -486,16 +583,16 @@ class WIO_Attachment {
486
  */
487
  public function getAllowedSizes() {
488
  $allowed_sizes = WRIO_Plugin::app()->getPopulateOption( 'allowed_sizes_thumbnail', 'thumbnail,medium' );
489
-
490
  if ( ! $allowed_sizes ) {
491
  return false;
492
  }
493
-
494
  $allowed_sizes = explode( ',', $allowed_sizes );
495
-
496
  return $allowed_sizes;
497
  }
498
-
499
  /**
500
  * Оптимизация других размеров аттачмента.
501
  *
@@ -503,47 +600,47 @@ class WIO_Attachment {
503
  */
504
  public function optimizeImageSizes() {
505
  $allowed_sizes = $this->getAllowedSizes();
506
-
507
  if ( $allowed_sizes === false ) {
508
- return array();
509
  }
510
-
511
  $image_processor = WIO_OptimizationTools::getImageProcessor();
512
  $quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
513
-
514
  if ( $quality == 'custom' ) {
515
  $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
516
  $quality = intval( $custom_quality );
517
  }
518
-
519
  $exif = WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false );
520
-
521
  $original_size = 0;
522
  $optimized_size = 0;
523
  $errors_count = 0;
524
  $optimized_count = 0;
525
- $thumbnails = array();
526
-
527
  foreach ( $allowed_sizes as $image_size ) {
528
  $url = $this->getImageSizeUrl( $image_size );
529
  $path = $this->getImageSizePath( $image_size );
530
-
531
  if ( ! $url || ! $path ) {
532
  continue;
533
  }
534
-
535
  $original_file_size = 0;
536
-
537
  if ( is_file( $path ) ) {
538
  $original_file_size = filesize( $path );
539
  }
540
-
541
- $optimized_img_data = $image_processor->process( array(
542
  'image_url' => $url,
543
  'image_path' => $path,
544
  'quality' => $image_processor->quality( $quality ),
545
  'save_exif' => $exif,
546
- ) );
547
  // проверяем на ошибку
548
  if ( is_wp_error( $optimized_img_data ) ) {
549
  $errors_count ++;
@@ -558,94 +655,94 @@ class WIO_Attachment {
558
  if ( ! $optimized_img_data['src_size'] ) {
559
  $optimized_img_data['src_size'] = $original_file_size;
560
  }
561
-
562
  // при отрицательной оптимизации ставим значение оригинала
563
  if ( $optimized_img_data['optimized_size'] > $original_file_size ) {
564
  $optimized_img_data['optimized_size'] = $original_file_size;
565
  }
566
-
567
  $thumbnails[ $image_size ] = $optimized_img_data;
568
-
569
  //просчитываем статистику
570
  $original_size += $optimized_img_data['src_size'];
571
  $optimized_size += $optimized_img_data['optimized_size'];
572
  $optimized_count ++;
573
  }
574
  }
575
-
576
- return array(
577
  'errors_count' => $errors_count,
578
  'original_size' => $original_size,
579
  'optimized_size' => $optimized_size,
580
  'thumbnails_count' => $optimized_count,
581
  'thumbnails' => $thumbnails,
582
- );
583
  }
584
-
585
  /**
586
  * Возвращает путь.
587
  *
588
- * @param string $image_size Размер(thumbnail, medium ... )
589
  *
590
  * @return string
591
  */
592
  public function getPath( $image_size = '' ) {
593
-
594
  if ( empty( $image_size ) ) {
595
  $path = $this->path;
596
  } else {
597
  $path = $this->getImageSizePath( $image_size );
598
  }
599
-
600
  return $path;
601
  }
602
-
603
  /**
604
  * Заменяет оригинальный файл на оптимизированный.
605
  *
606
- * @param array $optimized_img_data Hезультат оптимизации ввиде массива данных.
607
- * @param string $image_size Размер (thumbnail, medium ... )
608
  *
609
  * @return bool
610
  */
611
  public function replaceOriginalFile( $optimized_img_data, $image_size = '' ) {
612
-
613
  $optimized_img_url = $optimized_img_data['optimized_img_url'];
614
-
615
  if ( isset( $optimized_img_data['not_need_download'] ) && (bool) $optimized_img_data['not_need_download'] ) {
616
  $optimized_file = $optimized_img_url;
617
  } else {
618
  $optimized_file = $this->remoteDownloadImage( $optimized_img_url );
619
  }
620
-
621
  if ( empty( $optimized_file ) ) {
622
  WRIO_Logger::error( sprintf( 'Unable to replace original image with new as failed to download %s', $optimized_img_url ) );
623
-
624
  return false;
625
  }
626
-
627
  if ( isset( $optimized_img_data['not_need_replace'] ) && $optimized_img_data['not_need_replace'] ) {
628
  // если картинка уже оптимизирована и провайдер её не может уменьшить - он может вернуть положительный ответ, но без самой картинки. В таком случае ничего заменять не надо
629
  return true;
630
  }
631
-
632
  $attachment_size_path = $this->getPath( $image_size );
633
-
634
  if ( ! is_file( $attachment_size_path ) ) {
635
  return false;
636
  }
637
-
638
  $bytes = @file_put_contents( $attachment_size_path, $optimized_file );
639
-
640
  if ( $bytes === false ) {
641
  WRIO_Logger::error( sprintf( 'Failed to put new image\'s %s content to %s as file_put_contents() failed', $optimized_img_url, $attachment_size_path ) );
642
-
643
  return false;
644
  }
645
-
646
  return true;
647
  }
648
-
649
  /**
650
  * Скачивание изображения с удалённого сервера
651
  *
@@ -654,44 +751,44 @@ class WIO_Attachment {
654
  * @return string|null Image content on success, NULL on failure.
655
  */
656
  protected function remoteDownloadImage( $url ) {
657
-
658
  if ( ! function_exists( 'curl_version' ) ) {
659
  $content = @file_get_contents( $url );
660
-
661
  if ( $content === false ) {
662
  WRIO_Logger::error( sprintf( 'Failed to get content of "%s" using file_get_contents()', $url ) );
663
-
664
  return null;
665
  }
666
-
667
  return $content;
668
  }
669
-
670
  $ch = curl_init();
671
  curl_setopt( $ch, CURLOPT_HEADER, 0 );
672
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
673
  curl_setopt( $ch, CURLOPT_URL, $url );
674
-
675
  $image_body = curl_exec( $ch );
676
  $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
677
  if ( $http_code != '200' ) {
678
  $image_body = false;
679
  }
680
  curl_close( $ch );
681
-
682
  if ( $image_body === false ) {
683
  WRIO_Logger::error( sprintf( 'Failed to get content of "%s" using curl_exec()', $url ) );
684
-
685
  return null;
686
  }
687
-
688
  return $image_body;
689
  }
690
-
691
  /**
692
  * Возвращает свойство аттачмента
693
  *
694
- * @param string $property имя свойства
695
  *
696
  * @return mixed
697
  */
@@ -699,14 +796,14 @@ class WIO_Attachment {
699
  if ( isset( $this->$property ) ) {
700
  return $this->$property;
701
  }
702
-
703
  return false;
704
  }
705
-
706
  /**
707
  * Возвращает URL изображения по указанному размеру
708
  *
709
- * @param string $size - размер изображения(thumbnail,medium,large...)
710
  *
711
  * @return string|null
712
  */
@@ -714,17 +811,17 @@ class WIO_Attachment {
714
  if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
715
  return null;
716
  }
717
-
718
  $file = $this->attachment_meta['sizes'][ $size ]['file'];
719
  $url = str_replace( wp_basename( $this->url ), $file, $this->url );
720
-
721
  return $url;
722
  }
723
-
724
  /**
725
  * Возвращает путь к изображению по указанному размеру.
726
  *
727
- * @param string $size Размер изображения (thumbnail, medium, large ...)
728
  *
729
  * @return string Путь до изображения.
730
  */
@@ -732,13 +829,13 @@ class WIO_Attachment {
732
  if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
733
  return null;
734
  }
735
-
736
  $file = $this->attachment_meta['sizes'][ $size ]['file'];
737
  $path = str_replace( wp_basename( $this->path ), $file, $this->path );
738
-
739
  return $path;
740
  }
741
-
742
  /**
743
  * Проверка необходимости делать изменение размера.
744
  *
@@ -746,18 +843,18 @@ class WIO_Attachment {
746
  */
747
  protected function isNeedResize() {
748
  $resize_large_images = WRIO_Plugin::app()->getPopulateOption( 'resize_larger', true );
749
-
750
  if ( ! $resize_large_images ) {
751
  return false;
752
  }
753
-
754
  $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
755
  $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
756
-
757
  if ( ! $resize_larger_w && ! $resize_larger_h ) {
758
  return false;
759
  }
760
-
761
  // если ширина и высота установлены и > 0
762
  if ( $this->attachment_meta['width'] >= $this->attachment_meta['height'] ) {
763
  $larger_side = $this->attachment_meta['width'];
@@ -780,10 +877,10 @@ class WIO_Attachment {
780
  if ( $larger_side <= $resize_larger_side ) {
781
  return false;
782
  }
783
-
784
  return true;
785
  }
786
-
787
  /**
788
  * Возвращает метаданные аттачмента
789
  *
@@ -792,7 +889,7 @@ class WIO_Attachment {
792
  public function getMetaData() {
793
  return $this->attachment_meta;
794
  }
795
-
796
  /**
797
  * Изменяет размер изображения до заданного в настройках размера.
798
  *
@@ -801,19 +898,19 @@ class WIO_Attachment {
801
  protected function resize() {
802
  $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
803
  $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
804
-
805
  $image = wp_get_image_editor( $this->path );
806
-
807
  if ( is_wp_error( $image ) ) {
808
  WRIO_Logger::error( sprintf( 'Failed to get image edit via wp_get_image_editor(), error: "%s"', $image->get_error_message() ) );
809
-
810
  return false;
811
  }
812
-
813
  $current_size = $image->get_size();
814
  $new_width = 0;
815
  $new_height = 0;
816
-
817
  // если обе стороны заданы
818
  if ( $resize_larger_h && $resize_larger_w ) {
819
  // определяем большую сторону и по ней маштабируем
@@ -837,38 +934,38 @@ class WIO_Attachment {
837
  $new_height = round( $current_size['height'] * $new_width / $current_size['width'] );
838
  }
839
  }
840
-
841
  $nl = PHP_EOL;
842
  $log_message = sprintf( "\tResize from: %sx%s to %sx%s", $current_size['width'], $current_size['height'], $new_width, $new_height ) . $nl;
843
  $log_message .= sprintf( "\tLarger resize from %sx%s", $resize_larger_w, $resize_larger_h ) . $nl;
844
  $log_message .= sprintf( "\tAbsolute path: %s", $this->path ) . $nl;
845
-
846
  $resize_result = $image->resize( $new_width, $new_height, false );
847
-
848
  if ( is_wp_error( $resize_result ) ) {
849
  $this->writeLog( sprintf( 'Resize error: %s. Details: %s', $resize_result->get_error_messages(), $log_message ) );
850
-
851
  return false;
852
  }
853
-
854
  $save_result = $image->save( $this->path );
855
-
856
  if ( is_wp_error( $save_result ) ) {
857
  $this->writeLog( sprintf( 'Failed to save resized error in db: %s, Details: %s', $save_result->get_error_messages(), $log_message ) );
858
-
859
  return false;
860
  }
861
-
862
  $this->attachment_meta['width'] = $new_width;
863
  $this->attachment_meta['height'] = $new_height;
864
  $this->attachment_meta['old_width'] = $current_size['width'];
865
  $this->attachment_meta['old_height'] = $current_size['height'];
866
-
867
  wp_update_attachment_metadata( $this->id, $this->attachment_meta );
868
-
869
  return true;
870
  }
871
-
872
  /**
873
  * Делает резервную копию
874
  *
@@ -876,10 +973,10 @@ class WIO_Attachment {
876
  */
877
  protected function backup() {
878
  $backup = WIO_Backup::get_instance();
879
-
880
  return $backup->backupAttachment( $this );
881
  }
882
-
883
  /**
884
  * Восстанавливает файлы из резервной копии
885
  *
@@ -887,7 +984,7 @@ class WIO_Attachment {
887
  */
888
  public function restore() {
889
  $backup = WIO_Backup::get_instance();
890
-
891
  return $backup->restoreAttachment( $this );
892
  }
893
  }
8
  /**
9
  * Класс для работы с WordPress attachment.
10
  *
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
  * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
  */
15
  class WIO_Attachment {
16
+
17
  /**
18
  * @var int
19
  */
20
  private $id;
21
+
22
+
23
  /**
24
  * @var array meta-данные
25
  */
26
  private $attachment_meta;
27
+
28
  /**
29
  * @var array массив с данными о папке uploads
30
  */
31
  private $wp_upload_dir;
32
+
33
  /**
34
  * @var string
35
  */
36
  private $url;
37
+
38
  /**
39
  * @var string
40
  */
41
  private $path;
42
+
43
  /**
44
  * @var RIO_Process_Queue
45
  */
46
  private $optimization_data;
47
+
48
  /**
49
  * Инициализация аттачмента
50
  *
51
+ * @param int $attachment_id Номер аттачмента из медиабиблиотеки
52
+ * @param array|false $attachment_meta метаданные аттачмента. Ключи массива аналогичны функции wp_get_attachment_metadata
53
  */
54
  public function __construct( $attachment_id, $attachment_meta = false ) {
55
  $this->id = $attachment_id;
56
  $this->wp_upload_dir = wp_upload_dir();
57
  $this->attachment_meta = $attachment_meta;
58
+
59
  if ( ! $attachment_meta ) {
60
  // some meta can be missing due to: https://wordpress.stackexchange.com/q/330174/149161
61
  $this->attachment_meta = wp_get_attachment_metadata( $this->id );
62
  }
63
+
64
+ $this->set_paths();
65
+ }
66
+
67
+ /**
68
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
69
+ * @since 1.3.9
70
+ * @return bool
71
+ */
72
+ public function isset_attachment_meta() {
73
+ return $this->attachment_meta && isset( $this->attachment_meta['file'] );
74
+ }
75
+
76
+ /**
77
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
78
+ * @since 1.3.9
79
+ */
80
+ public function set_paths() {
81
+ if ( ! $this->isset_attachment_meta() ) {
82
+ return;
83
  }
84
+
85
+ $this->url = trailingslashit( $this->wp_upload_dir['baseurl'] ) . $this->attachment_meta['file'];
86
+ $this->path = wp_normalize_path( trailingslashit( $this->wp_upload_dir['basedir'] ) . $this->attachment_meta['file'] );
87
  }
88
+
89
  /**
90
  * Актуализирует мета данные аттачмента и загружает актуальные мета данные и данные по оптимизации из базы.
91
  */
92
+ public function reload( $attachment_meta = [] ) {
93
+ if ( empty( $attachment_meta ) ) {
94
+ $attachment_meta = wp_get_attachment_metadata( $this->id );
95
+ }
96
+ $this->attachment_meta = $attachment_meta;
97
+ $this->optimization_data = new RIO_Process_Queue( [
98
  'object_id' => $this->id,
99
  'object_name' => '',
100
  'item_type' => 'attachment',
101
+ ] );
102
  $this->optimization_data->load();
103
+ $this->set_paths();
104
  }
105
+
106
+ /**
107
+ * Fallback to get attachment meta it can be empty when WordPress failed to create it or invocation
108
+ * of method was produced too soon.
109
+ *
110
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
111
+ * @since 1.3.9
112
+ * @return bool
113
+ */
114
+ public function regenerate_metadata() {
115
+ if ( $this->isset_attachment_meta() ) {
116
+ return true;
117
+ }
118
+
119
+ WRIO_Logger::info( sprintf( 'Try regenerate metadata for attachment #%d', $this->id ) );
120
+
121
+ // Need to remove this filter, as it would start recursion
122
+ remove_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload' );
123
+
124
+ $file_path = get_attached_file( $this->id );
125
+
126
+ if ( empty( $file_path ) ) {
127
+ $attachment = get_post( $this->id );
128
+
129
+ if ( empty( $attachment ) || 'attachment' !== $attachment->post_type ) {
130
+ return false;
131
+ }
132
+
133
+ $file_path = wrio_url_to_abs_path( $attachment->guid );
134
+ }
135
+
136
+ if ( empty( $file_path ) || ! file_exists( $file_path ) ) {
137
+ WRIO_Logger::info( sprintf( 'Failed regenerate attachment meta data. Attachment file (%s) doesn\'t exists!', $file_path ) );
138
+
139
+ return false;
140
+ }
141
+
142
+ $attachment_meta = wp_generate_attachment_metadata( $this->id, $file_path );
143
+
144
+ if ( empty( $attachment_meta ) ) {
145
+ WRIO_Logger::error( sprintf( 'Failed regenerate meta data for attachment file (%s).', $file_path ) );
146
+
147
+ return false;
148
+ }
149
+
150
+ WRIO_Logger::debug( sprintf( 'Generated metadata: %s', var_export( $attachment_meta, true ) ) );
151
+
152
+ # Updating metadata in database
153
+ wp_update_attachment_metadata( $this->id, $attachment_meta );
154
+
155
+ $this->reload( $attachment_meta );
156
+
157
+ add_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload', 10, 2 );
158
+
159
+ WRIO_Logger::info( sprintf( 'Finish regenerate metadata for attachment #%d!', $this->id ) );
160
+
161
+ return true;
162
+ }
163
+
164
  /**
165
  * Добавляем сообщение в лог файл.
166
  *
167
+ * @param string $message Текст сообщения об ошибке.
168
  */
169
  public function writeLog( $message ) {
170
+
171
  $char = "\t-> ";
172
  $nl = PHP_EOL;
173
+
174
  $error = sprintf( 'Error to optimize attachment (ID: #%s). Message: "%s"', $this->id, trim( $message ) ) . $nl;
175
  $error .= $char . sprintf( "Attachment optimized? %s", ( $this->isOptimized() ? 'Yes' : 'No' ) ) . $nl;
176
  $error .= $char . sprintf( "Should be resized? %s", ( $this->isNeedResize() ? 'Yes' : 'No' ) ) . $nl;
177
  $error .= $char . sprintf( "Original size: %sx%s", $this->attachment_meta['width'], $this->attachment_meta['height'] ) . $nl;
178
  $error .= $char . sprintf( "Relative path: %s", $this->attachment_meta['file'] ) . $nl;
179
  $error .= $char . sprintf( "Server used: %s", WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' ) ) . $nl;
180
+
181
  if ( ! empty( $this->attachment_meta['sizes'] ) ) {
182
  $error .= $char . ' Additional sizes:' . $nl;
183
  foreach ( $this->attachment_meta['sizes'] as $size_type => $size_info ) {
184
  $error .= "\t" . $char . sprintf( 'Type: %s, size: %sx%s, MIME type: %s', $size_type, $size_info['width'], $size_info['height'], $size_info['mime-type'] ) . $nl;
185
  }
186
  }
187
+
188
  WRIO_Logger::error( $error );
189
  }
190
+
191
  /**
192
  * Возвращает объект с информацией об оптимизации
193
  *
195
  */
196
  public function getOptimizationData() {
197
  if ( ! isset( $optimization_data ) ) {
198
+ $this->optimization_data = new RIO_Process_Queue( [
199
  'object_id' => $this->id,
200
  'object_name' => '',
201
  'item_type' => 'attachment',
202
+ ] );
203
  $this->optimization_data->load();
204
  }
205
+
206
  return $this->optimization_data;
207
  }
208
+
209
  /**
210
  * Оптимизация аттачмента.
211
  *
212
+ * @param string $optimization_level Уровень оптимизации изображения.
213
  *
214
  * @return array
215
  */
216
  public function optimize( $optimization_level = '' ) {
217
+ $optimize_results = [
218
  'original_size' => 0,
219
  'optimized_size' => 0,
220
+ ];
221
+
222
  if ( empty( $optimization_level ) ) {
223
  $optimization_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
224
  }
225
+
226
  if ( $optimization_level == 'custom' ) {
227
  $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
228
  $optimization_level = intval( $custom_quality );
229
  }
230
+
231
  $optimization_data = $this->getOptimizationData();
232
+ $results = [
233
  'original_size' => 0,
234
  'final_size' => 0,
235
  'original_mime_type' => '',
236
  'final_mime_type' => '',
237
+ ];
238
  $results['processing_level'] = $optimization_level;
239
+
240
+ # The path may be empty because no metadata has been created for the image.
241
+ # We should try to create image metadata again.
242
+ if ( ! $this->isset_attachment_meta() ) {
243
+ WRIO_Logger::warning( sprintf( 'Attachment #%d doesn\'t have metadata.', $this->id ) );
244
+
245
+ $this->regenerate_metadata();
246
+ }
247
+
248
+ if ( empty( $this->path ) || ! file_exists( $this->path ) ) {
249
  $results['result_status'] = 'error';
250
+
251
+ $error_message = __( 'Attachment cannot be optimized.', 'robin-image-optimizer' );
252
+
253
+ if ( empty( $this->path ) ) {
254
+ $error_message .= ' ' . sprintf( __( 'Attachment #%d doesn\'t have metadata, the image may be damaged.', 'robin-image-optimizer' ), $this->id );
255
+ } else {
256
+ $error_message .= ' ' . sprintf( __( 'File "(%s)" doesn\'t exist', 'robin-image-optimizer' ), $this->path );
257
+ }
258
+
259
+ $extra_data = [
260
  'error' => 'path',
261
+ 'error_msg' => $error_message,
262
+ ];
263
+
264
+ $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
265
  $optimization_data->configure( $results );
266
  $optimization_data->save();
267
+
268
  WRIO_Logger::error( sprintf( 'Failed to find original attachment #%s located in %s. Skipping optimization. This may be caused due to bug in %s function, which returns false for attachment meta', $this->id, empty( $path ) ? '*empty path*' : $path, 'wp_get_attachment_metadata()' ) );
269
+
270
  return $optimize_results;
271
  }
272
+
273
  // сначала бекапим
274
  $is_image_backuped = $this->backup();
275
+
276
  if ( is_wp_error( $is_image_backuped ) ) {
277
  $error_msg = $is_image_backuped->get_error_message();
278
  $this->writeLog( $error_msg );
279
+
280
  $results['result_status'] = 'error';
281
+ $extra_data = [
282
  'error' => 'backup',
283
  'error_msg' => 'Failed to backup',
284
+ ];
285
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
286
  $optimization_data->configure( $results );
287
  $optimization_data->save();
288
+
289
  WRIO_Logger::error( sprintf( 'Failed to make backup of original attachment #%s. Skipping optimization.', $this->id ) );
290
+
291
  return $optimize_results;
292
  }
293
+
294
  $results['is_backed_up'] = $is_image_backuped;
295
+
296
+ $original_main_size = filesize( $this->path );
297
+
298
  // если файл большой - изменяем размер
299
  if ( $this->isNeedResize() ) {
300
  $this->resize();
301
  }
302
+
303
  $image_processor = WIO_OptimizationTools::getImageProcessor();
304
+
305
  clearstatcache(); // на всякий случай очистим кеш файловой статистики
306
+
307
+ $optimized_img_data = $image_processor->process( [
308
  'image_url' => $this->get( 'url' ),
309
  'image_path' => $this->get( 'path' ),
310
  'quality' => $image_processor->quality( $optimization_level ),
311
  'save_exif' => WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false ),
312
+ ] );
313
+
314
  // проверяем на ошибку
315
  if ( is_wp_error( $optimized_img_data ) ) {
316
  $error_msg = $optimized_img_data->get_error_message();
317
  $this->writeLog( $error_msg );
318
+
319
  $results['result_status'] = 'error';
320
+
321
+ $extra_data = [
322
  'error' => 'optimization',
323
  'error_msg' => $error_msg,
324
+ ];
325
+
326
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
327
+
328
  $optimization_data->configure( $results );
329
  $optimization_data->save();
330
+
331
  WRIO_Logger::error( sprintf( 'Failed to process (url: %s, path: %s, quality: %s) as error was returned: %s', $this->get( 'url' ), $this->get( 'path' ), $image_processor->quality( $optimization_level ), $error_msg ) );
332
+
333
  return $optimize_results;
334
  }
335
+
336
  $results['original_mime_type'] = '';
337
  $results['final_mime_type'] = '';
338
+
339
  // отложенная оптимизация
340
  if ( isset( $optimized_img_data['status'] ) && $optimized_img_data['status'] == 'processing' ) {
341
  $results['result_status'] = 'processing';
342
  $results['original_size'] = 0;
343
  $results['final_size'] = 0;
344
+
345
+ $extra_data = [
346
  'main_optimized_data' => $optimized_img_data,
347
  'thumbnails_optimized_data' => $this->optimizeImageSizes(),
348
+ ];
349
+
350
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
351
+
352
  $optimization_data->configure( $results );
353
  $optimization_data->save();
354
  $optimize_results['processing'] = 1;
355
+
356
  return $optimize_results;
357
  }
358
+
359
  //скачиваем и заменяем главную картинку
360
  $image_downloaded = $this->replaceOriginalFile( $optimized_img_data );
361
+
362
  // некоторые провайдеры не отдают оптимизированный размер, поэтому после замены файла получаем его сами
363
  if ( ! $optimized_img_data['optimized_size'] ) {
364
  clearstatcache();
365
  $optimized_img_data['optimized_size'] = filesize( $this->get( 'path' ) );
366
  }
367
+
368
  // при отрицательной оптимизации ставим значение оригинала
369
  if ( $optimized_img_data['optimized_size'] > $original_main_size ) {
370
  $optimized_img_data['optimized_size'] = $original_main_size;
371
  }
372
+
373
  if ( $image_downloaded ) {
374
  //просчитываем статистику
375
  $optimize_results['original_size'] += $original_main_size;
376
  $optimize_results['optimized_size'] += $optimized_img_data['optimized_size'];
377
  $thumbnails_count = 0;
378
+
379
  // оптимизируем дополнительные размеры
380
  $optimized_img_sizes_data = $this->optimizeImageSizes();
381
+
382
  // добавляем к статистике данные по оптимизации доп размеров
383
  if ( ! empty( $optimized_img_sizes_data ) ) {
384
  $optimize_results['original_size'] += $optimized_img_sizes_data['original_size'];
385
  $optimize_results['optimized_size'] += $optimized_img_sizes_data['optimized_size'];
386
  $thumbnails_count = $optimized_img_sizes_data['thumbnails_count'];
387
  }
388
+
389
  $results['result_status'] = 'success';
390
  $results['final_size'] = $optimize_results['optimized_size'];
391
  $results['original_size'] = $optimize_results['original_size'];
392
+
393
+ $extra_data = [
394
  'thumbnails_count' => $thumbnails_count,
395
  'original_main_size' => $original_main_size,
396
+ ];
397
+
398
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
399
  $mime_type = '';
400
+
401
  if ( function_exists( 'wp_get_image_mime' ) ) {
402
  $mime_type = wp_get_image_mime( $this->get( 'path' ) );
403
  } else {
404
  WRIO_Logger::error( 'App is missing wp_get_image_mime() function, unable to get MIME type' );
405
  }
406
+
407
  $results['original_mime_type'] = $mime_type;
408
  $results['final_mime_type'] = $mime_type;
409
  $optimization_data->configure( $results );
410
  } else {
411
  $error_msg = 'Failed to get optimized image from remote server';
412
  $this->writeLog( $error_msg );
413
+
414
  $results['result_status'] = 'error';
415
+
416
+ $extra_data = [
417
  'error' => 'download',
418
  'error_msg' => $error_msg,
419
+ ];
420
+
421
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
422
  $optimization_data->configure( $results );
423
  }
424
+
425
  $optimization_data->save();
426
+
427
  return $optimize_results;
428
  }
429
+
430
  /**
431
  * Отложенная оптимизация аттачмента
432
  *
433
  * @return bool|array
434
  */
435
  public function deferredOptimization() {
436
+ $results = [
437
  'original_size' => 0,
438
  'optimized_size' => 0,
439
  'optimized_count' => 0,
440
  'processing' => 1,
441
+ ];
442
+
443
  $image_processor = WIO_OptimizationTools::getImageProcessor();
444
  $optimization_data = $this->getOptimizationData();
445
+
446
  if ( $optimization_data->get_result_status() != 'processing' ) {
447
  return false;
448
  }
449
+
450
  // проверяем главную картинку
451
  /**
452
  * @var RIO_Attachment_Extra_Data $extra_data
454
  $extra_data = $optimization_data->get_extra_data();
455
  $main_optimized_data = $extra_data->get_main_optimized_data();
456
  $main_image_url = '';
457
+
458
  if ( ! $main_optimized_data['optimized_img_url'] ) {
459
  $main_image_url = $image_processor->checkDeferredOptimization( $main_optimized_data );
460
  if ( $main_image_url ) {
462
  $extra_data->set_main_optimized_data( $main_optimized_data );
463
  }
464
  }
465
+
466
  $thumbnails_processed = true;
467
  $thumbnails = (array) $extra_data->get_thumbnails_optimized_data();
468
  $thumbnails = json_decode( json_encode( $thumbnails ), true ); // рекурсивная конвертация объекта в массив
469
+
470
  if ( is_array( $thumbnails['thumbnails'] ) ) {
471
  foreach ( $thumbnails['thumbnails'] as &$thumbnail_optimized_data ) {
472
  if ( ! $thumbnail_optimized_data['optimized_img_url'] ) {
480
  }
481
  $extra_data->set_thumbnails_optimized_data( $thumbnails );
482
  }
483
+
484
  // когда все файлы получены - сохраняем и возвращаем результат
485
  if ( $main_image_url && $thumbnails_processed ) {
486
  $original_size = 0;
488
  $thumbnails_count = 0;
489
  $original_main_size = filesize( $this->get( 'path' ) );
490
  $original_size = $original_size + $original_main_size;
491
+
492
+ $this->replaceOriginalFile( [
493
  'optimized_img_url' => $main_image_url,
494
+ ] );
495
+
496
  clearstatcache();
497
+
498
  $optimized_main_size = filesize( $this->get( 'path' ) );
499
+
500
  // при отрицательной оптимизации ставим значение оригинала
501
  if ( $optimized_main_size > $original_main_size ) {
502
  $optimized_main_size = $original_main_size;
503
  }
504
+
505
  $optimized_size = $optimized_size + $optimized_main_size;
506
+
507
  if ( is_array( $thumbnails['thumbnails'] ) ) {
508
  foreach ( $thumbnails['thumbnails'] as $thumbnail_size => $thumbnail ) {
509
  $thumbnail_file = $this->getImageSizePath( $thumbnail_size );
510
  $original_thumbnail_size = filesize( $thumbnail_file );
511
  $original_size = $original_size + $original_thumbnail_size;
512
+
513
+ $this->replaceOriginalFile( [
514
  'optimized_img_url' => $thumbnail['optimized_img_url'],
515
+ ], $thumbnail_size );
516
+
517
  clearstatcache();
518
+
519
  $optimized_thumbnail_size = filesize( $thumbnail_file );
520
+
521
  // при отрицательной оптимизации ставим значение оригинала
522
  if ( $optimized_thumbnail_size > $original_thumbnail_size ) {
523
  $optimized_thumbnail_size = $original_thumbnail_size;
524
  }
525
+
526
  $optimized_size = $optimized_size + $optimized_thumbnail_size;
527
+
528
  $thumbnails_count ++;
529
  }
530
  }
531
+
532
  $mime_type = '';
533
  if ( function_exists( 'wp_get_image_mime' ) ) {
534
  $mime_type = wp_get_image_mime( $this->get( 'path' ) );
535
  }
536
+
537
+ $optimization_data->configure( [
538
  'final_size' => $optimized_size,
539
  'original_size' => $original_size,
540
  'result_status' => 'success',
541
  'original_mime_type' => $mime_type,
542
  'final_mime_type' => $mime_type,
543
+ ] );
544
+
545
  $extra_data->set_original_main_size( $original_main_size );
546
  $extra_data->set_thumbnails_count( $thumbnails_count );
547
+
548
  // удаляем промежуточные данные
549
  $extra_data->set_main_optimized_data( null );
550
  $extra_data->set_thumbnails_optimized_data( null );
551
  $extra_data->set_main_optimized_data( null );
552
+
553
  $results['optimized_count'] = 1;
554
  $results['original_size'] = $original_size;
555
  $results['optimized_size'] = $optimized_size;
556
+
557
  unset( $results['processing'] );
558
  }
559
  $optimization_data->set_extra_data( $extra_data );
560
  $optimization_data->save();
561
+
562
  return $results;
563
  }
564
+
565
  /**
566
  * Метод проверяет, оптимизирован ли аттачмент
567
  *
572
  if ( $optimization_data->is_optimized() ) {
573
  return true;
574
  }
575
+
576
  return false;
577
  }
578
+
579
  /**
580
  * Возвращает все размеры аттачмента, которые нужно оптимизировать
581
  *
583
  */
584
  public function getAllowedSizes() {
585
  $allowed_sizes = WRIO_Plugin::app()->getPopulateOption( 'allowed_sizes_thumbnail', 'thumbnail,medium' );
586
+
587
  if ( ! $allowed_sizes ) {
588
  return false;
589
  }
590
+
591
  $allowed_sizes = explode( ',', $allowed_sizes );
592
+
593
  return $allowed_sizes;
594
  }
595
+
596
  /**
597
  * Оптимизация других размеров аттачмента.
598
  *
600
  */
601
  public function optimizeImageSizes() {
602
  $allowed_sizes = $this->getAllowedSizes();
603
+
604
  if ( $allowed_sizes === false ) {
605
+ return [];
606
  }
607
+
608
  $image_processor = WIO_OptimizationTools::getImageProcessor();
609
  $quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
610
+
611
  if ( $quality == 'custom' ) {
612
  $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
613
  $quality = intval( $custom_quality );
614
  }
615
+
616
  $exif = WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false );
617
+
618
  $original_size = 0;
619
  $optimized_size = 0;
620
  $errors_count = 0;
621
  $optimized_count = 0;
622
+ $thumbnails = [];
623
+
624
  foreach ( $allowed_sizes as $image_size ) {
625
  $url = $this->getImageSizeUrl( $image_size );
626
  $path = $this->getImageSizePath( $image_size );
627
+
628
  if ( ! $url || ! $path ) {
629
  continue;
630
  }
631
+
632
  $original_file_size = 0;
633
+
634
  if ( is_file( $path ) ) {
635
  $original_file_size = filesize( $path );
636
  }
637
+
638
+ $optimized_img_data = $image_processor->process( [
639
  'image_url' => $url,
640
  'image_path' => $path,
641
  'quality' => $image_processor->quality( $quality ),
642
  'save_exif' => $exif,
643
+ ] );
644
  // проверяем на ошибку
645
  if ( is_wp_error( $optimized_img_data ) ) {
646
  $errors_count ++;
655
  if ( ! $optimized_img_data['src_size'] ) {
656
  $optimized_img_data['src_size'] = $original_file_size;
657
  }
658
+
659
  // при отрицательной оптимизации ставим значение оригинала
660
  if ( $optimized_img_data['optimized_size'] > $original_file_size ) {
661
  $optimized_img_data['optimized_size'] = $original_file_size;
662
  }
663
+
664
  $thumbnails[ $image_size ] = $optimized_img_data;
665
+
666
  //просчитываем статистику
667
  $original_size += $optimized_img_data['src_size'];
668
  $optimized_size += $optimized_img_data['optimized_size'];
669
  $optimized_count ++;
670
  }
671
  }
672
+
673
+ return [
674
  'errors_count' => $errors_count,
675
  'original_size' => $original_size,
676
  'optimized_size' => $optimized_size,
677
  'thumbnails_count' => $optimized_count,
678
  'thumbnails' => $thumbnails,
679
+ ];
680
  }
681
+
682
  /**
683
  * Возвращает путь.
684
  *
685
+ * @param string $image_size Размер(thumbnail, medium ... )
686
  *
687
  * @return string
688
  */
689
  public function getPath( $image_size = '' ) {
690
+
691
  if ( empty( $image_size ) ) {
692
  $path = $this->path;
693
  } else {
694
  $path = $this->getImageSizePath( $image_size );
695
  }
696
+
697
  return $path;
698
  }
699
+
700
  /**
701
  * Заменяет оригинальный файл на оптимизированный.
702
  *
703
+ * @param array $optimized_img_data Hезультат оптимизации ввиде массива данных.
704
+ * @param string $image_size Размер (thumbnail, medium ... )
705
  *
706
  * @return bool
707
  */
708
  public function replaceOriginalFile( $optimized_img_data, $image_size = '' ) {
709
+
710
  $optimized_img_url = $optimized_img_data['optimized_img_url'];
711
+
712
  if ( isset( $optimized_img_data['not_need_download'] ) && (bool) $optimized_img_data['not_need_download'] ) {
713
  $optimized_file = $optimized_img_url;
714
  } else {
715
  $optimized_file = $this->remoteDownloadImage( $optimized_img_url );
716
  }
717
+
718
  if ( empty( $optimized_file ) ) {
719
  WRIO_Logger::error( sprintf( 'Unable to replace original image with new as failed to download %s', $optimized_img_url ) );
720
+
721
  return false;
722
  }
723
+
724
  if ( isset( $optimized_img_data['not_need_replace'] ) && $optimized_img_data['not_need_replace'] ) {
725
  // если картинка уже оптимизирована и провайдер её не может уменьшить - он может вернуть положительный ответ, но без самой картинки. В таком случае ничего заменять не надо
726
  return true;
727
  }
728
+
729
  $attachment_size_path = $this->getPath( $image_size );
730
+
731
  if ( ! is_file( $attachment_size_path ) ) {
732
  return false;
733
  }
734
+
735
  $bytes = @file_put_contents( $attachment_size_path, $optimized_file );
736
+
737
  if ( $bytes === false ) {
738
  WRIO_Logger::error( sprintf( 'Failed to put new image\'s %s content to %s as file_put_contents() failed', $optimized_img_url, $attachment_size_path ) );
739
+
740
  return false;
741
  }
742
+
743
  return true;
744
  }
745
+
746
  /**
747
  * Скачивание изображения с удалённого сервера
748
  *
751
  * @return string|null Image content on success, NULL on failure.
752
  */
753
  protected function remoteDownloadImage( $url ) {
754
+
755
  if ( ! function_exists( 'curl_version' ) ) {
756
  $content = @file_get_contents( $url );
757
+
758
  if ( $content === false ) {
759
  WRIO_Logger::error( sprintf( 'Failed to get content of "%s" using file_get_contents()', $url ) );
760
+
761
  return null;
762
  }
763
+
764
  return $content;
765
  }
766
+
767
  $ch = curl_init();
768
  curl_setopt( $ch, CURLOPT_HEADER, 0 );
769
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
770
  curl_setopt( $ch, CURLOPT_URL, $url );
771
+
772
  $image_body = curl_exec( $ch );
773
  $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
774
  if ( $http_code != '200' ) {
775
  $image_body = false;
776
  }
777
  curl_close( $ch );
778
+
779
  if ( $image_body === false ) {
780
  WRIO_Logger::error( sprintf( 'Failed to get content of "%s" using curl_exec()', $url ) );
781
+
782
  return null;
783
  }
784
+
785
  return $image_body;
786
  }
787
+
788
  /**
789
  * Возвращает свойство аттачмента
790
  *
791
+ * @param string $property имя свойства
792
  *
793
  * @return mixed
794
  */
796
  if ( isset( $this->$property ) ) {
797
  return $this->$property;
798
  }
799
+
800
  return false;
801
  }
802
+
803
  /**
804
  * Возвращает URL изображения по указанному размеру
805
  *
806
+ * @param string $size - размер изображения(thumbnail,medium,large...)
807
  *
808
  * @return string|null
809
  */
811
  if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
812
  return null;
813
  }
814
+
815
  $file = $this->attachment_meta['sizes'][ $size ]['file'];
816
  $url = str_replace( wp_basename( $this->url ), $file, $this->url );
817
+
818
  return $url;
819
  }
820
+
821
  /**
822
  * Возвращает путь к изображению по указанному размеру.
823
  *
824
+ * @param string $size Размер изображения (thumbnail, medium, large ...)
825
  *
826
  * @return string Путь до изображения.
827
  */
829
  if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
830
  return null;
831
  }
832
+
833
  $file = $this->attachment_meta['sizes'][ $size ]['file'];
834
  $path = str_replace( wp_basename( $this->path ), $file, $this->path );
835
+
836
  return $path;
837
  }
838
+
839
  /**
840
  * Проверка необходимости делать изменение размера.
841
  *
843
  */
844
  protected function isNeedResize() {
845
  $resize_large_images = WRIO_Plugin::app()->getPopulateOption( 'resize_larger', true );
846
+
847
  if ( ! $resize_large_images ) {
848
  return false;
849
  }
850
+
851
  $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
852
  $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
853
+
854
  if ( ! $resize_larger_w && ! $resize_larger_h ) {
855
  return false;
856
  }
857
+
858
  // если ширина и высота установлены и > 0
859
  if ( $this->attachment_meta['width'] >= $this->attachment_meta['height'] ) {
860
  $larger_side = $this->attachment_meta['width'];
877
  if ( $larger_side <= $resize_larger_side ) {
878
  return false;
879
  }
880
+
881
  return true;
882
  }
883
+
884
  /**
885
  * Возвращает метаданные аттачмента
886
  *
889
  public function getMetaData() {
890
  return $this->attachment_meta;
891
  }
892
+
893
  /**
894
  * Изменяет размер изображения до заданного в настройках размера.
895
  *
898
  protected function resize() {
899
  $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
900
  $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
901
+
902
  $image = wp_get_image_editor( $this->path );
903
+
904
  if ( is_wp_error( $image ) ) {
905
  WRIO_Logger::error( sprintf( 'Failed to get image edit via wp_get_image_editor(), error: "%s"', $image->get_error_message() ) );
906
+
907
  return false;
908
  }
909
+
910
  $current_size = $image->get_size();
911
  $new_width = 0;
912
  $new_height = 0;
913
+
914
  // если обе стороны заданы
915
  if ( $resize_larger_h && $resize_larger_w ) {
916
  // определяем большую сторону и по ней маштабируем
934
  $new_height = round( $current_size['height'] * $new_width / $current_size['width'] );
935
  }
936
  }
937
+
938
  $nl = PHP_EOL;
939
  $log_message = sprintf( "\tResize from: %sx%s to %sx%s", $current_size['width'], $current_size['height'], $new_width, $new_height ) . $nl;
940
  $log_message .= sprintf( "\tLarger resize from %sx%s", $resize_larger_w, $resize_larger_h ) . $nl;
941
  $log_message .= sprintf( "\tAbsolute path: %s", $this->path ) . $nl;
942
+
943
  $resize_result = $image->resize( $new_width, $new_height, false );
944
+
945
  if ( is_wp_error( $resize_result ) ) {
946
  $this->writeLog( sprintf( 'Resize error: %s. Details: %s', $resize_result->get_error_messages(), $log_message ) );
947
+
948
  return false;
949
  }
950
+
951
  $save_result = $image->save( $this->path );
952
+
953
  if ( is_wp_error( $save_result ) ) {
954
  $this->writeLog( sprintf( 'Failed to save resized error in db: %s, Details: %s', $save_result->get_error_messages(), $log_message ) );
955
+
956
  return false;
957
  }
958
+
959
  $this->attachment_meta['width'] = $new_width;
960
  $this->attachment_meta['height'] = $new_height;
961
  $this->attachment_meta['old_width'] = $current_size['width'];
962
  $this->attachment_meta['old_height'] = $current_size['height'];
963
+
964
  wp_update_attachment_metadata( $this->id, $this->attachment_meta );
965
+
966
  return true;
967
  }
968
+
969
  /**
970
  * Делает резервную копию
971
  *
973
  */
974
  protected function backup() {
975
  $backup = WIO_Backup::get_instance();
976
+
977
  return $backup->backupAttachment( $this );
978
  }
979
+
980
  /**
981
  * Восстанавливает файлы из резервной копии
982
  *
984
  */
985
  public function restore() {
986
  $backup = WIO_Backup::get_instance();
987
+
988
  return $backup->restoreAttachment( $this );
989
  }
990
  }
includes/classes/class-rio-image-statistic.php CHANGED
@@ -135,7 +135,7 @@ class WRIO_Image_Statistic {
135
  $optimized_count = 0;
136
  }
137
  // unoptimized count: all - optimized - error
138
- $unoptimized_count = $this->getUnoptimizedCount();
139
  if ( $unoptimized_count < 0 ) {
140
  $unoptimized_count = 0;
141
  }
@@ -147,7 +147,7 @@ class WRIO_Image_Statistic {
147
  $percent_diff_line = 100;
148
  }
149
  if ( $total_images ) {
150
- $optimized_images_percent = round( $optimized_count * 100 / $total_images );
151
  } else {
152
  $optimized_images_percent = 0;
153
  }
@@ -166,9 +166,13 @@ class WRIO_Image_Statistic {
166
  }
167
 
168
  /**
169
- * Кол-во неоптимизированных изображений
 
 
 
 
170
  */
171
- public function getUnoptimizedCount() {
172
  global $wpdb;
173
  $db_table = RIO_Process_Queue::table_name();
174
 
@@ -181,57 +185,112 @@ class WRIO_Image_Statistic {
181
 
182
  $total_images = $wpdb->get_var( $sql_unoptimized );
183
 
184
- return $total_images;
185
  }
186
 
187
  /**
188
  * Возвращает результат последних оптимизаций изображений
189
  *
190
- * @param int $limit лимит
191
  *
192
  * @return array {
193
- * Параметры
194
- * {type} string $id id
195
- * {type} string $file_name Имя файла
196
- * {type} string $url URL
197
- * {type} string $thumbnail_url URL превьюшки
198
- * {type} string $original_size Размер до оптимизации
199
- * {type} string $optimized_size Размер после оптимизации
200
- * {type} string $webp_enabled webP включен
201
- * {type} string $webp_size webP размер
202
- * {type} string $original_saving На сколько процентов изменился главный файл
203
- * {type} string $thumbnails_count Сколько превьюшек оптимизировано
204
- * {type} string $total_saving Процент оптимизации главного файла и превьюшек
205
  * }
206
  */
207
  public function get_last_optimized_images( $limit = 100 ) {
208
  global $wpdb;
209
 
210
- $logs = [];
211
  $db_table = RIO_Process_Queue::table_name();
212
- $sql = $wpdb->prepare( "SELECT t1.*,t2.meta_value as attachment_meta
213
- FROM {$db_table} as t1
214
- LEFT JOIN {$wpdb->prefix}postmeta as t2 ON t1.object_id = t2.post_id
215
- WHERE t2.meta_key = '_wp_attachment_metadata' AND t1.item_type = 'attachment' AND t1.result_status IN (%s, %s)
216
  ORDER BY id DESC
217
  LIMIT %d ;", RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR, $limit );
218
 
219
- $optimized_images = $wpdb->get_results( $sql );
220
 
221
- if ( empty( $optimized_images ) ) {
222
- return $logs;
 
 
223
  }
224
 
225
- $upload_dir = wp_upload_dir();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
 
227
- if ( isset( $upload_dir['error'] ) && $upload_dir['error'] !== false ) {
228
- return $logs;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  }
230
 
231
- foreach ( $optimized_images as $row ) {
232
- $optimization_data = new RIO_Process_Queue( $row );
233
- $attachment_meta = unserialize( $row->attachment_meta );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
 
 
 
 
235
  $image_url = trailingslashit( $upload_dir['baseurl'] ) . $attachment_meta['file'];
236
  $thumbnail_url = $image_url;
237
 
@@ -240,58 +299,65 @@ class WRIO_Image_Statistic {
240
  $thumbnail_url = str_replace( $image_basename, $attachment_meta['sizes']['thumbnail']['file'], $image_url );
241
  }
242
 
243
- $item = [
244
- 'id' => $row->id,
245
- 'url' => $image_url,
246
- 'thumbnail_url' => $thumbnail_url,
247
- 'file_name' => wp_basename( $attachment_meta['file'] ),
248
- 'original_size' => size_format( $row->original_size, 2 ),
249
- 'optimized_size' => size_format( $row->final_size, 2 ),
250
- 'type' => 'success',
251
- 'webp_size' => null,
252
- 'original_saving' => 0,
253
- 'thumbnails_count' => 0,
254
- 'total_saving' => 0,
255
- ];
256
 
257
  $main_file = trailingslashit( $upload_dir['basedir'] ) . $attachment_meta['file'];
258
 
259
- /**
260
- * @var RIO_Attachment_Extra_Data $extra_data
261
- */
262
- $extra_data = $optimization_data->get_extra_data();
263
-
264
  if ( ! empty( $extra_data ) ) {
265
  $original_main_size = $extra_data->get_original_main_size();
266
 
267
  if ( $original_main_size && file_exists( $main_file ) ) {
268
- $original_saving = ( $original_main_size - filesize( $main_file ) ) * 100 / $original_main_size;
269
- $item['original_saving'] = round( $original_saving ) . '%';
270
  }
271
 
272
  $webp_size = $extra_data->get_webp_main_size();
273
 
274
  if ( $webp_size ) {
275
- $item['webp_size'] = size_format( $webp_size, 2 );
276
  }
277
 
278
- $item['thumbnails_count'] = $extra_data->get_thumbnails_count();
 
279
 
280
- if ( $row->result_status == RIO_Process_Queue::STATUS_ERROR || ! empty( $error ) ) {
281
- $item['type'] = 'error';
282
- $item['error_msg'] = $extra_data->get_error_msg();
283
- }
 
 
 
 
 
 
 
 
284
  }
285
 
286
- if ( $row->original_size ) {
287
- $total_saving = ( $row->original_size - $row->final_size ) * 100 / $row->original_size;
288
- $item['total_saving'] = round( $total_saving, 2 ) . '%';
 
 
 
 
 
 
289
  }
290
 
291
- $logs[] = $item;
 
 
 
292
  }
293
 
294
- return $logs;
295
  }
296
 
297
  /**
135
  $optimized_count = 0;
136
  }
137
  // unoptimized count: all - optimized - error
138
+ $unoptimized_count = static::get_unoptimized_count();
139
  if ( $unoptimized_count < 0 ) {
140
  $unoptimized_count = 0;
141
  }
147
  $percent_diff_line = 100;
148
  }
149
  if ( $total_images ) {
150
+ $optimized_images_percent = floor( $optimized_count * 100 / $total_images );
151
  } else {
152
  $optimized_images_percent = 0;
153
  }
166
  }
167
 
168
  /**
169
+ * Count of non-optimized images
170
+ *
171
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
172
+ * @since 1.3.6
173
+ * @return int
174
  */
175
+ public static function get_unoptimized_count() {
176
  global $wpdb;
177
  $db_table = RIO_Process_Queue::table_name();
178
 
185
 
186
  $total_images = $wpdb->get_var( $sql_unoptimized );
187
 
188
+ return (int) $total_images;
189
  }
190
 
191
  /**
192
  * Возвращает результат последних оптимизаций изображений
193
  *
194
+ * @param int $limit лимит
195
  *
196
  * @return array {
197
+ * Параметры
198
+ * @type string $id id
199
+ * @type string $file_name Имя файла
200
+ * @type string $url URL
201
+ * @type string $thumbnail_url URL превьюшки
202
+ * @type string $original_size Размер до оптимизации
203
+ * @type string $optimized_size Размер после оптимизации
204
+ * @type string $webp_size webP размер
205
+ * @type string $original_saving На сколько процентов изменился главный файл
206
+ * @type string $thumbnails_count Сколько превьюшек оптимизировано
207
+ * @type string $total_saving Процент оптимизации главного файла и превьюшек
 
208
  * }
209
  */
210
  public function get_last_optimized_images( $limit = 100 ) {
211
  global $wpdb;
212
 
213
+ $items = [];
214
  $db_table = RIO_Process_Queue::table_name();
215
+ $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
216
+ WHERE item_type = 'attachment' AND result_status IN (%s, %s)
 
 
217
  ORDER BY id DESC
218
  LIMIT %d ;", RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR, $limit );
219
 
220
+ $optimized_images = $wpdb->get_results( $sql, ARRAY_A );
221
 
222
+ if ( ! empty( $optimized_images ) ) {
223
+ foreach ( $optimized_images as $row ) {
224
+ $items[] = $this->format_for_log( new RIO_Process_Queue( $row ) );
225
+ }
226
  }
227
 
228
+ return $items;
229
+ }
230
+
231
+ /**
232
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
233
+ * @since 1.3.9
234
+ *
235
+ * @param int $object_id
236
+ */
237
+ public function get_last_optimized_image( $object_id ) {
238
+ global $wpdb;
239
+
240
+ $items = [];
241
+ $db_table = RIO_Process_Queue::table_name();
242
+ $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
243
+ WHERE object_id = '%d' AND item_type = 'attachment' AND result_status IN (%s, %s)
244
+ ORDER BY id DESC
245
+ LIMIT 1;", (int) $object_id, RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR );
246
+
247
+ $model = $wpdb->get_row( $sql, ARRAY_A );
248
 
249
+ if ( ! empty( $model ) ) {
250
+ $items[] = $this->format_for_log( new RIO_Process_Queue( $model ) );
251
+ }
252
+
253
+ return $items;
254
+ }
255
+
256
+ /**
257
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
258
+ * @since 1.3.9
259
+ *
260
+ * @param RIO_Process_Queue $queue_model
261
+ *
262
+ * @return array
263
+ * @throws \Exception
264
+ */
265
+ protected function format_for_log( $queue_model ) {
266
+ if ( ! $queue_model instanceof RIO_Process_Queue ) {
267
+ throw new Exception( 'Variable $queue_model must be an instance of RIO_Process_Queue!' );
268
  }
269
 
270
+ /**
271
+ * @var RIO_Attachment_Extra_Data $extra_data
272
+ */
273
+ $extra_data = $queue_model->get_extra_data();
274
+
275
+ $default_formated_data = [
276
+ 'id' => $queue_model->get_id(),
277
+ 'url' => admin_url( sprintf( "post.php?post=%d&action=edit", $queue_model->get_object_id() ) ),
278
+ 'thumbnail_url' => null,
279
+ 'file_name' => null,
280
+ 'original_size' => 0,
281
+ 'optimized_size' => 0,
282
+ 'type' => 'success',
283
+ 'webp_size' => null,
284
+ 'original_saving' => 0,
285
+ 'thumbnails_count' => 0,
286
+ 'total_saving' => 0,
287
+ ];
288
+
289
+ $upload_dir = wp_upload_dir();
290
 
291
+ $attachment_meta = wp_get_attachment_metadata( $queue_model->get_object_id() );
292
+
293
+ if ( ! empty( $attachment_meta ) ) {
294
  $image_url = trailingslashit( $upload_dir['baseurl'] ) . $attachment_meta['file'];
295
  $thumbnail_url = $image_url;
296
 
299
  $thumbnail_url = str_replace( $image_basename, $attachment_meta['sizes']['thumbnail']['file'], $image_url );
300
  }
301
 
302
+ $formated_data = wp_parse_args( [
303
+ 'thumbnail_url' => $thumbnail_url,
304
+ 'file_name' => wp_basename( $attachment_meta['file'] ),
305
+ 'original_size' => size_format( $queue_model->get_original_size(), 2 ),
306
+ 'optimized_size' => size_format( $queue_model->get_final_size(), 2 )
307
+ ], $default_formated_data );
 
 
 
 
 
 
 
308
 
309
  $main_file = trailingslashit( $upload_dir['basedir'] ) . $attachment_meta['file'];
310
 
311
+ # An extra data may be empty after a failed migration or an unknown error.
 
 
 
 
312
  if ( ! empty( $extra_data ) ) {
313
  $original_main_size = $extra_data->get_original_main_size();
314
 
315
  if ( $original_main_size && file_exists( $main_file ) ) {
316
+ $original_saving = ( $original_main_size - filesize( $main_file ) ) * 100 / $original_main_size;
317
+ $formated_data['original_saving'] = round( $original_saving ) . '%';
318
  }
319
 
320
  $webp_size = $extra_data->get_webp_main_size();
321
 
322
  if ( $webp_size ) {
323
+ $formated_data['webp_size'] = size_format( $webp_size, 2 );
324
  }
325
 
326
+ $formated_data['thumbnails_count'] = $extra_data->get_thumbnails_count();
327
+ }
328
 
329
+ if ( $queue_model->get_original_size() ) {
330
+ $total_saving = ( $queue_model->get_original_size() - $queue_model->get_final_size() ) * 100 / $queue_model->get_original_size();
331
+ $formated_data['total_saving'] = round( $total_saving, 2 ) . '%';
332
+ }
333
+ } else {
334
+ $attachment = get_post( $queue_model->get_object_id() );
335
+
336
+ if ( ! empty( $attachment ) ) {
337
+ $formated_data = [
338
+ 'thumbnail_url' => $attachment->guid,
339
+ 'file_name' => wp_basename( $attachment->guid )
340
+ ];
341
  }
342
 
343
+ $formated_data = wp_parse_args( $formated_data, $default_formated_data );
344
+ }
345
+
346
+ # We collect information about errors
347
+ if ( $queue_model->get_result_status() == RIO_Process_Queue::STATUS_ERROR ) {
348
+ $error_message = null;
349
+
350
+ if ( ! empty( $extra_data ) ) {
351
+ $error_message = $extra_data->get_error_msg();
352
  }
353
 
354
+ $formated_data['type'] = 'error';
355
+ $formated_data['error_msg'] = ! empty( $error_message ) ? $error_message : __( 'Unknown error', 'robin-image-optimizer' );
356
+
357
+ return $formated_data;
358
  }
359
 
360
+ return $formated_data;
361
  }
362
 
363
  /**
includes/classes/class-rio-media-library.php CHANGED
@@ -48,8 +48,7 @@ class WRIO_Media_Library {
48
  public function initHooks() {
49
  // оптимизация при загрузке в медиабиблиотеку
50
  if ( WRIO_Plugin::app()->getPopulateOption( 'auto_optimize_when_upload', false ) ) {
51
- add_filter( 'wp_generate_attachment_metadata', [ $this, 'optimizeAfterUpload' ], 10, 2 );
52
- //rest_after_insert_attachment
53
  }
54
 
55
  // соло оптимизация
@@ -71,26 +70,29 @@ class WRIO_Media_Library {
71
  *
72
  * @return array $metadata Метаданные аттачмента
73
  */
74
- public function optimizeAfterUpload( $metadata, $attachment_id ) {
75
  // todo: There is a bug in this method! The filter is executed when meta data is not saved yet.
76
  // todo: So you need to generate the meta data of the image again in the process of optimizing the image.
77
  // todo: The best solution would be to add images to the queue for optimization. And do not optimize them from the current moment.
78
 
79
  $backup = WIO_Backup::get_instance();
80
  $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
 
81
  if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
82
  return $metadata;
83
  }
84
 
85
- $attachment = $this->getAttachment( $attachment_id, $metadata );
86
- $this->optimizeAttachment( $attachment_id );
 
 
87
  $metadata = $attachment->getMetaData();
88
  $server = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' );
89
 
90
  // если отложенная оптимизация
91
  if ( in_array( $server, [ 'server_4' ] ) ) {
92
  sleep( 2 );
93
- $this->processDeferredOptimization();
94
  }
95
 
96
  return $metadata;
@@ -123,6 +125,7 @@ class WRIO_Media_Library {
123
  public function optimizeAttachment( $attachment_id, $level = '' ) {
124
  $wio_attachment = $this->getAttachment( $attachment_id );
125
  $optimization_data = $wio_attachment->getOptimizationData();
 
126
  if ( 'processing' == $optimization_data->get_result_status() ) {
127
  return $this->deferredOptimizeAttachment( $attachment_id );
128
  }
@@ -230,75 +233,47 @@ class WRIO_Media_Library {
230
  * @return array|\WP_Error
231
  */
232
  public function processUnoptimizedImages( $max_process_per_request ) {
233
- // $server = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' );
234
- $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
235
- $optimization_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
236
 
237
- if ( $optimization_level == 'custom' ) {
238
- $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
239
- $optimization_level = $custom_quality;
240
- }
241
 
242
- //do_action( 'wbcr/rio/multisite_current_blog' );
243
  $backup = WIO_Backup::get_instance();
244
 
245
  if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
246
  return new WP_Error( 'unwritable_backup_dir', __( 'No access for writing backups.', 'robin-image-optimizer' ) );
247
- //do_action( 'wbcr/rio/multisite_restore_blog' );
248
  }
249
 
250
  if ( ! $backup->isUploadWritable() ) {
251
- //do_action( 'wbcr/rio/multisite_restore_blog' );
252
  return new WP_Error( 'unwritable_upload_dir', __( 'No access for writing backups.', 'robin-image-optimizer' ) );
253
  }
254
 
255
- global $wpdb;
256
  $db_table = RIO_Process_Queue::table_name();
257
  $max_process_per_request = intval( $max_process_per_request );
258
- $level = esc_sql( $optimization_level );
259
 
260
  $sql = "SELECT DISTINCT posts.ID
261
- FROM {$wpdb->posts} AS posts
262
- LEFT JOIN {$db_table} AS rio ON posts.ID = rio.object_id
263
- WHERE ( ( rio.object_id IS NULL ) OR ( rio.item_type = 'attachment' AND rio.result_status = 'success' AND rio.processing_level != '{$level}' ) )
264
- AND posts.post_type = 'attachment'
265
- AND posts.post_status = 'inherit'
266
- AND posts.post_mime_type IN ( 'image/jpeg', 'image/gif', 'image/png' )
267
- LIMIT {$max_process_per_request}";
268
-
269
- // This was cut from $sql query above due to bug investigation from RIO-111, but related to media
270
- // AND ( rio.item_type = 'attachment' OR rio.item_type IS NULL )
271
 
272
  //выборка неоптимизированных изображений
273
  $unoptimized_attachments_ids = $wpdb->get_col( $sql );
274
 
275
  // временно
276
- $optimized_count = RIO_Process_Queue::count_by_type_status( 'attachment', 'success' );
277
-
278
- if ( ! $optimized_count ) {
279
- $optimized_count = 0;
280
- }
281
-
282
- $sql_unoptimized = "SELECT COUNT(DISTINCT p.ID)
283
- FROM {$wpdb->posts} p
284
- WHERE NOT EXISTS (SELECT *
285
- FROM {$db_table}
286
- WHERE p.ID = object_id AND p.post_type = item_type)
287
- AND p.post_type = 'attachment' AND p.post_mime_type IN ( 'image/jpeg', 'image/gif', 'image/png' )";
288
-
289
- $total_unoptimized = $wpdb->get_var( $sql_unoptimized );
290
 
291
- $attachments_count = 0;
292
-
293
- if ( isset( $unoptimized_attachments_ids ) ) {
294
- $attachments_count = count( $unoptimized_attachments_ids );
295
- }
296
-
297
- $original_size = 0;
298
- $optimized_size = 0;
299
 
300
  // обработка
301
  if ( ! empty( $attachments_count ) ) {
 
302
  foreach ( $unoptimized_attachments_ids as $attachment_id ) {
303
  $wio_attachment = $this->getAttachment( $attachment_id );
304
  if ( $wio_attachment->isOptimized() ) {
@@ -308,6 +283,7 @@ LIMIT {$max_process_per_request}";
308
  $attachment_optimized_data = $wio_attachment->optimize();
309
  $original_size = $original_size + $attachment_optimized_data['original_size'];
310
  $optimized_size = $optimized_size + $attachment_optimized_data['optimized_size'];
 
311
  }
312
  }
313
 
@@ -323,6 +299,7 @@ LIMIT {$max_process_per_request}";
323
 
324
  // проверяем, есть ли аттачменты в очереди на отложенную оптимизацию
325
  $optimized_data = $this->processDeferredOptimization();
 
326
  if ( $optimized_data ) {
327
  $optimized_count = $optimized_data['optimized_count'];
328
  $remain = $total_unoptimized - $optimized_count;
@@ -332,16 +309,17 @@ LIMIT {$max_process_per_request}";
332
  $remain = 0;
333
  }
334
 
 
 
 
335
  $response = [
336
  'remain' => $remain,
337
  'end' => false,
338
  'statistic' => $image_statistics->load(),
339
- 'last_optimized' => $image_statistics->get_last_optimized_images( $max_process_per_request ),
340
  'optimized_count' => $optimized_count,
341
  ];
342
 
343
- //do_action( 'wbcr/rio/multisite_restore_blog' );
344
-
345
  return $response;
346
  }
347
 
48
  public function initHooks() {
49
  // оптимизация при загрузке в медиабиблиотеку
50
  if ( WRIO_Plugin::app()->getPopulateOption( 'auto_optimize_when_upload', false ) ) {
51
+ add_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload', 10, 2 );
 
52
  }
53
 
54
  // соло оптимизация
70
  *
71
  * @return array $metadata Метаданные аттачмента
72
  */
73
+ public static function optimize_after_upload( $metadata, $attachment_id ) {
74
  // todo: There is a bug in this method! The filter is executed when meta data is not saved yet.
75
  // todo: So you need to generate the meta data of the image again in the process of optimizing the image.
76
  // todo: The best solution would be to add images to the queue for optimization. And do not optimize them from the current moment.
77
 
78
  $backup = WIO_Backup::get_instance();
79
  $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
80
+
81
  if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
82
  return $metadata;
83
  }
84
 
85
+ $media_library = static::get_instance();
86
+
87
+ $attachment = $media_library->getAttachment( $attachment_id, $metadata );
88
+ $media_library->optimizeAttachment( $attachment_id );
89
  $metadata = $attachment->getMetaData();
90
  $server = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' );
91
 
92
  // если отложенная оптимизация
93
  if ( in_array( $server, [ 'server_4' ] ) ) {
94
  sleep( 2 );
95
+ $media_library->processDeferredOptimization();
96
  }
97
 
98
  return $metadata;
125
  public function optimizeAttachment( $attachment_id, $level = '' ) {
126
  $wio_attachment = $this->getAttachment( $attachment_id );
127
  $optimization_data = $wio_attachment->getOptimizationData();
128
+
129
  if ( 'processing' == $optimization_data->get_result_status() ) {
130
  return $this->deferredOptimizeAttachment( $attachment_id );
131
  }
233
  * @return array|\WP_Error
234
  */
235
  public function processUnoptimizedImages( $max_process_per_request ) {
236
+ global $wpdb;
 
 
237
 
238
+ $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
 
 
 
239
 
 
240
  $backup = WIO_Backup::get_instance();
241
 
242
  if ( $backup_origin_images && ! $backup->isBackupWritable() ) {
243
  return new WP_Error( 'unwritable_backup_dir', __( 'No access for writing backups.', 'robin-image-optimizer' ) );
 
244
  }
245
 
246
  if ( ! $backup->isUploadWritable() ) {
 
247
  return new WP_Error( 'unwritable_upload_dir', __( 'No access for writing backups.', 'robin-image-optimizer' ) );
248
  }
249
 
 
250
  $db_table = RIO_Process_Queue::table_name();
251
  $max_process_per_request = intval( $max_process_per_request );
 
252
 
253
  $sql = "SELECT DISTINCT posts.ID
254
+ FROM {$wpdb->posts} AS posts
255
+ LEFT JOIN {$db_table} AS rio ON posts.ID = rio.object_id AND rio.item_type = 'attachment'
256
+ WHERE rio.object_id IS NULL
257
+ AND posts.post_type = 'attachment'
258
+ AND posts.post_status = 'inherit'
259
+ AND posts.post_mime_type IN ( 'image/jpeg', 'image/gif', 'image/png' )
260
+ LIMIT {$max_process_per_request}";
 
 
 
261
 
262
  //выборка неоптимизированных изображений
263
  $unoptimized_attachments_ids = $wpdb->get_col( $sql );
264
 
265
  // временно
266
+ $optimized_count = (int) RIO_Process_Queue::count_by_type_status( 'attachment', 'success' );
267
+ $attachments_count = ! empty( $unoptimized_attachments_ids ) ? sizeof( $unoptimized_attachments_ids ) : 0;
268
+ $total_unoptimized = WRIO_Image_Statistic::get_unoptimized_count();
 
 
 
 
 
 
 
 
 
 
 
269
 
270
+ $original_size = 0;
271
+ $optimized_size = 0;
272
+ $optimized_items = [];
 
 
 
 
 
273
 
274
  // обработка
275
  if ( ! empty( $attachments_count ) ) {
276
+
277
  foreach ( $unoptimized_attachments_ids as $attachment_id ) {
278
  $wio_attachment = $this->getAttachment( $attachment_id );
279
  if ( $wio_attachment->isOptimized() ) {
283
  $attachment_optimized_data = $wio_attachment->optimize();
284
  $original_size = $original_size + $attachment_optimized_data['original_size'];
285
  $optimized_size = $optimized_size + $attachment_optimized_data['optimized_size'];
286
+ $optimized_items[] = $attachment_id;
287
  }
288
  }
289
 
299
 
300
  // проверяем, есть ли аттачменты в очереди на отложенную оптимизацию
301
  $optimized_data = $this->processDeferredOptimization();
302
+
303
  if ( $optimized_data ) {
304
  $optimized_count = $optimized_data['optimized_count'];
305
  $remain = $total_unoptimized - $optimized_count;
309
  $remain = 0;
310
  }
311
 
312
+ # Take the last optimized image ID. Used to log 100 optimized images.
313
+ $last_optimized_id = end( $optimized_items );
314
+
315
  $response = [
316
  'remain' => $remain,
317
  'end' => false,
318
  'statistic' => $image_statistics->load(),
319
+ 'last_optimized' => $image_statistics->get_last_optimized_image( $last_optimized_id ),
320
  'optimized_count' => $optimized_count,
321
  ];
322
 
 
 
323
  return $response;
324
  }
325
 
includes/classes/class-rio-views.php CHANGED
@@ -63,11 +63,11 @@ class WRIO_Views {
63
  *
64
  * @param string $template The template name.
65
  * @param mixed $data Some data to pass to the template.
66
- * @param Wbcr_FactoryClearfy208_PageBase $page
67
  *
68
  * @return bool|string The page contents. False if the template doesn't exist.
69
  */
70
- public function get_template( $template, $data = [], Wbcr_FactoryClearfy208_PageBase $page = null ) {
71
  $template = str_replace( '_', '-', $template );
72
  $path = $this->plugin_dir . '/views/' . $template . '.php';
73
 
@@ -92,9 +92,9 @@ class WRIO_Views {
92
  *
93
  * @param string $template The template name.
94
  * @param mixed $data Some data to pass to the template.
95
- * @param Wbcr_FactoryClearfy208_PageBase $page
96
  */
97
- public function print_template( $template, $data = [], Wbcr_FactoryClearfy208_PageBase $page = null ) {
98
  echo $this->get_template( $template, $data, $page );
99
  }
100
  }
63
  *
64
  * @param string $template The template name.
65
  * @param mixed $data Some data to pass to the template.
66
+ * @param Wbcr_FactoryClearfy216_PageBase $page
67
  *
68
  * @return bool|string The page contents. False if the template doesn't exist.
69
  */
70
+ public function get_template( $template, $data = [], Wbcr_FactoryClearfy216_PageBase $page = null ) {
71
  $template = str_replace( '_', '-', $template );
72
  $path = $this->plugin_dir . '/views/' . $template . '.php';
73
 
92
  *
93
  * @param string $template The template name.
94
  * @param mixed $data Some data to pass to the template.
95
+ * @param Wbcr_FactoryClearfy216_PageBase $page
96
  */
97
+ public function print_template( $template, $data = [], Wbcr_FactoryClearfy216_PageBase $page = null ) {
98
  echo $this->get_template( $template, $data, $page );
99
  }
100
  }
includes/classes/index.php CHANGED
@@ -1,2 +1,3 @@
1
  <?php
2
  // silence is golden
 
1
  <?php
2
  // silence is golden
3
+
includes/classes/logger/class-rio-logger.php CHANGED
@@ -329,6 +329,10 @@ class WRIO_Logger {
329
  * @return bool|string
330
  */
331
  public static function get_content() {
 
 
 
 
332
  return @file_get_contents( static::get_dir() );
333
  }
334
 
@@ -342,13 +346,13 @@ class WRIO_Logger {
342
  */
343
  public static function add( $level, $message ) {
344
 
345
- if ( $level === self::LEVEL_DEBUG ) {
346
- $log_debug = defined( 'WP_DEBUG' ) && WP_DEBUG;
347
 
348
- if ( ! $log_debug ) {
349
- return false;
350
- }
351
- }
352
 
353
  static::$_logs[] = static::get_format( $level, $message );
354
 
329
  * @return bool|string
330
  */
331
  public static function get_content() {
332
+ if ( ! file_exists( static::get_dir() ) ) {
333
+ return null;
334
+ }
335
+
336
  return @file_get_contents( static::get_dir() );
337
  }
338
 
346
  */
347
  public static function add( $level, $message ) {
348
 
349
+ //if ( $level === self::LEVEL_DEBUG ) {
350
+ //$log_debug = defined( 'WP_DEBUG' ) && WP_DEBUG;
351
 
352
+ //if ( ! $log_debug ) {
353
+ //return false;
354
+ //}
355
+ //}
356
 
357
  static::$_logs[] = static::get_format( $level, $message );
358
 
includes/classes/models/class-rio-process-queue-table.php CHANGED
@@ -154,6 +154,40 @@ class RIO_Process_Queue extends RIO_Base_Active_Record {
154
  return $wpdb->prefix . 'rio_process_queue';
155
  }
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  /**
158
  * Find db item by hash.
159
  *
@@ -879,12 +913,14 @@ class RIO_Process_Queue extends RIO_Base_Active_Record {
879
  $sql_index_type_status_level = "ALTER TABLE {$table_name} ADD INDEX `index-type-status-level` (`item_type`, `result_status`, `processing_level`);";
880
  $sql_index_hash = "ALTER TABLE {$table_name} ADD UNIQUE `index-hash` (`item_hash`);";
881
  $sql_index_hash_alternative = "ALTER TABLE {$table_name} ADD INDEX `index-hash-alternative` (`item_hash_alternative`);";
 
882
 
883
  return [
884
  $sql_index_type_status,
885
  $sql_index_type_status_level,
886
  $sql_index_hash,
887
  $sql_index_hash_alternative,
 
888
  ];
889
  }
890
 
@@ -903,9 +939,7 @@ class RIO_Process_Queue extends RIO_Base_Active_Record {
903
  return;
904
  }
905
 
906
- $db_version = (int) WRIO_Plugin::app()->getOption( 'db_version', 0 );
907
-
908
- if ( ! $db_version ) {
909
  $sql = static::get_table_schema();
910
  $wpdb->query( $sql );
911
 
@@ -917,8 +951,7 @@ class RIO_Process_Queue extends RIO_Base_Active_Record {
917
  }
918
  }
919
 
920
- WRIO_Plugin::app()->updateOption( 'db_version', 1 );
921
-
922
  static::fix_table_collation();
923
  }
924
  } catch( \Exception $e ) {
154
  return $wpdb->prefix . 'rio_process_queue';
155
  }
156
 
157
+ /**
158
+ * It is used to check the migration and create a schema in the database.
159
+ * Gets the level of activity performed in the database.
160
+ *
161
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
162
+ * @since 1.3.8
163
+ * @return int
164
+ */
165
+ public static function get_db_version() {
166
+ if ( WRIO_Plugin::app()->isNetworkActive() ) {
167
+ return (int) get_site_option( WRIO_Plugin::app()->getOptionName( 'db_version' ), 0 );
168
+ }
169
+
170
+ return (int) get_option( WRIO_Plugin::app()->getOptionName( 'db_version' ), 0 );
171
+ }
172
+
173
+ /**
174
+ * It is used to check the migration and create a schema in the database.
175
+ * Updates the level of activity performed in the database.
176
+ *
177
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
178
+ * @since 1.3.8
179
+ * @return void
180
+ */
181
+ public static function update_db_version( $version ) {
182
+ if ( WRIO_Plugin::app()->isNetworkActive() ) {
183
+ update_site_option( WRIO_Plugin::app()->getOptionName( 'db_version' ), (int) $version );
184
+
185
+ return;
186
+ }
187
+
188
+ update_option( WRIO_Plugin::app()->getOptionName( 'db_version' ), (int) $version );
189
+ }
190
+
191
  /**
192
  * Find db item by hash.
193
  *
913
  $sql_index_type_status_level = "ALTER TABLE {$table_name} ADD INDEX `index-type-status-level` (`item_type`, `result_status`, `processing_level`);";
914
  $sql_index_hash = "ALTER TABLE {$table_name} ADD UNIQUE `index-hash` (`item_hash`);";
915
  $sql_index_hash_alternative = "ALTER TABLE {$table_name} ADD INDEX `index-hash-alternative` (`item_hash_alternative`);";
916
+ $sql_index_type_attachments = "ALTER TABLE {$table_name} ADD INDEX `index-type-attachments` (`object_id`, `item_type`);";
917
 
918
  return [
919
  $sql_index_type_status,
920
  $sql_index_type_status_level,
921
  $sql_index_hash,
922
  $sql_index_hash_alternative,
923
+ $sql_index_type_attachments
924
  ];
925
  }
926
 
939
  return;
940
  }
941
 
942
+ if ( ! static::get_db_version() ) {
 
 
943
  $sql = static::get_table_schema();
944
  $wpdb->query( $sql );
945
 
951
  }
952
  }
953
 
954
+ static::update_db_version( 1 );
 
955
  static::fix_table_collation();
956
  }
957
  } catch( \Exception $e ) {
includes/functions.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
 
 
 
3
  /**
4
  * Checks if the current request is a WP REST API request.
5
  *
@@ -58,13 +60,13 @@ function wrio_doing_cron() {
58
  * Convert full URL paths to absolute paths.
59
  *
60
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
61
- * @since 1.1
62
  *
63
- * @param string $url
64
  *
65
- * @return string|null
66
  */
67
- function wrio_convert_url_to_abs_path( $url ) {
68
  if ( empty( $url ) ) {
69
  return null;
70
  }
@@ -79,9 +81,42 @@ function wrio_convert_url_to_abs_path( $url ) {
79
 
80
  $url = rtrim( $url, '/' );
81
 
 
82
  return str_replace( get_site_url(), untrailingslashit( wp_normalize_path( ABSPATH ) ), $url );
83
  }
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  /**
86
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
87
  * @since 1.1
@@ -348,9 +383,9 @@ function wrio_get_server_url( $server_name ) {
348
  */
349
  function wbcr_rio_has_meta_to_migrate() {
350
 
351
- $db_version = WRIO_Plugin::app()->getOption( 'db_version', false );
352
 
353
- if ( $db_version !== false && (int) $db_version === 2 ) {
354
  return false;
355
  }
356
 
@@ -361,8 +396,8 @@ function wbcr_rio_has_meta_to_migrate() {
361
  return true;
362
  }
363
 
364
- if ( 1 === (int) $db_version ) {
365
- WRIO_Plugin::app()->updateOption( 'db_version', 2 );
366
  }
367
 
368
  return false;
1
  <?php
2
 
3
+ use WRIO\Paths\phpUri;
4
+
5
  /**
6
  * Checks if the current request is a WP REST API request.
7
  *
60
  * Convert full URL paths to absolute paths.
61
  *
62
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
63
+ * @since 1.4.0
64
  *
65
+ * @param string $url abs url https://site.com/wp-conent/uploads/10/05/image.jpeg
66
  *
67
+ * @return string|null abs path var/site.com/www/wp-conent/uploads/10/05/image.jpeg, if failure null
68
  */
69
+ function wrio_url_to_abs_path( $url ) {
70
  if ( empty( $url ) ) {
71
  return null;
72
  }
81
 
82
  $url = rtrim( $url, '/' );
83
 
84
+ # todo: if the external site, then it will not work
85
  return str_replace( get_site_url(), untrailingslashit( wp_normalize_path( ABSPATH ) ), $url );
86
  }
87
 
88
+ /**
89
+ * Convert relative urls to absolute
90
+ *
91
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
92
+ * @since 1.4.0
93
+ *
94
+ * @param string $url relative url /wp-conent/uploads/10/05/image.jpeg
95
+ *
96
+ * @return string abs url https://site.com/wp-conent/uploads/10/05/image.jpeg
97
+ */
98
+ function wrio_rel_to_abs_url( $url ) {
99
+ require_once WRIO_PLUGIN_DIR . '/libs/class-rio-relative-to-abs-uri.php';
100
+
101
+ return WRIO\Paths\phpUri::parse( get_site_url() )->join( $url );
102
+ }
103
+
104
+ /**
105
+ * Converts relative urls to absolute paths
106
+ *
107
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
108
+ * @since 1.4.0
109
+ *
110
+ * @param string $url relative url /wp-conent/uploads/10/05/image.jpeg
111
+ *
112
+ * @return string abs path var/site.com/www/wp-conent/uploads/10/05/image.jpeg
113
+ */
114
+ function wrio_rel_url_to_abs_path( $url ) {
115
+ $abs_url = wrio_rel_to_abs_url( $url );
116
+
117
+ return wrio_url_to_abs_path( $abs_url );
118
+ }
119
+
120
  /**
121
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
122
  * @since 1.1
383
  */
384
  function wbcr_rio_has_meta_to_migrate() {
385
 
386
+ $db_version = RIO_Process_Queue::get_db_version();
387
 
388
+ if ( 2 === $db_version ) {
389
  return false;
390
  }
391
 
396
  return true;
397
  }
398
 
399
+ if ( 1 === $db_version ) {
400
+ RIO_Process_Queue::update_db_version( 2 );
401
  }
402
 
403
  return false;
libs/addons/admin/ajax/folders.php CHANGED
@@ -2,8 +2,6 @@
2
 
3
  /**
4
  * AJAX обработчик выбора папки
5
- * todo: добавить обработку ошибок
6
- * todo: добавить nonce
7
  */
8
  add_action( 'wp_ajax_wriop_browse_dir', function () {
9
  if ( ! current_user_can( 'manage_options' ) ) {
@@ -36,12 +34,30 @@ add_action( 'wp_ajax_wriop_browse_dir', function () {
36
  $checkbox = $multiselect ? "<input type='checkbox' />" : null;
37
 
38
  $upload_dir = wp_upload_dir();
39
- $upload_dir_path = trailingslashit( str_replace( untrailingslashit( ABSPATH ), '', $upload_dir['basedir'] ) );
 
 
 
 
 
 
40
 
41
  $exclude_dirs = [
 
 
 
 
 
 
 
 
 
 
42
  $upload_dir_path . 'wio_backup',
43
- '/wp-admin',
44
- '/wp-includes'
 
 
45
  ];
46
  // исключаем все директории /wp-content/uploads/2019 - они уже оптимизируются в медиабиблиотеке.
47
  // с основания WP в 2003 году до текущего года + 1 на всякий случай.
2
 
3
  /**
4
  * AJAX обработчик выбора папки
 
 
5
  */
6
  add_action( 'wp_ajax_wriop_browse_dir', function () {
7
  if ( ! current_user_can( 'manage_options' ) ) {
34
  $checkbox = $multiselect ? "<input type='checkbox' />" : null;
35
 
36
  $upload_dir = wp_upload_dir();
37
+ $upload_dir_path = trailingslashit( str_replace( ABSPATH, '', $upload_dir['basedir'] ) );
38
+ $wp_content_dir = trailingslashit( str_replace( ABSPATH, '', WP_CONTENT_DIR ) );
39
+
40
+ $ngg_path = str_replace( wp_normalize_path( ABSPATH ), '', wrio_get_ngg_galleries_path() );
41
+ $shortpixel_path = str_replace( wp_normalize_path( ABSPATH ), '', wrio_get_shortpixel_path() );
42
+ $ewww_path = str_replace( wp_normalize_path( ABSPATH ), '', wrio_get_ewww_tools_path() );
43
+ $wc_path = str_replace( wp_normalize_path( ABSPATH ), '', wrio_get_wc_logs_path() );
44
 
45
  $exclude_dirs = [
46
+ $ngg_path,
47
+ $shortpixel_path,
48
+ $ewww_path,
49
+ $wc_path,
50
+ $wp_content_dir . 'backup',
51
+ $wp_content_dir . 'backups',
52
+ $wp_content_dir . 'cache',
53
+ $wp_content_dir . 'lang',
54
+ $wp_content_dir . 'langs',
55
+ $wp_content_dir . 'languages',
56
  $upload_dir_path . 'wio_backup',
57
+ $upload_dir_path . 'wrio',
58
+ $upload_dir_path . 'wrio-webp-uploads',
59
+ //'wp-admin',
60
+ //'wp-includes'
61
  ];
62
  // исключаем все директории /wp-content/uploads/2019 - они уже оптимизируются в медиабиблиотеке.
63
  // с основания WP в 2003 году до текущего года + 1 на всякий случай.
libs/addons/admin/assets/js/custom-folders.js CHANGED
@@ -86,10 +86,10 @@
86
  if( response.data && response.data.error_message ) {
87
  // todo: так как фреймворк не используется в аддоне, нужно доработать этот кусок кода. Он не
88
  // может быть скомпилирован.
89
- var noticeId = $.wbcr_factory_clearfy_208.app.showNotice(response.data.error_message, 'danger');
90
 
91
  setTimeout(function() {
92
- $.wbcr_factory_clearfy_208.app.hideNotice(noticeId);
93
  }, 5000);
94
  }
95
  return;
@@ -150,10 +150,10 @@
150
  if( response.data && response.data.error_message ) {
151
  // todo: так как фреймворк не используется в аддоне, нужно доработать этот кусок кода. Он не
152
  // может быть скомпилирован.
153
- var noticeId = $.wbcr_factory_clearfy_208.app.showNotice(response.data.error_message, 'danger');
154
 
155
  setTimeout(function() {
156
- $.wbcr_factory_clearfy_208.app.hideNotice(noticeId);
157
  }, 5000);
158
  }
159
  return;
86
  if( response.data && response.data.error_message ) {
87
  // todo: так как фреймворк не используется в аддоне, нужно доработать этот кусок кода. Он не
88
  // может быть скомпилирован.
89
+ var noticeId = $.wbcr_factory_clearfy_216.app.showNotice(response.data.error_message, 'danger');
90
 
91
  setTimeout(function() {
92
+ $.wbcr_factory_clearfy_216.app.hideNotice(noticeId);
93
  }, 5000);
94
  }
95
  return;
150
  if( response.data && response.data.error_message ) {
151
  // todo: так как фреймворк не используется в аддоне, нужно доработать этот кусок кода. Он не
152
  // может быть скомпилирован.
153
+ var noticeId = $.wbcr_factory_clearfy_216.app.showNotice(response.data.error_message, 'danger');
154
 
155
  setTimeout(function() {
156
+ $.wbcr_factory_clearfy_216.app.hideNotice(noticeId);
157
  }, 5000);
158
  }
159
  return;
libs/addons/admin/boot.php CHANGED
@@ -20,7 +20,7 @@ if ( ! defined( 'ABSPATH' ) ) {
20
  * Flush configuration after saving the settings
21
  *
22
  * @param WHM_Plugin $plugin
23
- * @param Wbcr_FactoryPages412_ImpressiveThemplate $page
24
  *
25
  * @return bool
26
  */
20
  * Flush configuration after saving the settings
21
  *
22
  * @param WHM_Plugin $plugin
23
+ * @param Wbcr_FactoryPages424_ImpressiveThemplate $page
24
  *
25
  * @return bool
26
  */
libs/addons/includes/classes/webp/class-webp-delivery.php CHANGED
@@ -3,6 +3,8 @@
3
  namespace WRIO\WEBP\HTML;
4
 
5
  // Exit if accessed directly
 
 
6
  if ( ! defined( 'ABSPATH' ) ) {
7
  exit;
8
  }
@@ -38,6 +40,7 @@ class Delivery {
38
  * Initiate the class.
39
  */
40
  public function init() {
 
41
  if ( static::is_webp_enabled() ) {
42
 
43
  if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
@@ -188,8 +191,10 @@ class Delivery {
188
  require_once WRIOP_PLUGIN_DIR . '/includes/classes/webp/class-webp-html-picture-tags.php';
189
  $content = Picture_Tags::replace( $content );
190
  } else if ( static::is_url_delivery_mode() ) {
191
- require_once( WRIOP_PLUGIN_DIR . '/includes/classes/webp/class-webp-html-image-urls-replacer.php' );
192
- $content = Urls_Replacer::replace( $content );
 
 
193
  }
194
 
195
  // If the search and replacement are completed with an error, then return the raw content.
@@ -215,26 +220,22 @@ class Delivery {
215
  * @return string
216
  */
217
  public static function get_webp_url( $source_url, $return_value_on_fail ) {
218
-
219
- // Currently we do not handle relative urls - so we skip
220
- if ( ! preg_match( '#^https?://#', $source_url ) ) {
221
  if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
222
- \WRIO_Logger::warning( sprintf( "Failed getting webp url. Invalid image url\r\nSource url: %s", $source_url ) );
223
  }
224
 
225
  return $return_value_on_fail;
226
  }
227
 
228
- if ( ! preg_match( '#(jpe?g|png)$#', $source_url ) ) {
229
- if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
230
- \WRIO_Logger::warning( sprintf( "Failed getting webp url. Unsupported image format\r\nSource url: %s", $source_url ) );
231
- }
232
-
233
- return $return_value_on_fail;
234
  }
235
 
 
 
236
  // If the image is stored on a remote server, need to skip it
237
- if ( strpos( $source_url, get_site_url() ) === false ) {
238
  if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
239
  \WRIO_Logger::warning( sprintf( "Failed getting webp url. Image is on a remote server\r\nSource url: %s", $source_url ) );
240
  }
@@ -250,21 +251,30 @@ class Delivery {
250
  return $return_value_on_fail;
251
  }
252
 
253
- $relative_file_path = wrio_convert_url_to_abs_path( $source_url );
 
 
 
 
 
 
 
 
 
254
 
255
  // If you could not find original image, skip it. Perhaps an error
256
  // in absolute path formation to the directory where the
257
  // image is stored.
258
- if ( empty( $relative_file_path ) || ! file_exists( $relative_file_path ) ) {
259
  if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
260
- \WRIO_Logger::warning( sprintf( "Failed getting webp url. Unable to find origin image\r\nRelative path: (%s)\r\nSource url: (%s)", $relative_file_path, $source_url ) );
261
  }
262
 
263
  return $return_value_on_fail;
264
  }
265
 
266
  $webp_file_url = $source_url . '.webp';
267
- $webp_file_path = $relative_file_path . '.webp';
268
 
269
  if ( ! file_exists( $webp_file_path ) ) {
270
  if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
@@ -277,12 +287,66 @@ class Delivery {
277
  return $webp_file_url;
278
  }
279
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  /**
281
  * Check whether browser supports WebP or not.
282
  *
283
  * @return bool
284
  */
285
- public static function is_supported_browser() {
286
  if ( isset( $_SERVER['HTTP_ACCEPT'] ) && strpos( $_SERVER['HTTP_ACCEPT'], 'image/webp' ) !== false || isset( $_SERVER['HTTP_USER_AGENT'] ) && strpos( $_SERVER['HTTP_USER_AGENT'], ' Chrome/' ) !== false ) {
287
  return true;
288
  }
3
  namespace WRIO\WEBP\HTML;
4
 
5
  // Exit if accessed directly
6
+ use WRIO_Logger;
7
+
8
  if ( ! defined( 'ABSPATH' ) ) {
9
  exit;
10
  }
40
  * Initiate the class.
41
  */
42
  public function init() {
43
+
44
  if ( static::is_webp_enabled() ) {
45
 
46
  if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
191
  require_once WRIOP_PLUGIN_DIR . '/includes/classes/webp/class-webp-html-picture-tags.php';
192
  $content = Picture_Tags::replace( $content );
193
  } else if ( static::is_url_delivery_mode() ) {
194
+ if(!is_admin()) {
195
+ require_once( WRIOP_PLUGIN_DIR . '/includes/classes/webp/class-webp-html-image-urls-replacer.php' );
196
+ $content = Urls_Replacer::replace( $content );
197
+ }
198
  }
199
 
200
  // If the search and replacement are completed with an error, then return the raw content.
220
  * @return string
221
  */
222
  public static function get_webp_url( $source_url, $return_value_on_fail ) {
223
+ if ( ! static::is_support_format( $source_url ) ) {
 
 
224
  if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
225
+ \WRIO_Logger::warning( sprintf( "Failed getting webp url. Unsupported image format\r\nSource url: %s", $source_url ) );
226
  }
227
 
228
  return $return_value_on_fail;
229
  }
230
 
231
+ if ( ! preg_match( '#^https?://#', $source_url ) ) {
232
+ $source_url = wrio_rel_to_abs_url( $source_url );
 
 
 
 
233
  }
234
 
235
+ $is_wpmedia_url = static::is_wpmedia_url( $source_url );
236
+
237
  // If the image is stored on a remote server, need to skip it
238
+ if ( static::is_external_url( $source_url ) && ! $is_wpmedia_url ) {
239
  if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
240
  \WRIO_Logger::warning( sprintf( "Failed getting webp url. Image is on a remote server\r\nSource url: %s", $source_url ) );
241
  }
251
  return $return_value_on_fail;
252
  }
253
 
254
+ if ( $is_wpmedia_url ) {
255
+ $upload_dir = wp_get_upload_dir();
256
+
257
+ $repace_dir = $upload_dir['basedir'];
258
+ $replace_url = $upload_dir['baseurl'];
259
+
260
+ $file_path = str_replace( $replace_url, $repace_dir, $source_url );
261
+ } else {
262
+ $file_path = wrio_url_to_abs_path( $source_url );
263
+ }
264
 
265
  // If you could not find original image, skip it. Perhaps an error
266
  // in absolute path formation to the directory where the
267
  // image is stored.
268
+ if ( empty( $file_path ) || ! file_exists( $file_path ) ) {
269
  if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
270
+ \WRIO_Logger::warning( sprintf( "Failed getting webp url. Unable to find origin image\r\nRelative path: (%s)\r\nSource url: (%s)", $file_path, $source_url ) );
271
  }
272
 
273
  return $return_value_on_fail;
274
  }
275
 
276
  $webp_file_url = $source_url . '.webp';
277
+ $webp_file_path = $file_path . '.webp';
278
 
279
  if ( ! file_exists( $webp_file_path ) ) {
280
  if ( \WRIO_Logger::is_keep_error_log_on_frontend() ) {
287
  return $webp_file_url;
288
  }
289
 
290
+ /**
291
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
292
+ * @since 1.4.0
293
+ *
294
+ * @param string $source_url
295
+ *
296
+ * @return bool
297
+ */
298
+ protected static function is_wpmedia_url( $source_url ) {
299
+ $upload_dir = wp_get_upload_dir();
300
+
301
+ if ( isset( $upload_dir['error'] ) && $upload_dir['error'] !== false ) {
302
+ return false;
303
+ }
304
+
305
+ if ( false !== strpos( $source_url, $upload_dir['baseurl'] ) ) {
306
+ return true;
307
+ }
308
+
309
+ return false;
310
+ }
311
+
312
+ /**
313
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
314
+ * @since 1.4.0
315
+ *
316
+ * @param string $source_url
317
+ *
318
+ * @return bool
319
+ */
320
+ protected static function is_support_format( $source_url ) {
321
+ if ( ! preg_match( '#(jpe?g|png)$#', $source_url ) ) {
322
+ return false;
323
+ }
324
+
325
+ return true;
326
+ }
327
+
328
+ /**
329
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
330
+ * @since 1.4.0
331
+ *
332
+ * @param string $source_url
333
+ *
334
+ * @return bool
335
+ */
336
+ protected static function is_external_url( $source_url ) {
337
+ if ( strpos( $source_url, get_site_url() ) === false ) {
338
+ return true;
339
+ }
340
+
341
+ return false;
342
+ }
343
+
344
  /**
345
  * Check whether browser supports WebP or not.
346
  *
347
  * @return bool
348
  */
349
+ protected static function is_supported_browser() {
350
  if ( isset( $_SERVER['HTTP_ACCEPT'] ) && strpos( $_SERVER['HTTP_ACCEPT'], 'image/webp' ) !== false || isset( $_SERVER['HTTP_USER_AGENT'] ) && strpos( $_SERVER['HTTP_USER_AGENT'], ' Chrome/' ) !== false ) {
351
  return true;
352
  }
libs/addons/includes/classes/webp/class-webp-listener.php CHANGED
@@ -7,6 +7,7 @@ if ( ! defined( 'ABSPATH' ) ) {
7
  exit;
8
  }
9
 
 
10
  use WRIO\WEBP\HTML\Delivery;
11
 
12
  /**
@@ -396,26 +397,25 @@ class Listener {
396
  // Fallback to get attachment meta it can be empty when WordPress failed to create it or invocation
397
  // of method was produced too soon
398
  if ( empty( $attachment_meta ) ) {
399
- $exploded_url = explode( 'wp-content/uploads/', $attachment->guid, 2 );
 
400
  if ( isset( $exploded_url[1] ) ) {
401
  $exploded_relative_path = trim( $exploded_url[1] );
402
  $path_from_url = trailingslashit( $dirs['basedir'] ) . $exploded_relative_path;
403
 
404
  // Need to remove this filter, as it would start recursion
405
- remove_filter( 'wp_generate_attachment_metadata', 'wp_generate_attachment_metadata' );
406
- remove_filter( 'wp_generate_attachment_metadata', [
407
- \WRIO_Media_Library::get_instance(),
408
- 'optimizeAfterUpload',
409
- ] );
410
 
411
  $attachment_meta = wp_generate_attachment_metadata( $attachment->ID, $path_from_url );
412
 
413
- add_filter( 'wp_generate_attachment_metadata', [
414
- \WRIO_Media_Library::get_instance(),
415
- 'optimizeAfterUpload',
416
- ], 10, 2 );
417
  }
418
  }
 
 
 
 
 
419
 
420
  if ( isset( $dirs['basedir'] ) && isset( $attachment_meta['file'] ) ) {
421
 
7
  exit;
8
  }
9
 
10
+ use WP_Post;
11
  use WRIO\WEBP\HTML\Delivery;
12
 
13
  /**
397
  // Fallback to get attachment meta it can be empty when WordPress failed to create it or invocation
398
  // of method was produced too soon
399
  if ( empty( $attachment_meta ) ) {
400
+ $exploded_url = explode('wp-content/uploads/', $attachment->guid, 2 );
401
+
402
  if ( isset( $exploded_url[1] ) ) {
403
  $exploded_relative_path = trim( $exploded_url[1] );
404
  $path_from_url = trailingslashit( $dirs['basedir'] ) . $exploded_relative_path;
405
 
406
  // Need to remove this filter, as it would start recursion
407
+ remove_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload' );
 
 
 
 
408
 
409
  $attachment_meta = wp_generate_attachment_metadata( $attachment->ID, $path_from_url );
410
 
411
+ add_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload', 10, 2 );
 
 
 
412
  }
413
  }
414
+ if ( empty( $attachment_meta ) ) {
415
+ \WRIO_Logger::error( sprintf( 'Attachment #%d metadata is empty. Webp image can not be converted.',$attachment->ID ) );
416
+
417
+ return $hashmap;
418
+ }
419
 
420
  if ( isset( $dirs['basedir'] ) && isset( $attachment_meta['file'] ) ) {
421
 
libs/addons/includes/classes/webp/composer.lock CHANGED
@@ -1,73 +1,73 @@
1
- {
2
- "_readme": [
3
- "This file locks the dependencies of your project to a known state",
4
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
- "This file is @generated automatically"
6
- ],
7
- "content-hash": "8d03ee8cf464879ef4a5fd1a6fba0c95",
8
- "packages": [
9
- {
10
- "name": "rosell-dk/dom-util-for-webp",
11
- "version": "0.3.0",
12
- "source": {
13
- "type": "git",
14
- "url": "https://github.com/rosell-dk/dom-util-for-webp.git",
15
- "reference": "c9cebf304553695fb6f7cf5634da51172e8e4aba"
16
- },
17
- "dist": {
18
- "type": "zip",
19
- "url": "https://api.github.com/repos/rosell-dk/dom-util-for-webp/zipball/c9cebf304553695fb6f7cf5634da51172e8e4aba",
20
- "reference": "c9cebf304553695fb6f7cf5634da51172e8e4aba",
21
- "shasum": ""
22
- },
23
- "require-dev": {
24
- "friendsofphp/php-cs-fixer": "^2.11",
25
- "phpunit/phpunit": "5.7.27",
26
- "squizlabs/php_codesniffer": "3.*"
27
- },
28
- "type": "library",
29
- "extra": {
30
- "scripts-descriptions": {
31
- "ci": "Run tests before CI",
32
- "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'",
33
- "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'",
34
- "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard",
35
- "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.",
36
- "test": "Launches the preconfigured PHPUnit"
37
- }
38
- },
39
- "autoload": {
40
- "psr-4": {
41
- "DOMUtilForWebP\\": "src/"
42
- }
43
- },
44
- "notification-url": "https://packagist.org/downloads/",
45
- "license": [
46
- "MIT"
47
- ],
48
- "authors": [
49
- {
50
- "name": "Bjørn Rosell",
51
- "homepage": "https://www.bitwise-it.dk/contact",
52
- "role": "Project Author"
53
- }
54
- ],
55
- "description": "Replace image URLs found in HTML",
56
- "keywords": [
57
- "Webp",
58
- "html",
59
- "images",
60
- "replace"
61
- ],
62
- "time": "2019-03-07T09:15:07+00:00"
63
- }
64
- ],
65
- "packages-dev": [],
66
- "aliases": [],
67
- "minimum-stability": "stable",
68
- "stability-flags": [],
69
- "prefer-stable": false,
70
- "prefer-lowest": false,
71
- "platform": [],
72
- "platform-dev": []
73
- }
1
+ {
2
+ "_readme": [
3
+ "This file locks the dependencies of your project to a known state",
4
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
+ "This file is @generated automatically"
6
+ ],
7
+ "content-hash": "8d03ee8cf464879ef4a5fd1a6fba0c95",
8
+ "packages": [
9
+ {
10
+ "name": "rosell-dk/dom-util-for-webp",
11
+ "version": "0.3.1",
12
+ "source": {
13
+ "type": "git",
14
+ "url": "https://github.com/rosell-dk/dom-util-for-webp.git",
15
+ "reference": "bae8f4a9b666726359d28bfb227d886c12f136a9"
16
+ },
17
+ "dist": {
18
+ "type": "zip",
19
+ "url": "https://api.github.com/repos/rosell-dk/dom-util-for-webp/zipball/bae8f4a9b666726359d28bfb227d886c12f136a9",
20
+ "reference": "bae8f4a9b666726359d28bfb227d886c12f136a9",
21
+ "shasum": ""
22
+ },
23
+ "require-dev": {
24
+ "friendsofphp/php-cs-fixer": "^2.11",
25
+ "phpunit/phpunit": "5.7.27",
26
+ "squizlabs/php_codesniffer": "3.*"
27
+ },
28
+ "type": "library",
29
+ "extra": {
30
+ "scripts-descriptions": {
31
+ "ci": "Run tests before CI",
32
+ "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'",
33
+ "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'",
34
+ "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard",
35
+ "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.",
36
+ "test": "Launches the preconfigured PHPUnit"
37
+ }
38
+ },
39
+ "autoload": {
40
+ "psr-4": {
41
+ "DOMUtilForWebP\\": "src/"
42
+ }
43
+ },
44
+ "notification-url": "https://packagist.org/downloads/",
45
+ "license": [
46
+ "MIT"
47
+ ],
48
+ "authors": [
49
+ {
50
+ "name": "Bjørn Rosell",
51
+ "role": "Project Author",
52
+ "homepage": "https://www.bitwise-it.dk/contact"
53
+ }
54
+ ],
55
+ "description": "Replace image URLs found in HTML",
56
+ "keywords": [
57
+ "Webp",
58
+ "html",
59
+ "images",
60
+ "replace"
61
+ ],
62
+ "time": "2019-07-31T14:17:18+00:00"
63
+ }
64
+ ],
65
+ "packages-dev": [],
66
+ "aliases": [],
67
+ "minimum-stability": "stable",
68
+ "stability-flags": [],
69
+ "prefer-stable": false,
70
+ "prefer-lowest": false,
71
+ "platform": [],
72
+ "platform-dev": []
73
+ }
libs/addons/includes/classes/webp/vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInitf915fc14971134da4d8f26cdeb45e0c1::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit07e8c2d809ebdfe41dd406bc58201d89::getLoader();
libs/addons/includes/classes/webp/vendor/composer/ClassLoader.php CHANGED
@@ -279,7 +279,7 @@ class ClassLoader
279
  */
280
  public function setApcuPrefix($apcuPrefix)
281
  {
282
- $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
283
  }
284
 
285
  /**
279
  */
280
  public function setApcuPrefix($apcuPrefix)
281
  {
282
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283
  }
284
 
285
  /**
libs/addons/includes/classes/webp/vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInitf915fc14971134da4d8f26cdeb45e0c1
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInitf915fc14971134da4d8f26cdeb45e0c1
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInitf915fc14971134da4d8f26cdeb45e0c1', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInitf915fc14971134da4d8f26cdeb45e0c1', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInitf915fc14971134da4d8f26cdeb45e0c1::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit07e8c2d809ebdfe41dd406bc58201d89
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit07e8c2d809ebdfe41dd406bc58201d89', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit07e8c2d809ebdfe41dd406bc58201d89', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit07e8c2d809ebdfe41dd406bc58201d89::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
libs/addons/includes/classes/webp/vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInitf915fc14971134da4d8f26cdeb45e0c1
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'D' =>
@@ -23,8 +23,8 @@ class ComposerStaticInitf915fc14971134da4d8f26cdeb45e0c1
23
  public static function getInitializer(ClassLoader $loader)
24
  {
25
  return \Closure::bind(function () use ($loader) {
26
- $loader->prefixLengthsPsr4 = ComposerStaticInitf915fc14971134da4d8f26cdeb45e0c1::$prefixLengthsPsr4;
27
- $loader->prefixDirsPsr4 = ComposerStaticInitf915fc14971134da4d8f26cdeb45e0c1::$prefixDirsPsr4;
28
 
29
  }, null, ClassLoader::class);
30
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit07e8c2d809ebdfe41dd406bc58201d89
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'D' =>
23
  public static function getInitializer(ClassLoader $loader)
24
  {
25
  return \Closure::bind(function () use ($loader) {
26
+ $loader->prefixLengthsPsr4 = ComposerStaticInit07e8c2d809ebdfe41dd406bc58201d89::$prefixLengthsPsr4;
27
+ $loader->prefixDirsPsr4 = ComposerStaticInit07e8c2d809ebdfe41dd406bc58201d89::$prefixDirsPsr4;
28
 
29
  }, null, ClassLoader::class);
30
  }
libs/addons/includes/classes/webp/vendor/composer/installed.json CHANGED
@@ -1,17 +1,17 @@
1
  [
2
  {
3
  "name": "rosell-dk/dom-util-for-webp",
4
- "version": "0.3.0",
5
- "version_normalized": "0.3.0.0",
6
  "source": {
7
  "type": "git",
8
  "url": "https://github.com/rosell-dk/dom-util-for-webp.git",
9
- "reference": "c9cebf304553695fb6f7cf5634da51172e8e4aba"
10
  },
11
  "dist": {
12
  "type": "zip",
13
- "url": "https://api.github.com/repos/rosell-dk/dom-util-for-webp/zipball/c9cebf304553695fb6f7cf5634da51172e8e4aba",
14
- "reference": "c9cebf304553695fb6f7cf5634da51172e8e4aba",
15
  "shasum": ""
16
  },
17
  "require-dev": {
@@ -19,7 +19,7 @@
19
  "phpunit/phpunit": "5.7.27",
20
  "squizlabs/php_codesniffer": "3.*"
21
  },
22
- "time": "2019-03-07T09:15:07+00:00",
23
  "type": "library",
24
  "extra": {
25
  "scripts-descriptions": {
@@ -44,8 +44,8 @@
44
  "authors": [
45
  {
46
  "name": "Bjørn Rosell",
47
- "homepage": "https://www.bitwise-it.dk/contact",
48
- "role": "Project Author"
49
  }
50
  ],
51
  "description": "Replace image URLs found in HTML",
1
  [
2
  {
3
  "name": "rosell-dk/dom-util-for-webp",
4
+ "version": "0.3.1",
5
+ "version_normalized": "0.3.1.0",
6
  "source": {
7
  "type": "git",
8
  "url": "https://github.com/rosell-dk/dom-util-for-webp.git",
9
+ "reference": "bae8f4a9b666726359d28bfb227d886c12f136a9"
10
  },
11
  "dist": {
12
  "type": "zip",
13
+ "url": "https://api.github.com/repos/rosell-dk/dom-util-for-webp/zipball/bae8f4a9b666726359d28bfb227d886c12f136a9",
14
+ "reference": "bae8f4a9b666726359d28bfb227d886c12f136a9",
15
  "shasum": ""
16
  },
17
  "require-dev": {
19
  "phpunit/phpunit": "5.7.27",
20
  "squizlabs/php_codesniffer": "3.*"
21
  },
22
+ "time": "2019-07-31T14:17:18+00:00",
23
  "type": "library",
24
  "extra": {
25
  "scripts-descriptions": {
44
  "authors": [
45
  {
46
  "name": "Bjørn Rosell",
47
+ "role": "Project Author",
48
+ "homepage": "https://www.bitwise-it.dk/contact"
49
  }
50
  ],
51
  "description": "Replace image URLs found in HTML",
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/README.md CHANGED
@@ -1,6 +1,11 @@
1
  # dom-util-for-webp
2
 
3
- [![Build Status](https://travis-ci.org/rosell-dk/dom-util-for-webp.png?branch=master)](https://travis-ci.org/rosell-dk/dom-util-for-webp)
 
 
 
 
 
4
 
5
  *Replace image URLs found in HTML*
6
 
1
  # dom-util-for-webp
2
 
3
+ [![Latest Stable Version](https://img.shields.io/packagist/v/rosell-dk/image-mime-type-guesser.svg?style=flat-square)](https://packagist.org/packages/rosell-dk/dom-util-for-webp)
4
+ [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.6-8892BF.svg?style=flat-square)](https://php.net)
5
+ [![Build Status](https://img.shields.io/travis/rosell-dk/dom-util-for-webp/master.svg?style=flat-square)](https://travis-ci.org/rosell-dk/dom-util-for-webp)
6
+ [![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://scrutinizer-ci.com/g/rosell-dk/dom-util-for-webp/code-structure/master)
7
+ [![Quality Score](https://img.shields.io/scrutinizer/g/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://scrutinizer-ci.com/g/rosell-dk/dom-util-for-webp/)
8
+ [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/rosell-dk/dom-util-for-webp/blob/master/LICENSE)
9
 
10
  *Replace image URLs found in HTML*
11
 
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/composer.json CHANGED
@@ -10,17 +10,19 @@
10
  "@build",
11
  "@test",
12
  "@phpcs-all",
13
- "@composer validate --no-check-all --strict"
 
14
  ],
15
  "cs-fix-all": [
16
  "php-cs-fixer fix src"
17
  ],
18
  "cs-fix": "php-cs-fixer fix",
19
  "cs-dry": "php-cs-fixer fix --dry-run --diff",
20
- "test": "phpunit",
21
  "phpcs": "phpcs --standard=PSR2",
22
- "phpcs-all": "phpcs --standard=PSR2 --ignore=src/simple_html_dom/simple_html_dom.inc src",
23
- "phpcbf": "phpcbf --standard=PSR2"
 
24
  },
25
  "extra": {
26
  "scripts-descriptions": {
10
  "@build",
11
  "@test",
12
  "@phpcs-all",
13
+ "@composer validate --no-check-all --strict",
14
+ "@phpstan-global"
15
  ],
16
  "cs-fix-all": [
17
  "php-cs-fixer fix src"
18
  ],
19
  "cs-fix": "php-cs-fixer fix",
20
  "cs-dry": "php-cs-fixer fix --dry-run --diff",
21
+ "test": "phpunit --coverage-text --coverage-clover=coverage.clover",
22
  "phpcs": "phpcs --standard=PSR2",
23
+ "phpcbf": "phpcbf --standard=PSR2",
24
+ "phpstan": "vendor/bin/phpstan analyse src --level=4",
25
+ "phpstan-global": "~/.composer/vendor/bin/phpstan analyse src --level=4"
26
  },
27
  "extra": {
28
  "scripts-descriptions": {
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/phpstan.neon ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ parameters:
2
+ ignoreErrors:
3
+ - '#Function str_get_html not found.#'
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/phpunit.xml.dist CHANGED
@@ -20,11 +20,19 @@
20
 
21
  <filter>
22
  <whitelist>
23
- <directory>./</directory>
24
  <exclude>
25
  <directory>./vendor</directory>
26
  <directory>./tests</directory>
27
  </exclude>
28
  </whitelist>
29
  </filter>
 
 
 
 
 
 
 
 
30
  </phpunit>
20
 
21
  <filter>
22
  <whitelist>
23
+ <directory suffix=".php">src/</directory>
24
  <exclude>
25
  <directory>./vendor</directory>
26
  <directory>./tests</directory>
27
  </exclude>
28
  </whitelist>
29
  </filter>
30
+
31
+ <logging>
32
+ <log type="junit" target="build/report.junit.xml"/>
33
+ <log type="coverage-clover" target="build/logs/clover.xml"/>
34
+ <log type="coverage-text" target="build/coverage.txt"/>
35
+ <!--<log type="coverage-html" target="build/coverage"/>-->
36
+ </logging>
37
+
38
  </phpunit>
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/{src → src-vendor}/simple_html_dom/simple_html_dom.inc RENAMED
File without changes
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src/ImageUrlReplacer.php CHANGED
@@ -26,17 +26,30 @@ namespace DOMUtilForWebP;
26
  class ImageUrlReplacer
27
  {
28
 
29
- // define tags to be searched. The div and li are on the list because these are often used with lazy loading
30
- public static $searchInTags = ['img', 'source', 'input', 'iframe', 'div', 'li'];
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  /**
33
  *
34
- * @return webp url or, if URL should not be changed, return nothing
35
  **/
36
  public function replaceUrl($url)
37
  {
38
  if (!preg_match('#(png|jpe?g)$#', $url)) {
39
- return;
40
  }
41
  return $url . '.webp';
42
  }
@@ -157,6 +170,11 @@ class ImageUrlReplacer
157
 
158
  //$dom = HtmlDomParser::str_get_html($html, false, false, 'UTF-8', false);
159
  $dom = str_get_html($html, false, false, 'UTF-8', false);
 
 
 
 
 
160
  if ($dom === false) {
161
  if (strlen($html) > MAX_FILE_SIZE) {
162
  return '<!-- Alter HTML was skipped because the HTML is too big to process! ' .
@@ -204,7 +222,7 @@ class ImageUrlReplacer
204
  public static function replace($html)
205
  {
206
  if (!function_exists('str_get_html')) {
207
- require_once 'simple_html_dom/simple_html_dom.inc';
208
  }
209
  $iur = new static();
210
  return $iur->replaceHtml($html);
26
  class ImageUrlReplacer
27
  {
28
 
29
+ // define tags to be searched.
30
+ // The div and li are on the list because these are often used with lazy loading
31
+ // should we add <meta> ?
32
+ // Probably not for open graph images or twitter
33
+ // so not these:
34
+ // - <meta property="og:image" content="[url]">
35
+ // - <meta property="og:image:secure_url" content="[url]">
36
+ // - <meta name="twitter:image" content="[url]">
37
+ // Meta can also be used in schema.org micro-formatting, ie:
38
+ // - <meta itemprop="image" content="[url]">
39
+ //
40
+ // How about preloaded images? - yes, suppose we should replace those
41
+ // - <link rel="prefetch" href="[url]">
42
+ // - <link rel="preload" as="image" href="[url]">
43
+ public static $searchInTags = ['img', 'source', 'input', 'iframe', 'div', 'li', 'link', 'a', 'section'];
44
 
45
  /**
46
  *
47
+ * @return string|null webp url or, if URL should not be changed, return nothing
48
  **/
49
  public function replaceUrl($url)
50
  {
51
  if (!preg_match('#(png|jpe?g)$#', $url)) {
52
+ return null;
53
  }
54
  return $url . '.webp';
55
  }
170
 
171
  //$dom = HtmlDomParser::str_get_html($html, false, false, 'UTF-8', false);
172
  $dom = str_get_html($html, false, false, 'UTF-8', false);
173
+
174
+ // MAX_FILE_SIZE is defined in simple_html_dom.
175
+ // For safety sake, we make sure it is defined before using
176
+ defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
177
+
178
  if ($dom === false) {
179
  if (strlen($html) > MAX_FILE_SIZE) {
180
  return '<!-- Alter HTML was skipped because the HTML is too big to process! ' .
222
  public static function replace($html)
223
  {
224
  if (!function_exists('str_get_html')) {
225
+ require_once __DIR__ . '/../src-vendor/simple_html_dom/simple_html_dom.inc';
226
  }
227
  $iur = new static();
228
  return $iur->replaceHtml($html);
libs/addons/includes/classes/webp/vendor/rosell-dk/dom-util-for-webp/src/PictureTags.php CHANGED
@@ -30,11 +30,11 @@ class PictureTags
30
  /**
31
  * Look for attributes such as "data-lazy-src" and "data-src" and prefer them over "src"
32
  *
33
- * @param $attributes an array of attributes for the element
34
- * @param $attrName ie "src", "srcset" or "sizes"
35
  *
36
- * @return [value:.., attrName:...] (value is the value of the attribute and
37
- * attrName is the name of the attribute used)
38
  *
39
  */
40
  private static function lazyGet($attributes, $attrName)
@@ -90,7 +90,7 @@ class PictureTags
90
  /**
91
  * Makes a string with all attributes.
92
  *
93
- * @param $attribute_array
94
  * @return string
95
  */
96
  private static function createAttributes($attribute_array)
@@ -194,7 +194,7 @@ class PictureTags
194
  public static function replace($html)
195
  {
196
  if (!function_exists('str_get_html')) {
197
- require_once 'simple_html_dom/simple_html_dom.inc';
198
  }
199
  $pt = new static();
200
  return $pt->replaceHtml($html);
30
  /**
31
  * Look for attributes such as "data-lazy-src" and "data-src" and prefer them over "src"
32
  *
33
+ * @param array $attributes an array of attributes for the element
34
+ * @param string $attrName ie "src", "srcset" or "sizes"
35
  *
36
+ * @return array an array with "value" key and "attrName" key. ("value" is the value of the attribute and
37
+ * "attrName" is the name of the attribute used)
38
  *
39
  */
40
  private static function lazyGet($attributes, $attrName)
90
  /**
91
  * Makes a string with all attributes.
92
  *
93
+ * @param array $attribute_array
94
  * @return string
95
  */
96
  private static function createAttributes($attribute_array)
194
  public static function replace($html)
195
  {
196
  if (!function_exists('str_get_html')) {
197
+ require_once __DIR__ . '/../src-vendor/simple_html_dom/simple_html_dom.inc';
198
  }
199
  $pt = new static();
200
  return $pt->replaceHtml($html);
libs/addons/includes/functions.php CHANGED
@@ -6,3 +6,113 @@
6
  * @copyright (c) 19.04.2019, Webcraftic
7
  * @version 1.0
8
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  * @copyright (c) 19.04.2019, Webcraftic
7
  * @version 1.0
8
  */
9
+
10
+ /**
11
+ * Get the path to NextGen galleries on monosites.
12
+ *
13
+ * @since 1.0.4
14
+ * @return string|bool An absolute path. False if it can't be retrieved.
15
+ */
16
+ function wrio_get_ngg_galleries_path() {
17
+ $galleries_path = get_site_option( 'ngg_options' );
18
+
19
+ if ( empty( $galleries_path['gallerypath'] ) ) {
20
+ return false;
21
+ }
22
+
23
+ $galleries_path = wp_normalize_path( $galleries_path['gallerypath'] );
24
+ $galleries_path = trim( $galleries_path, '/' ); // Something like `wp-content/gallery`.
25
+
26
+ $ngg_root = defined( 'NGG_GALLERY_ROOT_TYPE' ) ? NGG_GALLERY_ROOT_TYPE : 'site';
27
+
28
+ if ( $galleries_path && 'content' === $ngg_root ) {
29
+ $ngg_root = wp_normalize_path( WP_CONTENT_DIR );
30
+ $ngg_root = trim( $ngg_root, '/' ); // Something like `abs-path/to/wp-content`.
31
+
32
+ $exploded_root = explode( '/', $ngg_root );
33
+ $exploded_galleries = explode( '/', $galleries_path );
34
+ $first_gallery_dirname = reset( $exploded_galleries );
35
+ $last_root_dirname = end( $exploded_root );
36
+
37
+ if ( $last_root_dirname === $first_gallery_dirname ) {
38
+ array_shift( $exploded_galleries );
39
+ $galleries_path = implode( '/', $exploded_galleries );
40
+ }
41
+ }
42
+
43
+ if ( 'content' === $ngg_root ) {
44
+ $ngg_root = wp_normalize_path( WP_CONTENT_DIR );
45
+ } else {
46
+ $ngg_root = wp_normalize_path( ABSPATH );
47
+ }
48
+
49
+ if ( strpos( $galleries_path, $ngg_root ) !== 0 ) {
50
+ $galleries_path = $ngg_root . $galleries_path;
51
+ }
52
+
53
+ return $galleries_path;
54
+ }
55
+
56
+ /**
57
+ * Get the path to WooCommerce logs on monosites.
58
+ *
59
+ * @since 1.0.4
60
+ * @access public
61
+ * @return string An absolute path.
62
+ */
63
+
64
+ function wrio_get_wc_logs_path() {
65
+ if ( defined( 'WC_LOG_DIR' ) ) {
66
+ return WC_LOG_DIR;
67
+ }
68
+
69
+ $wp_upload_dir = wp_upload_dir();
70
+
71
+ if ( isset( $wp_upload_dir['error'] ) && $wp_upload_dir['error'] !== false ) {
72
+ return null;
73
+ }
74
+
75
+ $wp_upload_dir_path = wp_normalize_path( trailingslashit( $wp_upload_dir['basedir'] ) );
76
+
77
+ return $wp_upload_dir_path . 'wc-logs';
78
+ }
79
+
80
+ /**
81
+ * Get the path to EWWW optimization tools.
82
+ * It is the same for all sites on multisite.
83
+ *
84
+ * @since 1.0.4
85
+ * @return string An absolute path.
86
+ */
87
+ function wrio_get_ewww_tools_path() {
88
+ if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
89
+ return wp_normalize_path( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
90
+ }
91
+
92
+ return trailingslashit( wp_normalize_path( WP_CONTENT_DIR ) ) . 'ewww';
93
+ }
94
+
95
+ /**
96
+ * Get the path to ShortPixel backup folder.
97
+ * It is the same for all sites on multisite (and yes, you'll get a surprise if your upload base dir -aka uploads/sites/12/- is not 2 folders deeper than theuploads folder).
98
+ *
99
+ * @since 1.0.4
100
+ * @access public
101
+ * @return string An absolute path.
102
+ */
103
+
104
+ function wrio_get_shortpixel_path() {
105
+ if ( defined( 'SHORTPIXEL_BACKUP_FOLDER' ) ) {
106
+ return trailingslashit( SHORTPIXEL_BACKUP_FOLDER );
107
+ }
108
+
109
+ $wp_upload_dir = wp_upload_dir();
110
+
111
+ if ( isset( $wp_upload_dir['error'] ) && $wp_upload_dir['error'] !== false ) {
112
+ return null;
113
+ }
114
+
115
+ $wp_upload_dir_path = wp_normalize_path( trailingslashit( $wp_upload_dir['basedir'] ) );
116
+
117
+ return $wp_upload_dir_path . 'ShortpixelBackups';
118
+ }
libs/addons/views/modal-select-custom-folders.php CHANGED
@@ -4,7 +4,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
4
 
5
  /**
6
  * @var array $data
7
- * @var Wbcr_FactoryClearfy208_PageBase $page
8
  */
9
  ?>
10
  <p><?php _e( 'Select a directory for optimization. All nested images and folders will be optimized recursively.', 'robin-image-optimizer' ) ?></p>
4
 
5
  /**
6
  * @var array $data
7
+ * @var Wbcr_FactoryClearfy216_PageBase $page
8
  */
9
  ?>
10
  <p><?php _e( 'Select a directory for optimization. All nested images and folders will be optimized recursively.', 'robin-image-optimizer' ) ?></p>
libs/addons/views/part-bulk-optimization-table-folders.php CHANGED
@@ -4,7 +4,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
4
 
5
  /**
6
  * @var array $data
7
- * @var Wbcr_FactoryClearfy208_PageBase $page
8
  */
9
 
10
  $cf = WRIO_Custom_Folders::get_instance();
4
 
5
  /**
6
  * @var array $data
7
+ * @var Wbcr_FactoryClearfy216_PageBase $page
8
  */
9
 
10
  $cf = WRIO_Custom_Folders::get_instance();
libs/class-rio-relative-to-abs-uri.php ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WRIO\Paths;
4
+
5
+ // Exit if accessed directly
6
+ if ( ! defined( 'ABSPATH' ) ) {
7
+ exit;
8
+ }
9
+
10
+ /**
11
+ * A php library for converting relative urls to absolute.
12
+ * Website: https://github.com/monkeysuffrage/phpuri
13
+ *
14
+ * <pre>
15
+ * echo phpUri::parse('https://www.google.com/')->join('foo');
16
+ * //==> https://www.google.com/foo
17
+ * </pre>
18
+ *
19
+ * Licensed under The MIT License
20
+ * Redistributions of files must retain the above copyright notice.
21
+ *
22
+ * @author P Guardiario <pguardiario@gmail.com>
23
+ * @version 1.0
24
+ */
25
+ class phpUri {
26
+
27
+ /**
28
+ * http(s)://
29
+ *
30
+ * @var string
31
+ */
32
+ public $scheme;
33
+ /**
34
+ * www.example.com
35
+ *
36
+ * @var string
37
+ */
38
+ public $authority;
39
+ /**
40
+ * /search
41
+ *
42
+ * @var string
43
+ */
44
+ public $path;
45
+ /**
46
+ * ?q=foo
47
+ *
48
+ * @var string
49
+ */
50
+ public $query;
51
+ /**
52
+ * #bar
53
+ *
54
+ * @var string
55
+ */
56
+ public $fragment;
57
+
58
+ private function __construct( $string ) {
59
+ preg_match_all( '/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $string, $m );
60
+ $this->scheme = $m[2][0];
61
+ $this->authority = $m[4][0];
62
+ /**
63
+ * CHANGE:
64
+ *
65
+ * @author Dominik Habichtsberg <Dominik.Habichtsberg@Hbg-IT.de>
66
+ * @since 24 Mai 2015 10:02 Uhr
67
+ *
68
+ * Former code: $this->path = ( empty( $m[ 5 ][ 0 ] ) ) ? '/' : $m[ 5 ][ 0 ];
69
+ * No tests failed, when the path is empty.
70
+ * With the former code, the relative urls //g and #s failed
71
+ */
72
+ $this->path = $m[5][0];
73
+ $this->query = $m[7][0];
74
+ $this->fragment = $m[9][0];
75
+ }
76
+
77
+ private function to_str() {
78
+ $ret = '';
79
+ if ( ! empty( $this->scheme ) ) {
80
+ $ret .= "{$this->scheme}:";
81
+ }
82
+ if ( ! empty( $this->authority ) ) {
83
+ $ret .= "//{$this->authority}";
84
+ }
85
+ $ret .= $this->normalize_path( $this->path );
86
+ if ( ! empty( $this->query ) ) {
87
+ $ret .= "?{$this->query}";
88
+ }
89
+ if ( ! empty( $this->fragment ) ) {
90
+ $ret .= "#{$this->fragment}";
91
+ }
92
+
93
+ return $ret;
94
+ }
95
+
96
+ private function normalize_path( $path ) {
97
+ if ( empty( $path ) ) {
98
+ return '';
99
+ }
100
+ $normalized_path = $path;
101
+ $normalized_path = preg_replace( '`//+`', '/', $normalized_path, - 1, $c0 );
102
+ $normalized_path = preg_replace( '`^/\\.\\.?/`', '/', $normalized_path, - 1, $c1 );
103
+ $normalized_path = preg_replace( '`/\\.(/|$)`', '/', $normalized_path, - 1, $c2 );
104
+ /**
105
+ * CHANGE:
106
+ *
107
+ * @author Dominik Habichtsberg <Dominik.Habichtsberg@Hbg-IT.de>
108
+ * @since 24 Mai 2015 10:05 Uhr
109
+ * changed limit form -1 to 1, because climbing up the directory-tree failed
110
+ */
111
+ $normalized_path = preg_replace( '`/[^/]*?/\\.\\.(/|$)`', '/', $normalized_path, 1, $c3 );
112
+ $num_matches = $c0 + $c1 + $c2 + $c3;
113
+
114
+ return ( $num_matches > 0 ) ? $this->normalize_path( $normalized_path ) : $normalized_path;
115
+ }
116
+
117
+ /**
118
+ * Parse an url string
119
+ *
120
+ * @param string $url the url to parse
121
+ *
122
+ * @return phpUri
123
+ */
124
+ public static function parse( $url ) {
125
+ $uri = new phpUri( $url );
126
+ /**
127
+ * CHANGE:
128
+ *
129
+ * @author Dominik Habichtsberg <Dominik.Habichtsberg@Hbg-IT.de>
130
+ * @since 24 Mai 2015 10:25 Uhr
131
+ * The base-url should always have a path
132
+ */
133
+ if ( empty( $uri->path ) ) {
134
+ $uri->path = '/';
135
+ }
136
+
137
+ return $uri;
138
+ }
139
+
140
+ /**
141
+ * Join with a relative url
142
+ *
143
+ * @param string $relative the relative url to join
144
+ *
145
+ * @return string
146
+ */
147
+ public function join( $relative ) {
148
+ $uri = new phpUri( $relative );
149
+ switch ( true ) {
150
+ case ! empty( $uri->scheme ):
151
+ break;
152
+ case ! empty( $uri->authority ):
153
+ break;
154
+ case empty( $uri->path ):
155
+ $uri->path = $this->path;
156
+ if ( empty( $uri->query ) ) {
157
+ $uri->query = $this->query;
158
+ }
159
+ break;
160
+ case strpos( $uri->path, '/' ) === 0:
161
+ break;
162
+ default:
163
+ $base_path = $this->path;
164
+ if ( strpos( $base_path, '/' ) === false ) {
165
+ $base_path = '';
166
+ } else {
167
+ $base_path = preg_replace( '/\/[^\/]+$/', '/', $base_path );
168
+ }
169
+ if ( empty( $base_path ) && empty( $this->authority ) ) {
170
+ $base_path = '/';
171
+ }
172
+ $uri->path = $base_path . $uri->path;
173
+ }
174
+ if ( empty( $uri->scheme ) ) {
175
+ $uri->scheme = $this->scheme;
176
+ if ( empty( $uri->authority ) ) {
177
+ $uri->authority = $this->authority;
178
+ }
179
+ }
180
+
181
+ return $uri->to_str();
182
+ }
183
+ }
libs/factory/adverts/boot.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use WBCR\Factory_Adverts_105\Base;
4
+
5
+ /**
6
+ * Factory Adverts
7
+ *
8
+ * @author Alexander Vitkalov <nechin.va@gmail.com>
9
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
10
+ * @since 1.0.0
11
+ *
12
+ * @package factory-ad-inserter
13
+ * @copyright (c) 2019, Webcraftic Ltd
14
+ *
15
+ * @version 1.2.3
16
+ */
17
+
18
+ // Exit if accessed directly
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ }
22
+
23
+ if ( defined( 'FACTORY_ADVERTS_105_LOADED' ) || ( defined( 'FACTORY_ADVERTS_BLOCK' ) && FACTORY_ADVERTS_BLOCK ) ) {
24
+ return;
25
+ }
26
+
27
+ # Устанавливаем константу, что модуль уже загружен
28
+ define( 'FACTORY_ADVERTS_105_LOADED', true );
29
+
30
+ # Устанавливаем версию модуля
31
+ define( 'FACTORY_ADVERTS_105_VERSION', '1.0.5' );
32
+
33
+ # Регистрируем тектовый домен, для интернализации интерфейса модуля
34
+ load_plugin_textdomain( 'wbcr_factory_adverts_105', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
35
+
36
+ # Устанавливаем директорию модуля
37
+ define( 'FACTORY_ADVERTS_105_DIR', dirname( __FILE__ ) );
38
+
39
+ # Устанавливаем url модуля
40
+ define( 'FACTORY_ADVERTS_105_URL', plugins_url( null, __FILE__ ) );
41
+
42
+ require_once( FACTORY_ADVERTS_105_DIR . '/includes/class-rest-request.php' );
43
+ require_once( FACTORY_ADVERTS_105_DIR . '/includes/class-base.php' );
44
+
45
+ /**
46
+ * @param Wbcr_Factory424_Plugin $plugin
47
+ */
48
+ add_action( 'wbcr_factory_adverts_105_plugin_created', function ( $plugin ) {
49
+ $plugin->set_adverts_manager( "WBCR\Factory_Adverts_105\Base" );
50
+ } );
libs/factory/adverts/includes/class-base.php ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WBCR\Factory_Adverts_105;
4
+
5
+ // Exit if accessed directly
6
+ if ( ! defined( 'ABSPATH' ) ) {
7
+ exit;
8
+ }
9
+
10
+ /**
11
+ * Base class for adverts module.
12
+ *
13
+ * Contains methods for retrieving banner data for a specific position.
14
+ * With this class user cat get advert content for a specific position.
15
+ * This class use functional design pattern.
16
+ *
17
+ * @author Alexander Vitkalov <nechin.va@gmail.com>
18
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
19
+ *
20
+ * @since 1.0.0 Added
21
+ * @package factory-adverts
22
+ * @copyright (c) 2019 Webcraftic Ltd
23
+ */
24
+ class Base {
25
+
26
+ /**
27
+ * Экзепляр плагина с которым взаимодействует этот модуль
28
+ *
29
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
30
+ * @since 1.0.1
31
+ * @var \Wbcr_Factory424_Plugin
32
+ */
33
+ private $plugin;
34
+
35
+ /*
36
+ * Contain array data with the plugin information and the module settings.
37
+ * Mainly used to get the name of the plugin and how to get the adverts blocks.
38
+ *
39
+ * @since 1.0.0 Added
40
+ *
41
+ * @var array Example: array(
42
+ * 'dashboard_widget' => true,
43
+ * 'right_sidebar' => true,
44
+ * 'notice' => true,
45
+ * ...
46
+ * )
47
+ *
48
+ */
49
+ private $settings = [];
50
+
51
+ /**
52
+ * Экземпляр класса для работы API CreativeMotion
53
+ *
54
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
55
+ * @since 1.0.1
56
+ * @var \WBCR\Factory_Adverts_105\Creative_Motion_API
57
+ */
58
+ private $api;
59
+
60
+ /**
61
+ * Сохраняем уже полученные данные, для объектного кеширования
62
+ *
63
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
64
+ * @since 1.0.1
65
+ * @var array
66
+ */
67
+ private $placements = [];
68
+
69
+ /**
70
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
71
+ * @since 1.0.1
72
+ * @var array
73
+ */
74
+ private $errors = [];
75
+
76
+ /**
77
+ * Wbcr_Factory_Adinserter constructor.
78
+ *
79
+ * - Store plugin information and settings.
80
+ * - Add filter and actions.
81
+ * - Include dashboard widget.
82
+ *
83
+ * @since 1.0.0 Added
84
+ *
85
+ * @param \Wbcr_Factory424_Plugin $plugin
86
+ */
87
+ public function __construct( \Wbcr_Factory424_Plugin $plugin, $settings ) {
88
+ $this->plugin = $plugin;
89
+
90
+ $this->settings = wp_parse_args( $settings, [
91
+ 'dashboard_widget' => false, // show dashboard widget (default: false)
92
+ 'right_sidebar' => false, // show adverts sidebar (default: false)
93
+ 'notice' => false, // show notice message (default: false),
94
+ 'business_suggetion' => false,
95
+ 'support' => false
96
+ ] );
97
+
98
+ $this->api = new Creative_Motion_API( $this->plugin );
99
+
100
+ add_filter( 'wbcr/factory/pages/impressive/widgets', [ $this, 'register_plugin_widgets' ], 10, 3 );
101
+ add_action( 'wbcr/factory/admin_notices', [ $this, 'register_plugin_notice' ], 10, 2 );
102
+ add_action( 'current_screen', [ $this, 'register_dashboard_widget' ], 10, 2 );
103
+ }
104
+
105
+ /**
106
+ * Directly get advert content for selected position.
107
+ *
108
+ * @since 1.0.1 Rename method. Content should now be printed.
109
+ * @since 1.0.0 Added
110
+ *
111
+ * @param string $position Custom position name
112
+ *
113
+ * @return void
114
+ */
115
+ public function render_placement( $position = 'right_sidebar' ) {
116
+ $content = '';
117
+
118
+ if ( $position ) {
119
+ $content = $this->get_content( $position );
120
+ }
121
+
122
+ echo $content;
123
+ }
124
+
125
+ /**
126
+ * Register widgets.
127
+ *
128
+ * Depending on the settings, register new widgets.
129
+ *
130
+ * @since 1.0.0 Added
131
+ *
132
+ * @param array $widgets Already existing registered widgets
133
+ * @param string $position Position for the widget
134
+ * @param string $plugin Plugin object for which the hook is run
135
+ *
136
+ * @return array array(
137
+ * 'adverts_widget' => '<p></p>',
138
+ * 'business_suggetion' => '<p></p>',
139
+ * 'support' => '<p></p>',
140
+ * ...
141
+ * )
142
+ */
143
+ public function register_plugin_widgets( $widgets, $position, $plugin ) {
144
+ if ( $plugin->getPluginName() == $this->plugin->getPluginName() && 'right' == $position ) {
145
+
146
+ if ( $this->settings['right_sidebar'] ) {
147
+ $content = $this->get_content( 'right_sidebar' );
148
+ $widgets['adverts_widget'] = $content;
149
+
150
+ if ( empty( $widgets['adverts_widget'] ) ) {
151
+ if ( defined( 'FACTORY_ADVERTS_DEBUG' ) && FACTORY_ADVERTS_DEBUG ) {
152
+ $debug_message = '<div style="background: #fff4f1;padding: 10px;color: #a58074;">';
153
+ $debug_message .= $this->get_debug_message( 'right_sidebar' );
154
+ $debug_message .= '</div>';
155
+
156
+ $widgets['adverts_widget'] = $debug_message;
157
+ } else {
158
+ unset( $widgets['adverts_widget'] );
159
+ }
160
+ }
161
+ }
162
+
163
+ if ( $this->settings['business_suggetion'] ) {
164
+ $content = $this->get_content( 'business_suggetion' );
165
+
166
+ if ( ! empty( $content ) ) {
167
+ $widgets['business_suggetion'] = $content;
168
+ }
169
+ }
170
+
171
+ if ( $this->settings['support'] ) {
172
+ $content = $this->get_content( 'support' );
173
+
174
+ if ( ! empty( $content ) ) {
175
+ $widgets['support'] = $content;
176
+ }
177
+ }
178
+ }
179
+
180
+ return $widgets;
181
+ }
182
+
183
+ /**
184
+ * Регистрирует уведомление для текущего плагина
185
+ *
186
+ * Мы добавляем уведомления в массив всех уведомлений плагина с ключем 'adverts_notice',
187
+ * то есть если другие плагины, тоже добавят свои рекламные уведомления, они просто
188
+ * будут перезаписывать друг друга, в итоге будет отображено только одно рекламное
189
+ * уведомеление. Это нужно для того, чтобы ограничить пользователя от спама.
190
+ *
191
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
192
+ *
193
+ * @since 1.0.1 Переделан полностью под интферфейс фреймворка. Используем встроенную систему уведомлений.
194
+ * @since 1.0.0 Added
195
+ *
196
+ * @param array $notices Массив со списком всех уведомлений, которые будут напечатыны в админ панели
197
+ * @param string $plugin_name Имя плагина, передано для того, чтобы выводить уведомления условно, только для конкретного плагина
198
+ */
199
+ public function register_plugin_notice( $notices, $plugin_name ) {
200
+ if ( $plugin_name !== $this->plugin->getPluginName() ) {
201
+ return $notices;
202
+ }
203
+
204
+ if ( $this->settings['notice'] ) {
205
+ $notice_content = $this->get_content( 'notice' );
206
+
207
+ if ( empty( $notice_content ) ) {
208
+ # Информация для отладки
209
+ if ( defined( 'FACTORY_ADVERTS_DEBUG' ) && FACTORY_ADVERTS_DEBUG ) {
210
+ $debug_message = $this->get_debug_message( 'notice' );
211
+
212
+ $notices['adverts_notice'] = [
213
+ 'id' => 'adverts_debug',
214
+ 'type' => 'error',
215
+ 'dismissible' => false,
216
+ 'dismiss_expires' => 0,
217
+ 'text' => '<p><b>' . $this->plugin->getPluginTitle() . '</b>:<br>' . $debug_message . '</p>'
218
+ ];
219
+ }
220
+
221
+ return $notices;
222
+ }
223
+
224
+ $hash = md5( $notice_content );
225
+
226
+ $notices['adverts_notice'] = [
227
+ 'id' => 'adverts_' . $hash,
228
+ 'type' => 'success',
229
+ 'dismissible' => true,
230
+ 'dismiss_expires' => 0,
231
+ 'text' => '<p><b>' . $this->plugin->getPluginTitle() . '</b>:<br>' . $notice_content . '</p>'
232
+ ];
233
+ }
234
+
235
+ return $notices;
236
+ }
237
+
238
+ /**
239
+ * Include dashboard widget
240
+ *
241
+ * Include functionality the output of the widget on the dashboard.
242
+ * Only one dashboard widget must be shown for some plugins with this setting (dashboard_widget).
243
+ *
244
+ * @since 1.0.0 Added
245
+ */
246
+ public function register_dashboard_widget() {
247
+ if ( $this->settings['dashboard_widget'] && current_user_can( 'manage_options' ) ) {
248
+ $current_screen = get_current_screen();
249
+
250
+ if ( ! in_array( $current_screen->id, [ 'dashboard', 'dashboard-network' ] ) ) {
251
+ return;
252
+ }
253
+
254
+ $content = $this->get_content( 'dashboard_widget' );
255
+
256
+ if ( empty( $content ) && defined( 'FACTORY_ADVERTS_DEBUG' ) && FACTORY_ADVERTS_DEBUG ) {
257
+ $content = $this->get_debug_message( 'dashboard_widget' );
258
+ }
259
+
260
+ require_once FACTORY_ADVERTS_105_DIR . '/includes/class-dashboard-widget.php';
261
+ new Dashboard_Widget( $this->plugin, $content );
262
+ }
263
+ }
264
+
265
+ /**
266
+ * Позволяет получить сообщение об ошибках
267
+ *
268
+ * Метод проверяет последние ошибки, которые могли произойти в результате api запроса.
269
+ * Если ошибки есть, он выводит предупреждение и список последних ошибок. Если ошибок нет,
270
+ * метод вернет просто предупреждение, что реклама не настроена.
271
+ *
272
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
273
+ * @since 1.0.1
274
+ *
275
+ * @param string $position Position for the widget
276
+ *
277
+ * @return string Возвращает сообщение с последниеми ошибками для отладки
278
+ */
279
+ private function get_debug_message( $position ) {
280
+ $debug_massage = 'Plugin ads not configured or server unavailable. See full error report below.<br>';
281
+
282
+ if ( isset( $this->errors[ $position ] ) && ! empty( $this->errors ) ) {
283
+ $debug_massage .= '<b>Last errors:</b><br>';
284
+ foreach ( $this->errors[ $position ] as $error_code => $error_message ) {
285
+ $debug_massage .= 'Code: ' . $error_code . ' Error: ' . $error_message . '<br>';
286
+ }
287
+ }
288
+
289
+ return $debug_massage;
290
+ }
291
+
292
+ /**
293
+ * Get advert content for selected position.
294
+ *
295
+ * @since 1.0.1 Полностью переписан
296
+ * @since 1.0.0 Added
297
+ *
298
+ * @param string $position The position for advert
299
+ *
300
+ * @return string
301
+ */
302
+ private function get_content( $position ) {
303
+ if ( isset( $this->placements[ $position ] ) ) {
304
+ return $this->placements[ $position ];
305
+ }
306
+
307
+ $content = $this->api->get_content( $position );
308
+
309
+ if ( is_wp_error( $content ) ) {
310
+ $this->errors[ $position ][ $content->get_error_code() ] = $content->get_error_message();
311
+
312
+ return null;
313
+ }
314
+
315
+ $this->placements[ $position ] = $content;
316
+
317
+ return $content;
318
+ }
319
+ }
libs/factory/adverts/includes/class-dashboard-widget.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WBCR\Factory_Adverts_105;
4
+
5
+ // Exit if accessed directly
6
+ if ( ! defined( 'ABSPATH' ) ) {
7
+ exit;
8
+ }
9
+
10
+ /**
11
+ * Adverts Dashboard Widget.
12
+ *
13
+ * Adds a widget with a banner or a list of news.
14
+ *
15
+ * @author Alexander Vitkalov <nechin.va@gmail.com>
16
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
17
+ *
18
+ * @since 1.0.0 Added
19
+ * @package factory-adverts
20
+ * @copyright (c) 2019 Webcraftic Ltd
21
+ */
22
+ class Dashboard_Widget {
23
+
24
+ /**
25
+ * Контент, который должен быть напечатан внутри дашбоард виджета
26
+ *
27
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
28
+ * @since 1.0.1
29
+ * @var string
30
+ */
31
+ private $content;
32
+
33
+ /**
34
+ * Экзепляр плагина с которым взаимодействует этот модуль
35
+ *
36
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
37
+ * @since 1.0.1
38
+ * @var \Wbcr_Factory424_Plugin
39
+ */
40
+ private $plugin;
41
+
42
+ /**
43
+ * Dashboard_Widget constructor.
44
+ *
45
+ * Call parent constructor. Registration hooks.
46
+ *
47
+ * @since 1.0.0 Added
48
+ *
49
+ * @param \Wbcr_Factory424_Plugin $plugin
50
+ * @param string $content
51
+ */
52
+ public function __construct( \Wbcr_Factory424_Plugin $plugin, $content ) {
53
+
54
+ $this->plugin = $plugin;
55
+ $this->content = $content;
56
+
57
+ if ( ! empty( $this->content ) ) {
58
+ if ( $this->plugin->isNetworkActive() && $this->plugin->isNetworkAdmin() ) {
59
+ add_action( 'wp_network_dashboard_setup', [ $this, 'add_dashboard_widgets' ], 999 );
60
+
61
+ return;
62
+ }
63
+
64
+ add_action( 'wp_dashboard_setup', [ $this, 'add_dashboard_widgets' ], 999 );
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Add the News widget to the dashboard.
70
+ *
71
+ * @since 1.0.0 Added
72
+ */
73
+ public function add_dashboard_widgets() {
74
+ $widget_id = 'wbcr-factory-adverts-widget';
75
+
76
+ wp_add_dashboard_widget( $widget_id, $this->plugin->getPluginTitle() . ' News', [
77
+ $this,
78
+ 'print_widget_content'
79
+ ] );
80
+
81
+ $this->sort_dashboard_widgets( $widget_id );
82
+ }
83
+
84
+ /**
85
+ * Create the function to output the contents of the Dashboard Widget.
86
+ *
87
+ * @since 1.0.0 Added
88
+ */
89
+ public function print_widget_content() {
90
+ ?>
91
+ <div class="wordpress-news hide-if-no-js">
92
+ <div class="rss-widget">
93
+ <?php echo $this->content; ?>
94
+ </div>
95
+ </div>
96
+ <?php
97
+
98
+ }
99
+
100
+ /**
101
+ * Сортируем виджеты на странице дашбоард
102
+ *
103
+ * Виджеты должны быть в таком порядке, чтобы наш виджет был выше всех.
104
+ *
105
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
106
+ * @author Alexander Vitkalov <nechin.va@gmail.com>
107
+ *
108
+ * @since 1.0.2 Добавлена поддержка мультисайтов
109
+ * @since 1.0.0 Добавлен
110
+ *
111
+ * @param string $widget_id ID нашего виджета
112
+ */
113
+ private function sort_dashboard_widgets( $widget_id ) {
114
+ global $wp_meta_boxes;
115
+
116
+ $location = $this->plugin->isNetworkAdmin() ? 'dashboard-network' : 'dashboard';
117
+
118
+ $normal_core = $wp_meta_boxes[ $location ]['normal']['core'];
119
+ $widget_backup = [ $widget_id => $normal_core[ $widget_id ] ];
120
+ unset( $normal_core[ $widget_id ] );
121
+ $sorted_core = array_merge( $widget_backup, $normal_core );
122
+
123
+ $wp_meta_boxes['dashboard']['normal']['core'] = $sorted_core;
124
+ }
125
+ }
libs/factory/adverts/includes/class-rest-request.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WBCR\Factory_Adverts_105;
4
+
5
+ // Exit if accessed directly
6
+ if ( ! defined( 'ABSPATH' ) ) {
7
+ exit;
8
+ }
9
+
10
+ /**
11
+ * Factory request class.
12
+ *
13
+ * Performs a server request, retrieves banner data and stores it in the cache.
14
+ *
15
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
16
+ * @author Alexander Vitkalov <nechin.va@gmail.com>
17
+ *
18
+ * @since 1.0.1 Изменил имя класса и доработал его.
19
+ * @since 1.0.0 Added
20
+ *
21
+ * @package factory-adverts
22
+ * @copyright (c) 2019 Webcraftic Ltd
23
+ */
24
+ class Creative_Motion_API {
25
+
26
+ /**
27
+ * Rest request url.
28
+ *
29
+ * Define rest request url for rest request to remote server.
30
+ *
31
+ * @since 1.2.1
32
+ */
33
+ const SERVER_URL = 'https://api.cm-wp.com';
34
+
35
+ /**
36
+ * Rest route path.
37
+ *
38
+ * Define rest route path for rest request.
39
+ *
40
+ * @since 1.0.0
41
+ */
42
+ const REST_ROUTE = '/adverds/v1/advt';
43
+
44
+ /**
45
+ * Интервал между запросами по умолчанию
46
+ *
47
+ * Значение в часах.
48
+ *
49
+ * @since 1.0.1
50
+ */
51
+ const DEFAULT_REQUESTS_INTERVAL = 24;
52
+
53
+ /**
54
+ * Интервал между запросами, если сервер недоступен
55
+ *
56
+ * Значение в часах.
57
+ *
58
+ * @since 1.0.1
59
+ */
60
+ const SERVER_UNAVAILABLE_INTERVAL = 4;
61
+
62
+
63
+ /**
64
+ * Экзепляр плагина с которым взаимодействует этот модуль
65
+ *
66
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
67
+ * @since 1.0.1
68
+ * @var \Wbcr_Factory424_Plugin
69
+ */
70
+ private $plugin;
71
+
72
+
73
+ /**
74
+ * Request constructor.
75
+ *
76
+ * Variable initialization.
77
+ *
78
+ * @since 1.0.0 Added
79
+ *
80
+ * @param \Wbcr_Factory424_Plugin $plugin_name
81
+ */
82
+ public function __construct( \Wbcr_Factory424_Plugin $plugin ) {
83
+ $this->plugin = $plugin;
84
+ }
85
+
86
+ /**
87
+ * Get adverts content.
88
+ *
89
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
90
+ * @since 1.0.1
91
+ *
92
+ * @param $position
93
+ *
94
+ * @return string|\WP_Error
95
+ */
96
+ public function get_content( $position ) {
97
+ $data = $this->get_cache( $position );
98
+
99
+ if ( is_wp_error( $data ) ) {
100
+ return $data;
101
+ }
102
+
103
+ return strip_tags( $data['content'], '<b>,<a>,<i>,<strong>,<img>,<ul>,<ol>,<li>' );
104
+ }
105
+
106
+ /**
107
+ * Get data from cache.
108
+ *
109
+ * If data in the cache, not empty and not expired, then get data from cache. Or get data from server.
110
+ *
111
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
112
+ *
113
+ * @since 1.0.1 Полностью переписан, с перехватом api ошибок
114
+ * @since 1.0.0 Added
115
+ *
116
+ * @return mixed array(
117
+ * 'plugin' => 'wbcr_insert_php',
118
+ * 'content' => '<p></p>',
119
+ * 'expires' => 1563542199,
120
+ * );
121
+ */
122
+ private function get_cache( $position ) {
123
+
124
+ if ( defined( 'FACTORY_ADVERTS_DEBUG' ) && FACTORY_ADVERTS_DEBUG ) {
125
+ return $this->do_api_request( $position );
126
+ }
127
+
128
+ $key = $this->plugin->getPrefix() . md5( $position . 'advert_transient_' );
129
+
130
+ $cached = get_transient( $key );
131
+
132
+ if ( $cached !== false ) {
133
+ if ( isset( $cached['error_code'] ) && isset( $cached['error'] ) ) {
134
+ return new \WP_Error( $cached['error_code'], $cached['error'] );
135
+ }
136
+
137
+ return $cached;
138
+ }
139
+
140
+ $data = $this->do_api_request( $position );
141
+
142
+ if ( is_wp_error( $data ) ) {
143
+ set_transient( $key, [
144
+ 'error' => $data->get_error_message(),
145
+ 'error_code' => $data->get_error_code()
146
+ ], self::SERVER_UNAVAILABLE_INTERVAL * HOUR_IN_SECONDS );
147
+
148
+ return $data;
149
+ }
150
+
151
+ set_transient( $key, $data, $data['expires'] );
152
+
153
+ return $data;
154
+ }
155
+
156
+ /**
157
+ * Performs rest api request.
158
+ *
159
+ * In some case on the server (Apache) in the .htaccess must be set
160
+ * RewriteRule ^wp-json/(.*)[?](.*) /?rest_route=/$1&$2 [L]
161
+ *
162
+ * @since 1.0.1 Добавлен перехват ошибок, рефакторинг кода.
163
+ * @since 1.0.0 Added
164
+ *
165
+ * @return mixed array(
166
+ * 'plugin' => 'wbcr_insert_php',
167
+ * 'content' => '<p></p>',
168
+ * 'expires' => 1563542199,
169
+ * );
170
+ */
171
+ private function do_api_request( $position ) {
172
+ $default_result = [
173
+ 'content' => '',
174
+ 'expires' => self::DEFAULT_REQUESTS_INTERVAL * HOUR_IN_SECONDS,
175
+ ];
176
+
177
+ $url = untrailingslashit( self::SERVER_URL ) . '/wp-json' . self::REST_ROUTE;
178
+ $url = add_query_arg( [ 'plugin' => $this->plugin->getPluginName(), 'position' => $position ], $url );
179
+
180
+ $response = wp_remote_get( $url );
181
+
182
+ $code = wp_remote_retrieve_response_code( $response );
183
+ $body = wp_remote_retrieve_body( $response );
184
+
185
+ $data = @json_decode( $body, true );
186
+
187
+ if ( is_wp_error( $response ) ) {
188
+ return $response;
189
+ }
190
+
191
+ if ( 200 !== $code ) {
192
+ return new \WP_Error( 'http_request_error', 'Failed request to the remote server. Code: ' . $code );
193
+ }
194
+
195
+ return wp_parse_args( $data, $default_result );
196
+ }
197
+ }
libs/factory/adverts/includes/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/adverts/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/{core/langs/wbcr_factory_412-ru_RU.mo → adverts/langs/wbcr_factory_adverts_105-ru_RU.mo} RENAMED
File without changes
libs/factory/adverts/langs/wbcr_factory_adverts_105-ru_RU.po ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: factory_forms\n"
4
+ "POT-Creation-Date: 2018-10-16 22:44+0300\n"
5
+ "PO-Revision-Date: 2018-10-16 22:45+0300\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
8
+ "Language: ru_RU\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 2.1.1\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+
20
+ #: includes/check-compatibility.php:80
21
+ msgid "warning"
22
+ msgstr "предупреждение"
23
+
24
+ #: includes/check-compatibility.php:82
25
+ #, php-format
26
+ msgid "The %s plugin has stopped."
27
+ msgstr "Работа плагина %s была остановлена."
28
+
29
+ #: includes/check-compatibility.php:83
30
+ msgid "Possible reasons:"
31
+ msgstr "Возможные причины:"
32
+
33
+ #: includes/check-compatibility.php:89
34
+ #, php-format
35
+ msgid "You need to update the PHP version to %s or higher!"
36
+ msgstr "Вам нужно обновить версию PHP до %s или выше!"
37
+
38
+ #: includes/check-compatibility.php:94
39
+ #, php-format
40
+ msgid "You need to update WordPress to %s or higher!"
41
+ msgstr "Вам нужно обновить WordPress до %s или выше!"
42
+
43
+ #: includes/functions.php:132
44
+ #, php-format
45
+ msgid ""
46
+ "%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead."
47
+ msgstr ""
48
+ "%1$s является <strong>устаревшим,</strong> начиная с версии %2$s в "
49
+ "Wordpress! Используйте %3$s."
50
+
51
+ #: includes/functions.php:134
52
+ #, php-format
53
+ msgid ""
54
+ "%1$s is <strong>deprecated</strong> since version %2$s with no alternative "
55
+ "available."
56
+ msgstr ""
57
+ "%1$s был вызван с параметром, который является <strong>устаревшими</strong> "
58
+ "начиная с версии %2$s , в настоящее время доступных альтернатив нет."
59
+
60
+ #: includes/plugin.class.php:202 includes/plugin.class.php:237
61
+ msgid ""
62
+ "You are trying to call this earlier than the plugin menu will be registered."
63
+ msgstr ""
64
+ "Вы пытаетесь вызвать это раньше, чем будет зарегистрировано меню плагина."
65
+
66
+ #: includes/plugin.class.php:220
67
+ msgid ""
68
+ "You are trying to get a link to a page that does not have multisite mode. "
69
+ "Clicking this link will lead the user to a non-existent page."
70
+ msgstr ""
71
+ "Вы пытаетесь получить ссылку на страницу, которая не имеет "
72
+ "многопользовательского режима. Щелчок по этой ссылке приведет пользователя "
73
+ "к несуществующей странице."
74
+
75
+ #: includes/plugin.class.php:222
76
+ msgid ""
77
+ "Trying to get a link to an unregistered page. You are trying to call this "
78
+ "earlier than the plugin menu will be registered."
79
+ msgstr ""
80
+ "Попытка получить ссылку на незарегистрированную страницу. Вы пытаетесь "
81
+ "вызвать это раньше, чем будет зарегистрировано меню плагина."
82
+
83
+
libs/factory/bootstrap/assets/css-min/bootstrap.accordion.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .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-412 .factory-accordion>h3{border-bottom:1px solid #DDD;cursor:pointer;padding:8px 15px;margin:0}.factory-bootstrap-412 .factory-accordion>div{display:none;margin:0;border-bottom:1px solid #DDD}.factory-bootstrap-412 .factory-accordion-item{display:none}.factory-bootstrap-412 .inner-factory-accordion-item{padding:10px 0}.factory-bootstrap-412 .factory-accordion>h3.active:hover{cursor:default}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .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-425 .factory-accordion>h3{border-bottom:1px solid #DDD;cursor:pointer;padding:8px 15px;margin:0}.factory-bootstrap-425 .factory-accordion>div{display:none;margin:0;border-bottom:1px solid #DDD}.factory-bootstrap-425 .factory-accordion-item{display:none}.factory-bootstrap-425 .inner-factory-accordion-item{padding:10px 0}.factory-bootstrap-425 .factory-accordion>h3.active:hover{cursor:default}
libs/factory/bootstrap/assets/css-min/bootstrap.blue.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .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-412 .btn-primary:focus,.factory-bootstrap-412 .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-412 .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-412 .btn-primary:disabled,.factory-bootstrap-412 .btn-primary[disabled]{color:#d1cdc7!important;background:#db9825!important;border-color:#bd831f!important;text-shadow:none!important}.factory-bootstrap-412 .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-412 .pagination>.active>a,.factory-bootstrap-412 .pagination>.active>a:focus,.factory-bootstrap-412 .pagination>.active>a:hover,.factory-bootstrap-412 .pagination>.active>span,.factory-bootstrap-412 .pagination>.active>span:focus,.factory-bootstrap-412 .pagination>.active>span:hover{background-color:#e1a948;border-color:#d39323}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .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-425 .btn-primary:focus,.factory-bootstrap-425 .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-425 .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-425 .btn-primary:disabled,.factory-bootstrap-425 .btn-primary[disabled]{color:#d1cdc7!important;background:#db9825!important;border-color:#bd831f!important;text-shadow:none!important}.factory-bootstrap-425 .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-425 .pagination>.active>a,.factory-bootstrap-425 .pagination>.active>a:focus,.factory-bootstrap-425 .pagination>.active>a:hover,.factory-bootstrap-425 .pagination>.active>span,.factory-bootstrap-425 .pagination>.active>span:focus,.factory-bootstrap-425 .pagination>.active>span:hover{background-color:#e1a948;border-color:#d39323}
libs/factory/bootstrap/assets/css-min/bootstrap.coffee.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .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-412 .btn-primary:focus,.factory-bootstrap-412 .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-412 .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-412 .btn-primary:disabled,.factory-bootstrap-412 .btn-primary[disabled]{color:#d1cbc7!important;background:#ba906d!important;border-color:#ae7d55!important;text-shadow:none!important}.factory-bootstrap-412 .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-412 .pagination>.active>a,.factory-bootstrap-412 .pagination>.active>a:focus,.factory-bootstrap-412 .pagination>.active>a:hover,.factory-bootstrap-412 .pagination>.active>span,.factory-bootstrap-412 .pagination>.active>span:focus,.factory-bootstrap-412 .pagination>.active>span:hover{background-color:#c7a589;border-color:#b78a66}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .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-425 .btn-primary:focus,.factory-bootstrap-425 .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-425 .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-425 .btn-primary:disabled,.factory-bootstrap-425 .btn-primary[disabled]{color:#d1cbc7!important;background:#ba906d!important;border-color:#ae7d55!important;text-shadow:none!important}.factory-bootstrap-425 .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-425 .pagination>.active>a,.factory-bootstrap-425 .pagination>.active>a:focus,.factory-bootstrap-425 .pagination>.active>a:hover,.factory-bootstrap-425 .pagination>.active>span,.factory-bootstrap-425 .pagination>.active>span:focus,.factory-bootstrap-425 .pagination>.active>span:hover{background-color:#c7a589;border-color:#b78a66}
libs/factory/bootstrap/assets/css-min/bootstrap.core.min.css CHANGED
@@ -8,7 +8,7 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 article,.factory-bootstrap-412 aside,.factory-bootstrap-412 details,.factory-bootstrap-412 figcaption,.factory-bootstrap-412 figure,.factory-bootstrap-412 footer,.factory-bootstrap-412 header,.factory-bootstrap-412 hgroup,.factory-bootstrap-412 main,.factory-bootstrap-412 nav,.factory-bootstrap-412 section,.factory-bootstrap-412 summary{display:block}.factory-bootstrap-412 audio,.factory-bootstrap-412 canvas,.factory-bootstrap-412 video{display:inline-block}.factory-bootstrap-412 audio:not([controls]){display:none;height:0}.factory-bootstrap-412 [hidden],.factory-bootstrap-412 template{display:none}.factory-bootstrap-412 body{margin:0}.factory-bootstrap-412 a{background:0 0}.factory-bootstrap-412 a:focus{outline:thin dotted}.factory-bootstrap-412 a:active,.factory-bootstrap-412 a:hover{outline:0}.factory-bootstrap-412 h1{margin:.67em 0}.factory-bootstrap-412 b,.factory-bootstrap-412 strong{font-weight:700}.factory-bootstrap-412 dfn{font-style:italic}.factory-bootstrap-412 hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}.factory-bootstrap-412 mark{color:#000;background:#ff0}.factory-bootstrap-412 code,.factory-bootstrap-412 kbd,.factory-bootstrap-412 pre,.factory-bootstrap-412 samp{font-size:1em}.factory-bootstrap-412 pre{white-space:pre-wrap}.factory-bootstrap-412 q{quotes:"\201C" "\201D" "\2018" "\2019"}.factory-bootstrap-412 sub,.factory-bootstrap-412 sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}.factory-bootstrap-412 sup{top:-.5em}.factory-bootstrap-412 sub{bottom:-.25em}.factory-bootstrap-412 img{border:0}.factory-bootstrap-412 svg:not(:root){overflow:hidden}.factory-bootstrap-412 figure{margin:0}.factory-bootstrap-412 button,.factory-bootstrap-412 input,.factory-bootstrap-412 select,.factory-bootstrap-412 textarea{margin:0}.factory-bootstrap-412 button,.factory-bootstrap-412 select{text-transform:none}.factory-bootstrap-412 select{padding-right:4px!important}.factory-bootstrap-412 button,.factory-bootstrap-412 input[type=reset],.factory-bootstrap-412 input[type=submit],html .factory-bootstrap-412 input[type=button]{cursor:pointer;-webkit-appearance:button}.factory-bootstrap-412 button[disabled],html .factory-bootstrap-412 input[disabled]{cursor:default}.factory-bootstrap-412 input[type=checkbox],.factory-bootstrap-412 input[type=radio]{padding:0;box-sizing:border-box}.factory-bootstrap-412 input[type=search]{-webkit-appearance:textfield}.factory-bootstrap-412 input[type=search]::-webkit-search-cancel-button,.factory-bootstrap-412 input[type=search]::-webkit-search-decoration{-webkit-appearance:none}.factory-bootstrap-412 button::-moz-focus-inner,.factory-bootstrap-412 input::-moz-focus-inner{padding:0;border:0}.factory-bootstrap-412 textarea{overflow:auto;vertical-align:top}.factory-bootstrap-412 table{border-collapse:collapse;border-spacing:0}@media print{.factory-bootstrap-412 *{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}.factory-bootstrap-412 a,.factory-bootstrap-412 a:visited{text-decoration:underline}.factory-bootstrap-412 a[href]:after{content:" (" attr(href) ")"}.factory-bootstrap-412 abbr[title]:after{content:" (" attr(title) ")"}.factory-bootstrap-412 a[href^="javascript:"]:after,.factory-bootstrap-412 a[href^="#"]:after{content:""}.factory-bootstrap-412 blockquote,.factory-bootstrap-412 pre{border:1px solid #999;page-break-inside:avoid}.factory-bootstrap-412 thead{display:table-header-group}.factory-bootstrap-412 img,.factory-bootstrap-412 tr{page-break-inside:avoid}.factory-bootstrap-412 img{max-width:100%!important}@page{margin:2cm .5cm}.factory-bootstrap-412 h2,.factory-bootstrap-412 h3,.factory-bootstrap-412 p{orphans:3;widows:3}.factory-bootstrap-412 h2,.factory-bootstrap-412 h3{page-break-after:avoid}.factory-bootstrap-412 select{background:#fff!important}.factory-bootstrap-412 .navbar{display:none}.factory-bootstrap-412 .table td,.factory-bootstrap-412 .table th{background-color:#fff!important}.factory-bootstrap-412 .btn>.caret,.factory-bootstrap-412 .dropup>.btn>.caret{border-top-color:#000!important}.factory-bootstrap-412 .label{border:1px solid #000}.factory-bootstrap-412 .table{border-collapse:collapse!important}.factory-bootstrap-412 .table-bordered td,.factory-bootstrap-412 .table-bordered th{border:1px solid #ddd!important}}.factory-bootstrap-412 *,.factory-bootstrap-412 :after,.factory-bootstrap-412 :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html .factory-bootstrap-412{-webkit-tap-highlight-color:rgba(0,0,0,0)}.factory-bootstrap-412 body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}.factory-bootstrap-412 button,.factory-bootstrap-412 input,.factory-bootstrap-412 select,.factory-bootstrap-412 textarea{font-family:inherit;font-size:inherit;line-height:inherit}.factory-bootstrap-412 img{vertical-align:middle}.factory-bootstrap-412 .img-responsive{display:block;height:auto;max-width:100%}.factory-bootstrap-412 .img-rounded{border-radius:6px}.factory-bootstrap-412 .img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.factory-bootstrap-412 .img-circle{border-radius:50%}.factory-bootstrap-412 hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.factory-bootstrap-412 .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.factory-bootstrap-412 .h1,.factory-bootstrap-412 .h2,.factory-bootstrap-412 .h3,.factory-bootstrap-412 .h4,.factory-bootstrap-412 .h5,.factory-bootstrap-412 .h6,.factory-bootstrap-412 h1,.factory-bootstrap-412 h2,.factory-bootstrap-412 h3,.factory-bootstrap-412 h4,.factory-bootstrap-412 h5,.factory-bootstrap-412 h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit}.factory-bootstrap-412 .h1 .small,.factory-bootstrap-412 .h1 small,.factory-bootstrap-412 .h2 .small,.factory-bootstrap-412 .h2 small,.factory-bootstrap-412 .h3 .small,.factory-bootstrap-412 .h3 small,.factory-bootstrap-412 .h4 .small,.factory-bootstrap-412 .h4 small,.factory-bootstrap-412 .h5 .small,.factory-bootstrap-412 .h5 small,.factory-bootstrap-412 .h6 .small,.factory-bootstrap-412 .h6 small,.factory-bootstrap-412 h1 .small,.factory-bootstrap-412 h1 small,.factory-bootstrap-412 h2 .small,.factory-bootstrap-412 h2 small,.factory-bootstrap-412 h3 .small,.factory-bootstrap-412 h3 small,.factory-bootstrap-412 h4 .small,.factory-bootstrap-412 h4 small,.factory-bootstrap-412 h5 .small,.factory-bootstrap-412 h5 small,.factory-bootstrap-412 h6 .small,.factory-bootstrap-412 h6 small{font-weight:400;line-height:1;color:#999}.factory-bootstrap-412 h1,.factory-bootstrap-412 h2,.factory-bootstrap-412 h3{margin-top:20px;margin-bottom:10px}.factory-bootstrap-412 h1 .small,.factory-bootstrap-412 h1 small,.factory-bootstrap-412 h2 .small,.factory-bootstrap-412 h2 small,.factory-bootstrap-412 h3 .small,.factory-bootstrap-412 h3 small{font-size:65%}.factory-bootstrap-412 h4,.factory-bootstrap-412 h5,.factory-bootstrap-412 h6{margin-top:10px;margin-bottom:10px}.factory-bootstrap-412 h4 .small,.factory-bootstrap-412 h4 small,.factory-bootstrap-412 h5 .small,.factory-bootstrap-412 h5 small,.factory-bootstrap-412 h6 .small,.factory-bootstrap-412 h6 small{font-size:75%}.factory-bootstrap-412 .h1,.factory-bootstrap-412 h1{font-size:36px}.factory-bootstrap-412 .h2,.factory-bootstrap-412 h2{font-size:30px}.factory-bootstrap-412 .h3,.factory-bootstrap-412 h3{font-size:24px}.factory-bootstrap-412 .h4,.factory-bootstrap-412 h4{font-size:18px}.factory-bootstrap-412 .h5,.factory-bootstrap-412 h5{font-size:14px}.factory-bootstrap-412 .h6,.factory-bootstrap-412 h6{font-size:12px}.factory-bootstrap-412 p{margin:0 0 10px}.factory-bootstrap-412 .lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.factory-bootstrap-412 .small,.factory-bootstrap-412 small{font-size:85%}.factory-bootstrap-412 cite{font-style:normal}.factory-bootstrap-412 .text-muted{color:#999}.factory-bootstrap-412 .text-primary{color:#428bca}.factory-bootstrap-412 .text-primary:hover{color:#3071a9}.factory-bootstrap-412 .text-warning{color:#8a6d3b}.factory-bootstrap-412 .text-warning:hover{color:#66512c}.factory-bootstrap-412 .text-danger{color:#a94442}.factory-bootstrap-412 .text-danger:hover{color:#843534}.factory-bootstrap-412 .text-success{color:#3c763d}.factory-bootstrap-412 .text-success:hover{color:#2b542c}.factory-bootstrap-412 .text-info{color:#31708f}.factory-bootstrap-412 .text-info:hover{color:#245269}.factory-bootstrap-412 .text-left{text-align:left}.factory-bootstrap-412 .text-right{text-align:right}.factory-bootstrap-412 .text-center{text-align:center}.factory-bootstrap-412 .page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}.factory-bootstrap-412 ol,.factory-bootstrap-412 ul{margin-top:0;margin-bottom:10px}.factory-bootstrap-412 ol ol,.factory-bootstrap-412 ol ul,.factory-bootstrap-412 ul ol,.factory-bootstrap-412 ul ul{margin-bottom:0}.factory-bootstrap-412 .list-inline,.factory-bootstrap-412 .list-unstyled{padding-left:0;list-style:none}.factory-bootstrap-412 .list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.factory-bootstrap-412 .list-inline>li:first-child{padding-left:0}.factory-bootstrap-412 dl{margin-top:0;margin-bottom:20px}.factory-bootstrap-412 dd,.factory-bootstrap-412 dt{line-height:1.428571429}.factory-bootstrap-412 dt{font-weight:700}.factory-bootstrap-412 dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:after,.dl-horizontal dd:before{display:table;content:" "}.dl-horizontal dd:after{clear:both}}.factory-bootstrap-412 abbr[data-original-title],.factory-bootstrap-412 abbr[title]{cursor:help;border-bottom:1px dotted #999}.factory-bootstrap-412 .initialism{font-size:90%;text-transform:uppercase}.factory-bootstrap-412 blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}.factory-bootstrap-412 blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}.factory-bootstrap-412 blockquote p:last-child{margin-bottom:0}.factory-bootstrap-412 blockquote .small,.factory-bootstrap-412 blockquote small{display:block;line-height:1.428571429;color:#999}.factory-bootstrap-412 blockquote .small:before,.factory-bootstrap-412 blockquote small:before{content:'\2014 \00A0'}.factory-bootstrap-412 blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}.factory-bootstrap-412 blockquote.pull-right .small,.factory-bootstrap-412 blockquote.pull-right p,.factory-bootstrap-412 blockquote.pull-right small{text-align:right}.factory-bootstrap-412 blockquote.pull-right .small:before,.factory-bootstrap-412 blockquote.pull-right small:before{content:''}.factory-bootstrap-412 blockquote.pull-right .small:after,.factory-bootstrap-412 blockquote.pull-right small:after{content:'\00A0 \2014'}.factory-bootstrap-412 blockquote:after,.factory-bootstrap-412 blockquote:before{content:""}.factory-bootstrap-412 address{margin-bottom:20px;font-style:normal;line-height:1.428571429}.factory-bootstrap-412 code,.factory-bootstrap-412 kbd,.factory-bootstrap-412 pre,.factory-bootstrap-412 samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}.factory-bootstrap-412 code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}.factory-bootstrap-412 pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}.factory-bootstrap-412 pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.factory-bootstrap-412 .pre-scrollable{max-height:340px;overflow-y:scroll}.factory-bootstrap-412 .container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.factory-bootstrap-412 .container:after,.factory-bootstrap-412 .container:before{display:table;content:" "}.factory-bootstrap-412 .container:after{clear:both}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.factory-bootstrap-412 .row{margin-right:-15px;margin-left:-15px}.factory-bootstrap-412 .row:after,.factory-bootstrap-412 .row:before{display:table;content:" "}.factory-bootstrap-412 .row:after{clear:both}.factory-bootstrap-412 .col-lg-1,.factory-bootstrap-412 .col-lg-10,.factory-bootstrap-412 .col-lg-11,.factory-bootstrap-412 .col-lg-12,.factory-bootstrap-412 .col-lg-2,.factory-bootstrap-412 .col-lg-3,.factory-bootstrap-412 .col-lg-4,.factory-bootstrap-412 .col-lg-5,.factory-bootstrap-412 .col-lg-6,.factory-bootstrap-412 .col-lg-7,.factory-bootstrap-412 .col-lg-8,.factory-bootstrap-412 .col-lg-9,.factory-bootstrap-412 .col-md-1,.factory-bootstrap-412 .col-md-10,.factory-bootstrap-412 .col-md-11,.factory-bootstrap-412 .col-md-12,.factory-bootstrap-412 .col-md-2,.factory-bootstrap-412 .col-md-3,.factory-bootstrap-412 .col-md-4,.factory-bootstrap-412 .col-md-5,.factory-bootstrap-412 .col-md-6,.factory-bootstrap-412 .col-md-7,.factory-bootstrap-412 .col-md-8,.factory-bootstrap-412 .col-md-9,.factory-bootstrap-412 .col-sm-1,.factory-bootstrap-412 .col-sm-10,.factory-bootstrap-412 .col-sm-11,.factory-bootstrap-412 .col-sm-12,.factory-bootstrap-412 .col-sm-2,.factory-bootstrap-412 .col-sm-3,.factory-bootstrap-412 .col-sm-4,.factory-bootstrap-412 .col-sm-5,.factory-bootstrap-412 .col-sm-6,.factory-bootstrap-412 .col-sm-7,.factory-bootstrap-412 .col-sm-8,.factory-bootstrap-412 .col-sm-9,.factory-bootstrap-412 .col-xs-1,.factory-bootstrap-412 .col-xs-10,.factory-bootstrap-412 .col-xs-11,.factory-bootstrap-412 .col-xs-12,.factory-bootstrap-412 .col-xs-2,.factory-bootstrap-412 .col-xs-3,.factory-bootstrap-412 .col-xs-4,.factory-bootstrap-412 .col-xs-5,.factory-bootstrap-412 .col-xs-6,.factory-bootstrap-412 .col-xs-7,.factory-bootstrap-412 .col-xs-8,.factory-bootstrap-412 .col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.factory-bootstrap-412 .col-xs-1,.factory-bootstrap-412 .col-xs-10,.factory-bootstrap-412 .col-xs-11,.factory-bootstrap-412 .col-xs-12,.factory-bootstrap-412 .col-xs-2,.factory-bootstrap-412 .col-xs-3,.factory-bootstrap-412 .col-xs-4,.factory-bootstrap-412 .col-xs-5,.factory-bootstrap-412 .col-xs-6,.factory-bootstrap-412 .col-xs-7,.factory-bootstrap-412 .col-xs-8,.factory-bootstrap-412 .col-xs-9{float:left}.factory-bootstrap-412 .col-xs-12{width:100%}.factory-bootstrap-412 .col-xs-11{width:91.66666666666666%}.factory-bootstrap-412 .col-xs-10{width:83.33333333333334%}.factory-bootstrap-412 .col-xs-9{width:75%}.factory-bootstrap-412 .col-xs-8{width:66.66666666666666%}.factory-bootstrap-412 .col-xs-7{width:58.333333333333336%}.factory-bootstrap-412 .col-xs-6{width:50%}.factory-bootstrap-412 .col-xs-5{width:41.66666666666667%}.factory-bootstrap-412 .col-xs-4{width:33.33333333333333%}.factory-bootstrap-412 .col-xs-3{width:25%}.factory-bootstrap-412 .col-xs-2{width:16.666666666666664%}.factory-bootstrap-412 .col-xs-1{width:8.333333333333332%}.factory-bootstrap-412 .col-xs-pull-12{right:100%}.factory-bootstrap-412 .col-xs-pull-11{right:91.66666666666666%}.factory-bootstrap-412 .col-xs-pull-10{right:83.33333333333334%}.factory-bootstrap-412 .col-xs-pull-9{right:75%}.factory-bootstrap-412 .col-xs-pull-8{right:66.66666666666666%}.factory-bootstrap-412 .col-xs-pull-7{right:58.333333333333336%}.factory-bootstrap-412 .col-xs-pull-6{right:50%}.factory-bootstrap-412 .col-xs-pull-5{right:41.66666666666667%}.factory-bootstrap-412 .col-xs-pull-4{right:33.33333333333333%}.factory-bootstrap-412 .col-xs-pull-3{right:25%}.factory-bootstrap-412 .col-xs-pull-2{right:16.666666666666664%}.factory-bootstrap-412 .col-xs-pull-1{right:8.333333333333332%}.factory-bootstrap-412 .col-xs-pull-0{right:0}.factory-bootstrap-412 .col-xs-push-12{left:100%}.factory-bootstrap-412 .col-xs-push-11{left:91.66666666666666%}.factory-bootstrap-412 .col-xs-push-10{left:83.33333333333334%}.factory-bootstrap-412 .col-xs-push-9{left:75%}.factory-bootstrap-412 .col-xs-push-8{left:66.66666666666666%}.factory-bootstrap-412 .col-xs-push-7{left:58.333333333333336%}.factory-bootstrap-412 .col-xs-push-6{left:50%}.factory-bootstrap-412 .col-xs-push-5{left:41.66666666666667%}.factory-bootstrap-412 .col-xs-push-4{left:33.33333333333333%}.factory-bootstrap-412 .col-xs-push-3{left:25%}.factory-bootstrap-412 .col-xs-push-2{left:16.666666666666664%}.factory-bootstrap-412 .col-xs-push-1{left:8.333333333333332%}.factory-bootstrap-412 .col-xs-push-0{left:0}.factory-bootstrap-412 .col-xs-offset-12{margin-left:100%}.factory-bootstrap-412 .col-xs-offset-11{margin-left:91.66666666666666%}.factory-bootstrap-412 .col-xs-offset-10{margin-left:83.33333333333334%}.factory-bootstrap-412 .col-xs-offset-9{margin-left:75%}.factory-bootstrap-412 .col-xs-offset-8{margin-left:66.66666666666666%}.factory-bootstrap-412 .col-xs-offset-7{margin-left:58.333333333333336%}.factory-bootstrap-412 .col-xs-offset-6{margin-left:50%}.factory-bootstrap-412 .col-xs-offset-5{margin-left:41.66666666666667%}.factory-bootstrap-412 .col-xs-offset-4{margin-left:33.33333333333333%}.factory-bootstrap-412 .col-xs-offset-3{margin-left:25%}.factory-bootstrap-412 .col-xs-offset-2{margin-left:16.666666666666664%}.factory-bootstrap-412 .col-xs-offset-1{margin-left:8.333333333333332%}.factory-bootstrap-412 .col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}.factory-bootstrap-412 table{max-width:100%;background-color:transparent}.factory-bootstrap-412 th{text-align:left}.factory-bootstrap-412 .table{width:100%;margin-bottom:20px}.factory-bootstrap-412 .table>tbody>tr>td,.factory-bootstrap-412 .table>tbody>tr>th,.factory-bootstrap-412 .table>tfoot>tr>td,.factory-bootstrap-412 .table>tfoot>tr>th,.factory-bootstrap-412 .table>thead>tr>td,.factory-bootstrap-412 .table>thead>tr>th{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.factory-bootstrap-412 .table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.factory-bootstrap-412 .table>caption+thead>tr:first-child>td,.factory-bootstrap-412 .table>caption+thead>tr:first-child>th,.factory-bootstrap-412 .table>colgroup+thead>tr:first-child>td,.factory-bootstrap-412 .table>colgroup+thead>tr:first-child>th,.factory-bootstrap-412 .table>thead:first-child>tr:first-child>td,.factory-bootstrap-412 .table>thead:first-child>tr:first-child>th{border-top:0}.factory-bootstrap-412 .table>tbody+tbody{border-top:2px solid #ddd}.factory-bootstrap-412 .table .table{background-color:#fff}.factory-bootstrap-412 .table-condensed>tbody>tr>td,.factory-bootstrap-412 .table-condensed>tbody>tr>th,.factory-bootstrap-412 .table-condensed>tfoot>tr>td,.factory-bootstrap-412 .table-condensed>tfoot>tr>th,.factory-bootstrap-412 .table-condensed>thead>tr>td,.factory-bootstrap-412 .table-condensed>thead>tr>th{padding:5px}.factory-bootstrap-412 .table-bordered,.factory-bootstrap-412 .table-bordered>tbody>tr>td,.factory-bootstrap-412 .table-bordered>tbody>tr>th,.factory-bootstrap-412 .table-bordered>tfoot>tr>td,.factory-bootstrap-412 .table-bordered>tfoot>tr>th,.factory-bootstrap-412 .table-bordered>thead>tr>td,.factory-bootstrap-412 .table-bordered>thead>tr>th{border:1px solid #ddd}.factory-bootstrap-412 .table-bordered>thead>tr>td,.factory-bootstrap-412 .table-bordered>thead>tr>th{border-bottom-width:2px}.factory-bootstrap-412 .table-striped>tbody>tr:nth-child(odd)>td,.factory-bootstrap-412 .table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.factory-bootstrap-412 .table-hover>tbody>tr:hover>td,.factory-bootstrap-412 .table-hover>tbody>tr:hover>th{background-color:#f5f5f5}.factory-bootstrap-412 table col[class*=col-]{position:static;display:table-column;float:none}.factory-bootstrap-412 table td[class*=col-],.factory-bootstrap-412 table th[class*=col-]{display:table-cell;float:none}.factory-bootstrap-412 .table>tbody>.active>td,.factory-bootstrap-412 .table>tbody>.active>th,.factory-bootstrap-412 .table>tbody>tr>.active,.factory-bootstrap-412 .table>tfoot>.active>td,.factory-bootstrap-412 .table>tfoot>.active>th,.factory-bootstrap-412 .table>tfoot>tr>.active,.factory-bootstrap-412 .table>thead>.active>td,.factory-bootstrap-412 .table>thead>.active>th,.factory-bootstrap-412 .table>thead>tr>.active{background-color:#f5f5f5}.factory-bootstrap-412 .table-hover>tbody>.active:hover>td,.factory-bootstrap-412 .table-hover>tbody>.active:hover>th,.factory-bootstrap-412 .table-hover>tbody>tr>.active:hover{background-color:#e8e8e8}.factory-bootstrap-412 .table>tbody>.success>td,.factory-bootstrap-412 .table>tbody>.success>th,.factory-bootstrap-412 .table>tbody>tr>.success,.factory-bootstrap-412 .table>tfoot>.success>td,.factory-bootstrap-412 .table>tfoot>.success>th,.factory-bootstrap-412 .table>tfoot>tr>.success,.factory-bootstrap-412 .table>thead>.success>td,.factory-bootstrap-412 .table>thead>.success>th,.factory-bootstrap-412 .table>thead>tr>.success{background-color:#dff0d8}.factory-bootstrap-412 .table-hover>tbody>.success:hover>td,.factory-bootstrap-412 .table-hover>tbody>.success:hover>th,.factory-bootstrap-412 .table-hover>tbody>tr>.success:hover{background-color:#d0e9c6}.factory-bootstrap-412 .table>tbody>.danger>td,.factory-bootstrap-412 .table>tbody>.danger>th,.factory-bootstrap-412 .table>tbody>tr>.danger,.factory-bootstrap-412 .table>tfoot>.danger>td,.factory-bootstrap-412 .table>tfoot>.danger>th,.factory-bootstrap-412 .table>tfoot>tr>.danger,.factory-bootstrap-412 .table>thead>.danger>td,.factory-bootstrap-412 .table>thead>.danger>th,.factory-bootstrap-412 .table>thead>tr>.danger{background-color:#f2dede}.factory-bootstrap-412 .table-hover>tbody>.danger:hover>td,.factory-bootstrap-412 .table-hover>tbody>.danger:hover>th,.factory-bootstrap-412 .table-hover>tbody>tr>.danger:hover{background-color:#ebcccc}.factory-bootstrap-412 .table>tbody>.warning>td,.factory-bootstrap-412 .table>tbody>.warning>th,.factory-bootstrap-412 .table>tbody>tr>.warning,.factory-bootstrap-412 .table>tfoot>.warning>td,.factory-bootstrap-412 .table>tfoot>.warning>th,.factory-bootstrap-412 .table>tfoot>tr>.warning,.factory-bootstrap-412 .table>thead>.warning>td,.factory-bootstrap-412 .table>thead>.warning>th,.factory-bootstrap-412 .table>thead>tr>.warning{background-color:#fcf8e3}.factory-bootstrap-412 .table-hover>tbody>.warning:hover>td,.factory-bootstrap-412 .table-hover>tbody>.warning:hover>th,.factory-bootstrap-412 .table-hover>tbody>tr>.warning:hover{background-color:#faf2cc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}.factory-bootstrap-412 fieldset{padding:0;margin:0;border:0}.factory-bootstrap-412 legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5;-moz-box-sizing:content-box;box-sizing:content-box}.factory-bootstrap-412 label{display:inline-block;margin-bottom:5px;font-weight:700}.factory-bootstrap-412 input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.factory-bootstrap-412 input[type=checkbox],.factory-bootstrap-412 input[type=radio]{margin:4px 0 0;margin-top:1px \9;line-height:normal}.factory-bootstrap-412 input[type=file]{display:block}.factory-bootstrap-412 select[multiple],.factory-bootstrap-412 select[size]{height:auto}.factory-bootstrap-412 select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}.factory-bootstrap-412 input[type=checkbox]:focus,.factory-bootstrap-412 input[type=file]:focus,.factory-bootstrap-412 input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.factory-bootstrap-412 input[type=number]::-webkit-inner-spin-button,.factory-bootstrap-412 input[type=number]::-webkit-outer-spin-button{height:auto}.factory-bootstrap-412 output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.factory-bootstrap-412 .form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.factory-bootstrap-412 .form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-412 .form-control:-moz-placeholder{color:#999}.factory-bootstrap-412 .form-control::-moz-placeholder{color:#999;opacity:1}.factory-bootstrap-412 .form-control:-ms-input-placeholder{color:#999}.factory-bootstrap-412 .form-control::-webkit-input-placeholder{color:#999}.factory-bootstrap-412 .form-control[disabled],.factory-bootstrap-412 .form-control[readonly],.factory-bootstrap-412 fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}.factory-bootstrap-412 textarea.form-control{height:auto}.factory-bootstrap-412 .form-group{margin-bottom:15px}.factory-bootstrap-412 .checkbox,.factory-bootstrap-412 .radio{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.factory-bootstrap-412 .checkbox label,.factory-bootstrap-412 .radio label{display:inline;margin-bottom:0;font-weight:400;cursor:pointer}.factory-bootstrap-412 .checkbox input[type=checkbox],.factory-bootstrap-412 .checkbox-inline input[type=checkbox],.factory-bootstrap-412 .radio input[type=radio],.factory-bootstrap-412 .radio-inline input[type=radio]{float:left;margin-left:-20px}.factory-bootstrap-412 .checkbox+.checkbox,.factory-bootstrap-412 .radio+.radio{margin-top:-5px}.factory-bootstrap-412 .checkbox-inline,.factory-bootstrap-412 .radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.factory-bootstrap-412 .checkbox-inline+.checkbox-inline,.factory-bootstrap-412 .radio-inline+.radio-inline{margin-top:0;margin-left:10px}.factory-bootstrap-412 .checkbox-inline[disabled],.factory-bootstrap-412 .checkbox[disabled],.factory-bootstrap-412 .radio-inline[disabled],.factory-bootstrap-412 .radio[disabled],.factory-bootstrap-412 fieldset[disabled] .checkbox,.factory-bootstrap-412 fieldset[disabled] .checkbox-inline,.factory-bootstrap-412 fieldset[disabled] .radio,.factory-bootstrap-412 fieldset[disabled] .radio-inline,.factory-bootstrap-412 fieldset[disabled] input[type=checkbox],.factory-bootstrap-412 fieldset[disabled] input[type=radio],.factory-bootstrap-412 input[type=checkbox][disabled],.factory-bootstrap-412 input[type=radio][disabled]{cursor:not-allowed}.factory-bootstrap-412 .input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-412 select.input-sm{height:30px;line-height:30px}.factory-bootstrap-412 textarea.input-sm{height:auto}.factory-bootstrap-412 .input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-412 select.input-lg{height:46px;line-height:46px}.factory-bootstrap-412 textarea.input-lg{height:auto}.factory-bootstrap-412 .has-warning .checkbox,.factory-bootstrap-412 .has-warning .checkbox-inline,.factory-bootstrap-412 .has-warning .control-label,.factory-bootstrap-412 .has-warning .help-block,.factory-bootstrap-412 .has-warning .radio,.factory-bootstrap-412 .has-warning .radio-inline{color:#8a6d3b}.factory-bootstrap-412 .has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-412 .has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.factory-bootstrap-412 .has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.factory-bootstrap-412 .has-error .checkbox,.factory-bootstrap-412 .has-error .checkbox-inline,.factory-bootstrap-412 .has-error .control-label,.factory-bootstrap-412 .has-error .help-block,.factory-bootstrap-412 .has-error .radio,.factory-bootstrap-412 .has-error .radio-inline{color:#a94442}.factory-bootstrap-412 .controls{display:block}.factory-bootstrap-412 .has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-412 .has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.factory-bootstrap-412 .has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.factory-bootstrap-412 .has-success .checkbox,.factory-bootstrap-412 .has-success .checkbox-inline,.factory-bootstrap-412 .has-success .control-label,.factory-bootstrap-412 .has-success .help-block,.factory-bootstrap-412 .has-success .radio,.factory-bootstrap-412 .has-success .radio-inline{color:#3c763d}.factory-bootstrap-412 .has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-412 .has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.factory-bootstrap-412 .has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.factory-bootstrap-412 .form-control-static{margin-bottom:0}.factory-bootstrap-412 .help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373;font-weight:400}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline select.form-control{width:auto}.form-inline .checkbox,.form-inline .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{float:none;margin-left:0}}.factory-bootstrap-412 .form-horizontal .checkbox,.factory-bootstrap-412 .form-horizontal .checkbox-inline,.factory-bootstrap-412 .form-horizontal .control-label,.factory-bootstrap-412 .form-horizontal .radio,.factory-bootstrap-412 .form-horizontal .radio-inline{position:relative;padding-top:7px;margin-top:0;margin-bottom:0}.factory-bootstrap-412 .form-horizontal .control-label{max-width:200px}.factory-bootstrap-412 .form-horizontal .checkbox,.factory-bootstrap-412 .form-horizontal .radio{min-height:27px}.factory-bootstrap-412 .form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.factory-bootstrap-412 .form-horizontal .form-group:after,.factory-bootstrap-412 .form-horizontal .form-group:before{display:table;content:" "}.factory-bootstrap-412 .form-horizontal .form-group:after{clear:both}.factory-bootstrap-412 .form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.factory-bootstrap-412 .btn{display:inline-block;padding:5px 12px;margin-bottom:0;font-size:13px;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;border-radius:3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.factory-bootstrap-412 .btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.factory-bootstrap-412 .btn{text-decoration:none}.factory-bootstrap-412 .btn:focus,.factory-bootstrap-412 .btn:hover{color:#333;text-decoration:none}.factory-bootstrap-412 .btn.disabled,.factory-bootstrap-412 .btn[disabled],.factory-bootstrap-412 fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-412 .btn-default.active,.factory-bootstrap-412 .btn-default:active,.factory-bootstrap-412 .btn-default:focus,.factory-bootstrap-412 .btn-default:hover,.factory-bootstrap-412 .open .dropdown-toggle.btn-default{background:#fafafa;border-color:#999;color:#222}.factory-bootstrap-412 .btn-default.active,.factory-bootstrap-412 .btn-default:active,.factory-bootstrap-412 .open .dropdown-toggle.btn-default{background-image:none}.factory-bootstrap-412 .btn-default.disabled,.factory-bootstrap-412 .btn-default.disabled.active,.factory-bootstrap-412 .btn-default.disabled:active,.factory-bootstrap-412 .btn-default.disabled:focus,.factory-bootstrap-412 .btn-default.disabled:hover,.factory-bootstrap-412 .btn-default[disabled],.factory-bootstrap-412 .btn-default[disabled].active,.factory-bootstrap-412 .btn-default[disabled]:active,.factory-bootstrap-412 .btn-default[disabled]:focus,.factory-bootstrap-412 .btn-default[disabled]:hover,.factory-bootstrap-412 fieldset[disabled] .btn-default,.factory-bootstrap-412 fieldset[disabled] .btn-default.active,.factory-bootstrap-412 fieldset[disabled] .btn-default:active,.factory-bootstrap-412 fieldset[disabled] .btn-default:focus,.factory-bootstrap-412 fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.factory-bootstrap-412 .btn-default .badge{color:#fff;background-color:#fff}.factory-bootstrap-412 .btn-primary.active,.factory-bootstrap-412 .btn-primary:active,.factory-bootstrap-412 .btn-primary:focus,.factory-bootstrap-412 .btn-primary:hover,.factory-bootstrap-412 .open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.factory-bootstrap-412 .btn-primary.active,.factory-bootstrap-412 .btn-primary:active,.factory-bootstrap-412 .open .dropdown-toggle.btn-primary{background-image:none}.factory-bootstrap-412 .btn-primary.disabled,.factory-bootstrap-412 .btn-primary.disabled.active,.factory-bootstrap-412 .btn-primary.disabled:active,.factory-bootstrap-412 .btn-primary.disabled:focus,.factory-bootstrap-412 .btn-primary.disabled:hover,.factory-bootstrap-412 .btn-primary[disabled],.factory-bootstrap-412 .btn-primary[disabled].active,.factory-bootstrap-412 .btn-primary[disabled]:active,.factory-bootstrap-412 .btn-primary[disabled]:focus,.factory-bootstrap-412 .btn-primary[disabled]:hover,.factory-bootstrap-412 fieldset[disabled] .btn-primary,.factory-bootstrap-412 fieldset[disabled] .btn-primary.active,.factory-bootstrap-412 fieldset[disabled] .btn-primary:active,.factory-bootstrap-412 fieldset[disabled] .btn-primary:focus,.factory-bootstrap-412 fieldset[disabled] .btn-primary:hover{background-color:#428bca;border-color:#357ebd}.factory-bootstrap-412 .btn-primary .badge{color:#428bca;background-color:#fff}.factory-bootstrap-412 .btn-warning{color:#fff;background-color:#f0ad4e}.factory-bootstrap-412 .btn-warning.active,.factory-bootstrap-412 .btn-warning:active,.factory-bootstrap-412 .btn-warning:focus,.factory-bootstrap-412 .btn-warning:hover,.factory-bootstrap-412 .open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.factory-bootstrap-412 .btn-warning.active,.factory-bootstrap-412 .btn-warning:active,.factory-bootstrap-412 .open .dropdown-toggle.btn-warning{background-image:none}.factory-bootstrap-412 .btn-warning.disabled,.factory-bootstrap-412 .btn-warning.disabled.active,.factory-bootstrap-412 .btn-warning.disabled:active,.factory-bootstrap-412 .btn-warning.disabled:focus,.factory-bootstrap-412 .btn-warning.disabled:hover,.factory-bootstrap-412 .btn-warning[disabled],.factory-bootstrap-412 .btn-warning[disabled].active,.factory-bootstrap-412 .btn-warning[disabled]:active,.factory-bootstrap-412 .btn-warning[disabled]:focus,.factory-bootstrap-412 .btn-warning[disabled]:hover,.factory-bootstrap-412 fieldset[disabled] .btn-warning,.factory-bootstrap-412 fieldset[disabled] .btn-warning.active,.factory-bootstrap-412 fieldset[disabled] .btn-warning:active,.factory-bootstrap-412 fieldset[disabled] .btn-warning:focus,.factory-bootstrap-412 fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.factory-bootstrap-412 .btn-warning .badge{color:#f0ad4e;background-color:#fff}.factory-bootstrap-412 .btn-success{color:#fff;background-color:#5cb85c}.factory-bootstrap-412 .btn-success.active,.factory-bootstrap-412 .btn-success:active,.factory-bootstrap-412 .btn-success:focus,.factory-bootstrap-412 .btn-success:hover,.factory-bootstrap-412 .open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.factory-bootstrap-412 .btn-success.active,.factory-bootstrap-412 .btn-success:active,.factory-bootstrap-412 .open .dropdown-toggle.btn-success{background-image:none}.factory-bootstrap-412 .btn-success.disabled,.factory-bootstrap-412 .btn-success.disabled.active,.factory-bootstrap-412 .btn-success.disabled:active,.factory-bootstrap-412 .btn-success.disabled:focus,.factory-bootstrap-412 .btn-success.disabled:hover,.factory-bootstrap-412 .btn-success[disabled],.factory-bootstrap-412 .btn-success[disabled].active,.factory-bootstrap-412 .btn-success[disabled]:active,.factory-bootstrap-412 .btn-success[disabled]:focus,.factory-bootstrap-412 .btn-success[disabled]:hover,.factory-bootstrap-412 fieldset[disabled] .btn-success,.factory-bootstrap-412 fieldset[disabled] .btn-success.active,.factory-bootstrap-412 fieldset[disabled] .btn-success:active,.factory-bootstrap-412 fieldset[disabled] .btn-success:focus,.factory-bootstrap-412 fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.factory-bootstrap-412 .btn-success .badge{color:#5cb85c;background-color:#fff}.factory-bootstrap-412 .btn-info{color:#fff;background-color:#5bc0de}.factory-bootstrap-412 .btn-info.active,.factory-bootstrap-412 .btn-info:active,.factory-bootstrap-412 .btn-info:focus,.factory-bootstrap-412 .btn-info:hover,.factory-bootstrap-412 .open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.factory-bootstrap-412 .btn-info.active,.factory-bootstrap-412 .btn-info:active,.factory-bootstrap-412 .open .dropdown-toggle.btn-info{background-image:none}.factory-bootstrap-412 .btn-info.disabled,.factory-bootstrap-412 .btn-info.disabled.active,.factory-bootstrap-412 .btn-info.disabled:active,.factory-bootstrap-412 .btn-info.disabled:focus,.factory-bootstrap-412 .btn-info.disabled:hover,.factory-bootstrap-412 .btn-info[disabled],.factory-bootstrap-412 .btn-info[disabled].active,.factory-bootstrap-412 .btn-info[disabled]:active,.factory-bootstrap-412 .btn-info[disabled]:focus,.factory-bootstrap-412 .btn-info[disabled]:hover,.factory-bootstrap-412 fieldset[disabled] .btn-info,.factory-bootstrap-412 fieldset[disabled] .btn-info.active,.factory-bootstrap-412 fieldset[disabled] .btn-info:active,.factory-bootstrap-412 fieldset[disabled] .btn-info:focus,.factory-bootstrap-412 fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.factory-bootstrap-412 .btn-info .badge{color:#5bc0de;background-color:#fff}.factory-bootstrap-412 .btn-link{font-weight:400;color:#428bca;cursor:pointer;border-radius:0}.factory-bootstrap-412 .btn-link,.factory-bootstrap-412 .btn-link:active,.factory-bootstrap-412 .btn-link[disabled],.factory-bootstrap-412 fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-412 .btn-link,.factory-bootstrap-412 .btn-link:active,.factory-bootstrap-412 .btn-link:focus,.factory-bootstrap-412 .btn-link:hover{border-color:transparent}.factory-bootstrap-412 .btn-link:focus,.factory-bootstrap-412 .btn-link:hover{color:#2a6496;text-decoration:underline;background-color:transparent}.factory-bootstrap-412 .btn-link[disabled]:focus,.factory-bootstrap-412 .btn-link[disabled]:hover,.factory-bootstrap-412 fieldset[disabled] .btn-link:focus,.factory-bootstrap-412 fieldset[disabled] .btn-link:hover{color:#999;text-decoration:none}.factory-bootstrap-412 .btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-412 .btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-412 .btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-412 .btn-block{display:block;width:100%;padding-right:0;padding-left:0}.factory-bootstrap-412 .btn-block+.btn-block{margin-top:5px}.factory-bootstrap-412 input[type=button].btn-block,.factory-bootstrap-412 input[type=reset].btn-block,.factory-bootstrap-412 input[type=submit].btn-block{width:100%}.factory-bootstrap-412 .fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.factory-bootstrap-412 .fade.in{opacity:1}.factory-bootstrap-412 .collapse{display:none}.factory-bootstrap-412 .collapse.in{display:block}.factory-bootstrap-412 .collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular) format('svg')}.factory-bootstrap-412 .glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale}.factory-bootstrap-412 .glyphicon:empty{width:1em}.factory-bootstrap-412 .glyphicon-asterisk:before{content:"\2a"}.factory-bootstrap-412 .glyphicon-plus:before{content:"\2b"}.factory-bootstrap-412 .glyphicon-euro:before{content:"\20ac"}.factory-bootstrap-412 .glyphicon-minus:before{content:"\2212"}.factory-bootstrap-412 .glyphicon-cloud:before{content:"\2601"}.factory-bootstrap-412 .glyphicon-envelope:before{content:"\2709"}.factory-bootstrap-412 .glyphicon-pencil:before{content:"\270f"}.factory-bootstrap-412 .glyphicon-glass:before{content:"\e001"}.factory-bootstrap-412 .glyphicon-music:before{content:"\e002"}.factory-bootstrap-412 .glyphicon-search:before{content:"\e003"}.factory-bootstrap-412 .glyphicon-heart:before{content:"\e005"}.factory-bootstrap-412 .glyphicon-star:before{content:"\e006"}.factory-bootstrap-412 .glyphicon-star-empty:before{content:"\e007"}.factory-bootstrap-412 .glyphicon-user:before{content:"\e008"}.factory-bootstrap-412 .glyphicon-film:before{content:"\e009"}.factory-bootstrap-412 .glyphicon-th-large:before{content:"\e010"}.factory-bootstrap-412 .glyphicon-th:before{content:"\e011"}.factory-bootstrap-412 .glyphicon-th-list:before{content:"\e012"}.factory-bootstrap-412 .glyphicon-ok:before{content:"\e013"}.factory-bootstrap-412 .glyphicon-remove:before{content:"\e014"}.factory-bootstrap-412 .glyphicon-zoom-in:before{content:"\e015"}.factory-bootstrap-412 .glyphicon-zoom-out:before{content:"\e016"}.factory-bootstrap-412 .glyphicon-off:before{content:"\e017"}.factory-bootstrap-412 .glyphicon-signal:before{content:"\e018"}.factory-bootstrap-412 .glyphicon-cog:before{content:"\e019"}.factory-bootstrap-412 .glyphicon-trash:before{content:"\e020"}.factory-bootstrap-412 .glyphicon-home:before{content:"\e021"}.factory-bootstrap-412 .glyphicon-file:before{content:"\e022"}.factory-bootstrap-412 .glyphicon-time:before{content:"\e023"}.factory-bootstrap-412 .glyphicon-road:before{content:"\e024"}.factory-bootstrap-412 .glyphicon-download-alt:before{content:"\e025"}.factory-bootstrap-412 .glyphicon-download:before{content:"\e026"}.factory-bootstrap-412 .glyphicon-upload:before{content:"\e027"}.factory-bootstrap-412 .glyphicon-inbox:before{content:"\e028"}.factory-bootstrap-412 .glyphicon-play-circle:before{content:"\e029"}.factory-bootstrap-412 .glyphicon-repeat:before{content:"\e030"}.factory-bootstrap-412 .glyphicon-refresh:before{content:"\e031"}.factory-bootstrap-412 .glyphicon-list-alt:before{content:"\e032"}.factory-bootstrap-412 .glyphicon-lock:before{content:"\e033"}.factory-bootstrap-412 .glyphicon-flag:before{content:"\e034"}.factory-bootstrap-412 .glyphicon-headphones:before{content:"\e035"}.factory-bootstrap-412 .glyphicon-volume-off:before{content:"\e036"}.factory-bootstrap-412 .glyphicon-volume-down:before{content:"\e037"}.factory-bootstrap-412 .glyphicon-volume-up:before{content:"\e038"}.factory-bootstrap-412 .glyphicon-qrcode:before{content:"\e039"}.factory-bootstrap-412 .glyphicon-barcode:before{content:"\e040"}.factory-bootstrap-412 .glyphicon-tag:before{content:"\e041"}.factory-bootstrap-412 .glyphicon-tags:before{content:"\e042"}.factory-bootstrap-412 .glyphicon-book:before{content:"\e043"}.factory-bootstrap-412 .glyphicon-bookmark:before{content:"\e044"}.factory-bootstrap-412 .glyphicon-print:before{content:"\e045"}.factory-bootstrap-412 .glyphicon-camera:before{content:"\e046"}.factory-bootstrap-412 .glyphicon-font:before{content:"\e047"}.factory-bootstrap-412 .glyphicon-bold:before{content:"\e048"}.factory-bootstrap-412 .glyphicon-italic:before{content:"\e049"}.factory-bootstrap-412 .glyphicon-text-height:before{content:"\e050"}.factory-bootstrap-412 .glyphicon-text-width:before{content:"\e051"}.factory-bootstrap-412 .glyphicon-align-left:before{content:"\e052"}.factory-bootstrap-412 .glyphicon-align-center:before{content:"\e053"}.factory-bootstrap-412 .glyphicon-align-right:before{content:"\e054"}.factory-bootstrap-412 .glyphicon-align-justify:before{content:"\e055"}.factory-bootstrap-412 .glyphicon-list:before{content:"\e056"}.factory-bootstrap-412 .glyphicon-indent-left:before{content:"\e057"}.factory-bootstrap-412 .glyphicon-indent-right:before{content:"\e058"}.factory-bootstrap-412 .glyphicon-facetime-video:before{content:"\e059"}.factory-bootstrap-412 .glyphicon-picture:before{content:"\e060"}.factory-bootstrap-412 .glyphicon-map-marker:before{content:"\e062"}.factory-bootstrap-412 .glyphicon-adjust:before{content:"\e063"}.factory-bootstrap-412 .glyphicon-tint:before{content:"\e064"}.factory-bootstrap-412 .glyphicon-edit:before{content:"\e065"}.factory-bootstrap-412 .glyphicon-share:before{content:"\e066"}.factory-bootstrap-412 .glyphicon-check:before{content:"\e067"}.factory-bootstrap-412 .glyphicon-move:before{content:"\e068"}.factory-bootstrap-412 .glyphicon-step-backward:before{content:"\e069"}.factory-bootstrap-412 .glyphicon-fast-backward:before{content:"\e070"}.factory-bootstrap-412 .glyphicon-backward:before{content:"\e071"}.factory-bootstrap-412 .glyphicon-play:before{content:"\e072"}.factory-bootstrap-412 .glyphicon-pause:before{content:"\e073"}.factory-bootstrap-412 .glyphicon-stop:before{content:"\e074"}.factory-bootstrap-412 .glyphicon-forward:before{content:"\e075"}.factory-bootstrap-412 .glyphicon-fast-forward:before{content:"\e076"}.factory-bootstrap-412 .glyphicon-step-forward:before{content:"\e077"}.factory-bootstrap-412 .glyphicon-eject:before{content:"\e078"}.factory-bootstrap-412 .glyphicon-chevron-left:before{content:"\e079"}.factory-bootstrap-412 .glyphicon-chevron-right:before{content:"\e080"}.factory-bootstrap-412 .glyphicon-plus-sign:before{content:"\e081"}.factory-bootstrap-412 .glyphicon-minus-sign:before{content:"\e082"}.factory-bootstrap-412 .glyphicon-remove-sign:before{content:"\e083"}.factory-bootstrap-412 .glyphicon-ok-sign:before{content:"\e084"}.factory-bootstrap-412 .glyphicon-question-sign:before{content:"\e085"}.factory-bootstrap-412 .glyphicon-info-sign:before{content:"\e086"}.factory-bootstrap-412 .glyphicon-screenshot:before{content:"\e087"}.factory-bootstrap-412 .glyphicon-remove-circle:before{content:"\e088"}.factory-bootstrap-412 .glyphicon-ok-circle:before{content:"\e089"}.factory-bootstrap-412 .glyphicon-ban-circle:before{content:"\e090"}.factory-bootstrap-412 .glyphicon-arrow-left:before{content:"\e091"}.factory-bootstrap-412 .glyphicon-arrow-right:before{content:"\e092"}.factory-bootstrap-412 .glyphicon-arrow-up:before{content:"\e093"}.factory-bootstrap-412 .glyphicon-arrow-down:before{content:"\e094"}.factory-bootstrap-412 .glyphicon-share-alt:before{content:"\e095"}.factory-bootstrap-412 .glyphicon-resize-full:before{content:"\e096"}.factory-bootstrap-412 .glyphicon-resize-small:before{content:"\e097"}.factory-bootstrap-412 .glyphicon-exclamation-sign:before{content:"\e101"}.factory-bootstrap-412 .glyphicon-gift:before{content:"\e102"}.factory-bootstrap-412 .glyphicon-leaf:before{content:"\e103"}.factory-bootstrap-412 .glyphicon-fire:before{content:"\e104"}.factory-bootstrap-412 .glyphicon-eye-open:before{content:"\e105"}.factory-bootstrap-412 .glyphicon-eye-close:before{content:"\e106"}.factory-bootstrap-412 .glyphicon-warning-sign:before{content:"\e107"}.factory-bootstrap-412 .glyphicon-plane:before{content:"\e108"}.factory-bootstrap-412 .glyphicon-calendar:before{content:"\e109"}.factory-bootstrap-412 .glyphicon-random:before{content:"\e110"}.factory-bootstrap-412 .glyphicon-comment:before{content:"\e111"}.factory-bootstrap-412 .glyphicon-magnet:before{content:"\e112"}.factory-bootstrap-412 .glyphicon-chevron-up:before{content:"\e113"}.factory-bootstrap-412 .glyphicon-chevron-down:before{content:"\e114"}.factory-bootstrap-412 .glyphicon-retweet:before{content:"\e115"}.factory-bootstrap-412 .glyphicon-shopping-cart:before{content:"\e116"}.factory-bootstrap-412 .glyphicon-folder-close:before{content:"\e117"}.factory-bootstrap-412 .glyphicon-folder-open:before{content:"\e118"}.factory-bootstrap-412 .glyphicon-resize-vertical:before{content:"\e119"}.factory-bootstrap-412 .glyphicon-resize-horizontal:before{content:"\e120"}.factory-bootstrap-412 .glyphicon-hdd:before{content:"\e121"}.factory-bootstrap-412 .glyphicon-bullhorn:before{content:"\e122"}.factory-bootstrap-412 .glyphicon-bell:before{content:"\e123"}.factory-bootstrap-412 .glyphicon-certificate:before{content:"\e124"}.factory-bootstrap-412 .glyphicon-thumbs-up:before{content:"\e125"}.factory-bootstrap-412 .glyphicon-thumbs-down:before{content:"\e126"}.factory-bootstrap-412 .glyphicon-hand-right:before{content:"\e127"}.factory-bootstrap-412 .glyphicon-hand-left:before{content:"\e128"}.factory-bootstrap-412 .glyphicon-hand-up:before{content:"\e129"}.factory-bootstrap-412 .glyphicon-hand-down:before{content:"\e130"}.factory-bootstrap-412 .glyphicon-circle-arrow-right:before{content:"\e131"}.factory-bootstrap-412 .glyphicon-circle-arrow-left:before{content:"\e132"}.factory-bootstrap-412 .glyphicon-circle-arrow-up:before{content:"\e133"}.factory-bootstrap-412 .glyphicon-circle-arrow-down:before{content:"\e134"}.factory-bootstrap-412 .glyphicon-globe:before{content:"\e135"}.factory-bootstrap-412 .glyphicon-wrench:before{content:"\e136"}.factory-bootstrap-412 .glyphicon-tasks:before{content:"\e137"}.factory-bootstrap-412 .glyphicon-filter:before{content:"\e138"}.factory-bootstrap-412 .glyphicon-briefcase:before{content:"\e139"}.factory-bootstrap-412 .glyphicon-fullscreen:before{content:"\e140"}.factory-bootstrap-412 .glyphicon-dashboard:before{content:"\e141"}.factory-bootstrap-412 .glyphicon-paperclip:before{content:"\e142"}.factory-bootstrap-412 .glyphicon-heart-empty:before{content:"\e143"}.factory-bootstrap-412 .glyphicon-link:before{content:"\e144"}.factory-bootstrap-412 .glyphicon-phone:before{content:"\e145"}.factory-bootstrap-412 .glyphicon-pushpin:before{content:"\e146"}.factory-bootstrap-412 .glyphicon-usd:before{content:"\e148"}.factory-bootstrap-412 .glyphicon-gbp:before{content:"\e149"}.factory-bootstrap-412 .glyphicon-sort:before{content:"\e150"}.factory-bootstrap-412 .glyphicon-sort-by-alphabet:before{content:"\e151"}.factory-bootstrap-412 .glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.factory-bootstrap-412 .glyphicon-sort-by-order:before{content:"\e153"}.factory-bootstrap-412 .glyphicon-sort-by-order-alt:before{content:"\e154"}.factory-bootstrap-412 .glyphicon-sort-by-attributes:before{content:"\e155"}.factory-bootstrap-412 .glyphicon-sort-by-attributes-alt:before{content:"\e156"}.factory-bootstrap-412 .glyphicon-unchecked:before{content:"\e157"}.factory-bootstrap-412 .glyphicon-expand:before{content:"\e158"}.factory-bootstrap-412 .glyphicon-collapse-down:before{content:"\e159"}.factory-bootstrap-412 .glyphicon-collapse-up:before{content:"\e160"}.factory-bootstrap-412 .glyphicon-log-in:before{content:"\e161"}.factory-bootstrap-412 .glyphicon-flash:before{content:"\e162"}.factory-bootstrap-412 .glyphicon-log-out:before{content:"\e163"}.factory-bootstrap-412 .glyphicon-new-window:before{content:"\e164"}.factory-bootstrap-412 .glyphicon-record:before{content:"\e165"}.factory-bootstrap-412 .glyphicon-save:before{content:"\e166"}.factory-bootstrap-412 .glyphicon-open:before{content:"\e167"}.factory-bootstrap-412 .glyphicon-saved:before{content:"\e168"}.factory-bootstrap-412 .glyphicon-import:before{content:"\e169"}.factory-bootstrap-412 .glyphicon-export:before{content:"\e170"}.factory-bootstrap-412 .glyphicon-send:before{content:"\e171"}.factory-bootstrap-412 .glyphicon-floppy-disk:before{content:"\e172"}.factory-bootstrap-412 .glyphicon-floppy-saved:before{content:"\e173"}.factory-bootstrap-412 .glyphicon-floppy-remove:before{content:"\e174"}.factory-bootstrap-412 .glyphicon-floppy-save:before{content:"\e175"}.factory-bootstrap-412 .glyphicon-floppy-open:before{content:"\e176"}.factory-bootstrap-412 .glyphicon-credit-card:before{content:"\e177"}.factory-bootstrap-412 .glyphicon-transfer:before{content:"\e178"}.factory-bootstrap-412 .glyphicon-cutlery:before{content:"\e179"}.factory-bootstrap-412 .glyphicon-header:before{content:"\e180"}.factory-bootstrap-412 .glyphicon-compressed:before{content:"\e181"}.factory-bootstrap-412 .glyphicon-earphone:before{content:"\e182"}.factory-bootstrap-412 .glyphicon-phone-alt:before{content:"\e183"}.factory-bootstrap-412 .glyphicon-tower:before{content:"\e184"}.factory-bootstrap-412 .glyphicon-stats:before{content:"\e185"}.factory-bootstrap-412 .glyphicon-sd-video:before{content:"\e186"}.factory-bootstrap-412 .glyphicon-hd-video:before{content:"\e187"}.factory-bootstrap-412 .glyphicon-subtitles:before{content:"\e188"}.factory-bootstrap-412 .glyphicon-sound-stereo:before{content:"\e189"}.factory-bootstrap-412 .glyphicon-sound-dolby:before{content:"\e190"}.factory-bootstrap-412 .glyphicon-sound-5-1:before{content:"\e191"}.factory-bootstrap-412 .glyphicon-sound-6-1:before{content:"\e192"}.factory-bootstrap-412 .glyphicon-sound-7-1:before{content:"\e193"}.factory-bootstrap-412 .glyphicon-copyright-mark:before{content:"\e194"}.factory-bootstrap-412 .glyphicon-registration-mark:before{content:"\e195"}.factory-bootstrap-412 .glyphicon-cloud-download:before{content:"\e197"}.factory-bootstrap-412 .glyphicon-cloud-upload:before{content:"\e198"}.factory-bootstrap-412 .glyphicon-tree-conifer:before{content:"\e199"}.factory-bootstrap-412 .glyphicon-tree-deciduous:before{content:"\e200"}.factory-bootstrap-412 .caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.factory-bootstrap-412 .dropdown{position:relative}.factory-bootstrap-412 .dropdown-toggle:focus{outline:0}.factory-bootstrap-412 .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.factory-bootstrap-412 .dropdown-menu.pull-right{right:0;left:auto}.factory-bootstrap-412 .dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.factory-bootstrap-412 .dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429;color:#333;white-space:nowrap}.factory-bootstrap-412 .dropdown-menu>li>a:focus,.factory-bootstrap-412 .dropdown-menu>li>a:hover{color:#262626;text-decoration:none}.factory-bootstrap-412 .dropdown-menu>.active>a,.factory-bootstrap-412 .dropdown-menu>.active>a:focus,.factory-bootstrap-412 .dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0}.factory-bootstrap-412 .dropdown-menu>.disabled>a,.factory-bootstrap-412 .dropdown-menu>.disabled>a:focus,.factory-bootstrap-412 .dropdown-menu>.disabled>a:hover{color:#999}.factory-bootstrap-412 .dropdown-menu>.disabled>a:focus,.factory-bootstrap-412 .dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-412 .open>.dropdown-menu{display:block}.factory-bootstrap-412 .open>a{outline:0}.factory-bootstrap-412 .dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.factory-bootstrap-412 .dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.factory-bootstrap-412 .pull-right>.dropdown-menu{right:0;left:auto}.factory-bootstrap-412 .dropup .caret,.factory-bootstrap-412 .navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.factory-bootstrap-412 .dropup .dropdown-menu,.factory-bootstrap-412 .navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.factory-bootstrap-412 .btn-group,.factory-bootstrap-412 .btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.factory-bootstrap-412 .btn-group-vertical>.btn,.factory-bootstrap-412 .btn-group>.btn{position:relative;float:left}.factory-bootstrap-412 .btn-group-vertical>.btn.active,.factory-bootstrap-412 .btn-group-vertical>.btn:active,.factory-bootstrap-412 .btn-group-vertical>.btn:focus,.factory-bootstrap-412 .btn-group-vertical>.btn:hover,.factory-bootstrap-412 .btn-group>.btn.active,.factory-bootstrap-412 .btn-group>.btn:active,.factory-bootstrap-412 .btn-group>.btn:focus,.factory-bootstrap-412 .btn-group>.btn:hover{z-index:2}.factory-bootstrap-412 .btn-group-vertical>.btn:focus,.factory-bootstrap-412 .btn-group>.btn:focus{outline:0}.factory-bootstrap-412 .btn-group .btn+.btn,.factory-bootstrap-412 .btn-group .btn+.btn-group,.factory-bootstrap-412 .btn-group .btn-group+.btn,.factory-bootstrap-412 .btn-group .btn-group+.btn-group{margin-left:-1px}.factory-bootstrap-412 .btn-toolbar:after,.factory-bootstrap-412 .btn-toolbar:before{display:table;content:" "}.factory-bootstrap-412 .btn-toolbar:after{clear:both}.factory-bootstrap-412 .btn-toolbar .btn-group{float:left}.factory-bootstrap-412 .btn-toolbar>.btn+.btn,.factory-bootstrap-412 .btn-toolbar>.btn+.btn-group,.factory-bootstrap-412 .btn-toolbar>.btn-group+.btn,.factory-bootstrap-412 .btn-toolbar>.btn-group+.btn-group{margin-left:5px}.factory-bootstrap-412 .btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.factory-bootstrap-412 .btn-group>.btn:first-child{margin-left:0}.factory-bootstrap-412 .btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-412 .btn-group>.btn:last-child:not(:first-child),.factory-bootstrap-412 .btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-412 .btn-group>.btn-group{float:left}.factory-bootstrap-412 .btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.factory-bootstrap-412 .btn-group>.btn-group:first-child>.btn:last-child,.factory-bootstrap-412 .btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-412 .btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-412 .btn-group .dropdown-toggle:active,.factory-bootstrap-412 .btn-group.open .dropdown-toggle{outline:0}.factory-bootstrap-412 .btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-412 .btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-412 .btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-412 .btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.factory-bootstrap-412 .btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.factory-bootstrap-412 .btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.factory-bootstrap-412 .btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-412 .btn-group{border:4px solid #f9f9f9;border-radius:4px}.factory-bootstrap-412 .btn-group .btn.active.value{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-412 .btn .caret{margin-left:0}.factory-bootstrap-412 .btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.factory-bootstrap-412 .dropup .btn-lg .caret{border-width:0 5px 5px}.factory-bootstrap-412 .btn-group-vertical>.btn,.factory-bootstrap-412 .btn-group-vertical>.btn-group,.factory-bootstrap-412 .btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.factory-bootstrap-412 .btn-group-vertical>.btn-group:after,.factory-bootstrap-412 .btn-group-vertical>.btn-group:before{display:table;content:" "}.factory-bootstrap-412 .btn-group-vertical>.btn-group:after{clear:both}.factory-bootstrap-412 .btn-group-vertical>.btn-group>.btn{float:none}.factory-bootstrap-412 .btn-group-vertical>.btn+.btn,.factory-bootstrap-412 .btn-group-vertical>.btn+.btn-group,.factory-bootstrap-412 .btn-group-vertical>.btn-group+.btn,.factory-bootstrap-412 .btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.factory-bootstrap-412 .btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.factory-bootstrap-412 .btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-412 .btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.factory-bootstrap-412 .btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.factory-bootstrap-412 .btn-group-vertical>.btn-group:first-child>.btn:last-child,.factory-bootstrap-412 .btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-412 .btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-412 .btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.factory-bootstrap-412 .btn-group-justified>.btn,.factory-bootstrap-412 .btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.factory-bootstrap-412 .btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=checkbox],[data-toggle=buttons]>.btn>input[type=radio]{display:none}.factory-bootstrap-412 .input-group{position:relative;display:table;border-collapse:separate}.factory-bootstrap-412 .input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.factory-bootstrap-412 .input-group .form-control{width:100%;margin-bottom:0}.factory-bootstrap-412 .input-group-lg>.form-control,.factory-bootstrap-412 .input-group-lg>.input-group-addon,.factory-bootstrap-412 .input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-412 select.input-group-lg>.form-control,.factory-bootstrap-412 select.input-group-lg>.input-group-addon,.factory-bootstrap-412 select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}.factory-bootstrap-412 textarea.input-group-lg>.form-control,.factory-bootstrap-412 textarea.input-group-lg>.input-group-addon,.factory-bootstrap-412 textarea.input-group-lg>.input-group-btn>.btn{height:auto}.factory-bootstrap-412 .input-group-sm>.form-control,.factory-bootstrap-412 .input-group-sm>.input-group-addon,.factory-bootstrap-412 .input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-412 select.input-group-sm>.form-control,.factory-bootstrap-412 select.input-group-sm>.input-group-addon,.factory-bootstrap-412 select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}.factory-bootstrap-412 textarea.input-group-sm>.form-control,.factory-bootstrap-412 textarea.input-group-sm>.input-group-addon,.factory-bootstrap-412 textarea.input-group-sm>.input-group-btn>.btn{height:auto}.factory-bootstrap-412 .input-group .form-control,.factory-bootstrap-412 .input-group-addon,.factory-bootstrap-412 .input-group-btn{display:table-cell}.factory-bootstrap-412 .input-group .form-control:not(:first-child):not(:last-child),.factory-bootstrap-412 .input-group-addon:not(:first-child):not(:last-child),.factory-bootstrap-412 .input-group-btn:not(:first-child):not(:last-child){border-radius:0}.factory-bootstrap-412 .input-group-addon,.factory-bootstrap-412 .input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.factory-bootstrap-412 .input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.factory-bootstrap-412 .input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.factory-bootstrap-412 .input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.factory-bootstrap-412 .input-group-addon input[type=checkbox],.factory-bootstrap-412 .input-group-addon input[type=radio]{margin-top:0}.factory-bootstrap-412 .input-group .form-control:first-child,.factory-bootstrap-412 .input-group-addon:first-child,.factory-bootstrap-412 .input-group-btn:first-child>.btn,.factory-bootstrap-412 .input-group-btn:first-child>.dropdown-toggle,.factory-bootstrap-412 .input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-412 .input-group-addon:first-child{border-right:0}.factory-bootstrap-412 .input-group .form-control:last-child,.factory-bootstrap-412 .input-group-addon:last-child,.factory-bootstrap-412 .input-group-btn:first-child>.btn:not(:first-child),.factory-bootstrap-412 .input-group-btn:last-child>.btn,.factory-bootstrap-412 .input-group-btn:last-child>.dropdown-toggle{border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-412 .input-group-addon:last-child{border-left:0}.factory-bootstrap-412 .input-group-btn{position:relative;white-space:nowrap}.factory-bootstrap-412 .input-group-btn:first-child>.btn{margin-right:-1px}.factory-bootstrap-412 .input-group-btn:last-child>.btn{margin-left:-1px}.factory-bootstrap-412 .input-group-btn>.btn{position:relative}.factory-bootstrap-412 .input-group-btn>.btn+.btn{margin-left:-4px}.factory-bootstrap-412 .input-group-btn>.btn:active,.factory-bootstrap-412 .input-group-btn>.btn:hover{z-index:2}.factory-bootstrap-412 .nav{padding-left:0;margin-bottom:0;list-style:none}.factory-bootstrap-412 .nav:after,.factory-bootstrap-412 .nav:before{display:table;content:" "}.factory-bootstrap-412 .nav:after{clear:both}.factory-bootstrap-412 .nav>li{position:relative;display:block}.factory-bootstrap-412 .nav>li>a{position:relative;display:block;padding:10px 15px}.factory-bootstrap-412 .nav>li>a:focus,.factory-bootstrap-412 .nav>li>a:hover{text-decoration:none;background-color:#eee}.factory-bootstrap-412 .nav>li.disabled>a{color:#999}.factory-bootstrap-412 .nav>li.disabled>a:focus,.factory-bootstrap-412 .nav>li.disabled>a:hover{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.factory-bootstrap-412 .nav .open>a,.factory-bootstrap-412 .nav .open>a:focus,.factory-bootstrap-412 .nav .open>a:hover{background-color:#eee;border-color:#428bca}.factory-bootstrap-412 .nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.factory-bootstrap-412 .nav>li>a>img{max-width:none}.factory-bootstrap-412 .nav-tabs{border-bottom:1px solid #ddd}.factory-bootstrap-412 .nav-tabs>li{float:left;margin-bottom:-1px}.factory-bootstrap-412 .nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.factory-bootstrap-412 .nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.factory-bootstrap-412 .nav-tabs>li.active>a,.factory-bootstrap-412 .nav-tabs>li.active>a:focus,.factory-bootstrap-412 .nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.factory-bootstrap-412 .nav-tabs.nav-justified{width:100%;border-bottom:0}.factory-bootstrap-412 .nav-tabs.nav-justified>li{float:none}.factory-bootstrap-412 .nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.factory-bootstrap-412 .nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.factory-bootstrap-412 .nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.factory-bootstrap-412 .nav-tabs.nav-justified>.active>a,.factory-bootstrap-412 .nav-tabs.nav-justified>.active>a:focus,.factory-bootstrap-412 .nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.factory-bootstrap-412 .nav-pills>li{float:left}.factory-bootstrap-412 .nav-pills>li>a{border-radius:4px}.factory-bootstrap-412 .nav-pills>li+li{margin-left:2px}.factory-bootstrap-412 .nav-pills>li.active>a,.factory-bootstrap-412 .nav-pills>li.active>a:focus,.factory-bootstrap-412 .nav-pills>li.active>a:hover{color:#fff;background-color:#428bca}.factory-bootstrap-412 .nav-stacked>li{float:none}.factory-bootstrap-412 .nav-stacked>li+li{margin-top:2px;margin-left:0}.factory-bootstrap-412 .nav-justified{width:100%}.factory-bootstrap-412 .nav-justified>li{float:none}.factory-bootstrap-412 .nav-justified>li>a{margin-bottom:5px;text-align:center}.factory-bootstrap-412 .nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.factory-bootstrap-412 .nav-tabs-justified{border-bottom:0}.factory-bootstrap-412 .nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.factory-bootstrap-412 .nav-tabs-justified>.active>a,.factory-bootstrap-412 .nav-tabs-justified>.active>a:focus,.factory-bootstrap-412 .nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.factory-bootstrap-412 .tab-content>.tab-pane{display:none}.factory-bootstrap-412 .tab-content>.active{display:block}.factory-bootstrap-412 .nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-412 .navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.factory-bootstrap-412 .navbar:after,.factory-bootstrap-412 .navbar:before{display:table;content:" "}.factory-bootstrap-412 .navbar:after{clear:both}@media (min-width:768px){.navbar{border-radius:4px}}.factory-bootstrap-412 .navbar-header:after,.factory-bootstrap-412 .navbar-header:before{display:table;content:" "}.factory-bootstrap-412 .navbar-header:after{clear:both}@media (min-width:768px){.navbar-header{float:left}}.factory-bootstrap-412 .navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.factory-bootstrap-412 .navbar-collapse:after,.factory-bootstrap-412 .navbar-collapse:before{display:table;content:" "}.factory-bootstrap-412 .navbar-collapse:after{clear:both}.factory-bootstrap-412 .navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.factory-bootstrap-412 .container>.navbar-collapse,.factory-bootstrap-412 .container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.factory-bootstrap-412 .navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.factory-bootstrap-412 .navbar-fixed-bottom,.factory-bootstrap-412 .navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.factory-bootstrap-412 .navbar-fixed-top{top:0;border-width:0 0 1px}.factory-bootstrap-412 .navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.factory-bootstrap-412 .navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px}.factory-bootstrap-412 .navbar-brand:focus,.factory-bootstrap-412 .navbar-brand:hover{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.factory-bootstrap-412 .navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.factory-bootstrap-412 .navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.factory-bootstrap-412 .navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.factory-bootstrap-412 .navbar-nav{margin:7.5px -15px}.factory-bootstrap-412 .navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.factory-bootstrap-412 .navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form select.form-control{width:auto}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{float:none;margin-left:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.factory-bootstrap-412 .navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-412 .navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-412 .navbar-nav.pull-right>li>.dropdown-menu,.factory-bootstrap-412 .navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.factory-bootstrap-412 .navbar-btn{margin-top:8px;margin-bottom:8px}.factory-bootstrap-412 .navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.factory-bootstrap-412 .navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.factory-bootstrap-412 .navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.factory-bootstrap-412 .navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.factory-bootstrap-412 .navbar-default .navbar-brand{color:#777}.factory-bootstrap-412 .navbar-default .navbar-brand:focus,.factory-bootstrap-412 .navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.factory-bootstrap-412 .navbar-default .navbar-nav>li>a,.factory-bootstrap-412 .navbar-default .navbar-text{color:#777}.factory-bootstrap-412 .navbar-default .navbar-nav>li>a:focus,.factory-bootstrap-412 .navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.factory-bootstrap-412 .navbar-default .navbar-nav>.active>a,.factory-bootstrap-412 .navbar-default .navbar-nav>.active>a:focus,.factory-bootstrap-412 .navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.factory-bootstrap-412 .navbar-default .navbar-nav>.disabled>a,.factory-bootstrap-412 .navbar-default .navbar-nav>.disabled>a:focus,.factory-bootstrap-412 .navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.factory-bootstrap-412 .navbar-default .navbar-toggle{border-color:#ddd}.factory-bootstrap-412 .navbar-default .navbar-toggle:focus,.factory-bootstrap-412 .navbar-default .navbar-toggle:hover{background-color:#ddd}.factory-bootstrap-412 .navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.factory-bootstrap-412 .navbar-default .navbar-collapse,.factory-bootstrap-412 .navbar-default .navbar-form{border-color:#e7e7e7}.factory-bootstrap-412 .navbar-default .navbar-nav>.open>a,.factory-bootstrap-412 .navbar-default .navbar-nav>.open>a:focus,.factory-bootstrap-412 .navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.factory-bootstrap-412 .navbar-default .navbar-link{color:#777}.factory-bootstrap-412 .navbar-default .navbar-link:hover{color:#333}.factory-bootstrap-412 .navbar-inverse{background-color:#222;border-color:#080808}.factory-bootstrap-412 .navbar-inverse .navbar-brand{color:#999}.factory-bootstrap-412 .navbar-inverse .navbar-brand:focus,.factory-bootstrap-412 .navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.factory-bootstrap-412 .navbar-inverse .navbar-nav>li>a,.factory-bootstrap-412 .navbar-inverse .navbar-text{color:#999}.factory-bootstrap-412 .navbar-inverse .navbar-nav>li>a:focus,.factory-bootstrap-412 .navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.factory-bootstrap-412 .navbar-inverse .navbar-nav>.active>a,.factory-bootstrap-412 .navbar-inverse .navbar-nav>.active>a:focus,.factory-bootstrap-412 .navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.factory-bootstrap-412 .navbar-inverse .navbar-nav>.disabled>a,.factory-bootstrap-412 .navbar-inverse .navbar-nav>.disabled>a:focus,.factory-bootstrap-412 .navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.factory-bootstrap-412 .navbar-inverse .navbar-toggle{border-color:#333}.factory-bootstrap-412 .navbar-inverse .navbar-toggle:focus,.factory-bootstrap-412 .navbar-inverse .navbar-toggle:hover{background-color:#333}.factory-bootstrap-412 .navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.factory-bootstrap-412 .navbar-inverse .navbar-collapse,.factory-bootstrap-412 .navbar-inverse .navbar-form{border-color:#101010}.factory-bootstrap-412 .navbar-inverse .navbar-nav>.open>a,.factory-bootstrap-412 .navbar-inverse .navbar-nav>.open>a:focus,.factory-bootstrap-412 .navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.factory-bootstrap-412 .navbar-inverse .navbar-link{color:#999}.factory-bootstrap-412 .navbar-inverse .navbar-link:hover{color:#fff}.factory-bootstrap-412 .breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.factory-bootstrap-412 .breadcrumb>li{display:inline-block}.factory-bootstrap-412 .breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.factory-bootstrap-412 .breadcrumb>.active{color:#999}.factory-bootstrap-412 .pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.factory-bootstrap-412 .pagination>li{display:inline}.factory-bootstrap-412 .pagination>li>a,.factory-bootstrap-412 .pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.factory-bootstrap-412 .pagination>li:first-child>a,.factory-bootstrap-412 .pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.factory-bootstrap-412 .pagination>li:last-child>a,.factory-bootstrap-412 .pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.factory-bootstrap-412 .pagination>li>a:focus,.factory-bootstrap-412 .pagination>li>a:hover,.factory-bootstrap-412 .pagination>li>span:focus,.factory-bootstrap-412 .pagination>li>span:hover{background-color:#eee}.factory-bootstrap-412 .pagination>.active>a,.factory-bootstrap-412 .pagination>.active>a:focus,.factory-bootstrap-412 .pagination>.active>a:hover,.factory-bootstrap-412 .pagination>.active>span,.factory-bootstrap-412 .pagination>.active>span:focus,.factory-bootstrap-412 .pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#1e8cbe;border-color:#0074a2}.factory-bootstrap-412 .pagination>.disabled>a,.factory-bootstrap-412 .pagination>.disabled>a:focus,.factory-bootstrap-412 .pagination>.disabled>a:hover,.factory-bootstrap-412 .pagination>.disabled>span,.factory-bootstrap-412 .pagination>.disabled>span:focus,.factory-bootstrap-412 .pagination>.disabled>span:hover{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.factory-bootstrap-412 .pagination-lg>li>a,.factory-bootstrap-412 .pagination-lg>li>span{padding:10px 16px;font-size:18px}.factory-bootstrap-412 .pagination-lg>li:first-child>a,.factory-bootstrap-412 .pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.factory-bootstrap-412 .pagination-lg>li:last-child>a,.factory-bootstrap-412 .pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.factory-bootstrap-412 .pagination-sm>li>a,.factory-bootstrap-412 .pagination-sm>li>span{padding:5px 10px;font-size:12px}.factory-bootstrap-412 .pagination-sm>li:first-child>a,.factory-bootstrap-412 .pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.factory-bootstrap-412 .pagination-sm>li:last-child>a,.factory-bootstrap-412 .pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.factory-bootstrap-412 .pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.factory-bootstrap-412 .pager:after,.factory-bootstrap-412 .pager:before{display:table;content:" "}.factory-bootstrap-412 .pager:after{clear:both}.factory-bootstrap-412 .pager li{display:inline}.factory-bootstrap-412 .pager li>a,.factory-bootstrap-412 .pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.factory-bootstrap-412 .pager li>a:focus,.factory-bootstrap-412 .pager li>a:hover{text-decoration:none;background-color:#eee}.factory-bootstrap-412 .pager .next>a,.factory-bootstrap-412 .pager .next>span{float:right}.factory-bootstrap-412 .pager .previous>a,.factory-bootstrap-412 .pager .previous>span{float:left}.factory-bootstrap-412 .pager .disabled>a,.factory-bootstrap-412 .pager .disabled>a:focus,.factory-bootstrap-412 .pager .disabled>a:hover,.factory-bootstrap-412 .pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.factory-bootstrap-412 .label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.factory-bootstrap-412 .label[href]:focus,.factory-bootstrap-412 .label[href]:hover{color:#fff;text-decoration:none;cursor:pointer}.factory-bootstrap-412 .label:empty{display:none}.factory-bootstrap-412 .btn .label{position:relative;top:-1px}.factory-bootstrap-412 .label-default{background-color:#999}.factory-bootstrap-412 .label-default[href]:focus,.factory-bootstrap-412 .label-default[href]:hover{background-color:gray}.factory-bootstrap-412 .label-primary{background-color:#428bca}.factory-bootstrap-412 .label-primary[href]:focus,.factory-bootstrap-412 .label-primary[href]:hover{background-color:#3071a9}.factory-bootstrap-412 .label-success{background-color:#5cb85c}.factory-bootstrap-412 .label-success[href]:focus,.factory-bootstrap-412 .label-success[href]:hover{background-color:#449d44}.factory-bootstrap-412 .label-info{background-color:#5bc0de}.factory-bootstrap-412 .label-info[href]:focus,.factory-bootstrap-412 .label-info[href]:hover{background-color:#31b0d5}.factory-bootstrap-412 .label-warning{background-color:#f0ad4e}.factory-bootstrap-412 .label-warning[href]:focus,.factory-bootstrap-412 .label-warning[href]:hover{background-color:#ec971f}.factory-bootstrap-412 .label-danger{background-color:#d9534f}.factory-bootstrap-412 .label-danger[href]:focus,.factory-bootstrap-412 .label-danger[href]:hover{background-color:#c9302c}.factory-bootstrap-412 .badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.factory-bootstrap-412 .badge:empty{display:none}.factory-bootstrap-412 .btn .badge{position:relative;top:-1px}.factory-bootstrap-412 a.badge:focus,.factory-bootstrap-412 a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.factory-bootstrap-412 .nav-pills>.active>a>.badge,.factory-bootstrap-412 a.list-group-item.active>.badge{color:#428bca;background-color:#fff}.factory-bootstrap-412 .nav-pills>li>a>.badge{margin-left:3px}.factory-bootstrap-412 .jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.factory-bootstrap-412 .jumbotron .h1,.factory-bootstrap-412 .jumbotron h1{line-height:1;color:inherit}.factory-bootstrap-412 .jumbotron p{line-height:1.4}.factory-bootstrap-412 .container .jumbotron{border-radius:6px}.factory-bootstrap-412 .jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.factory-bootstrap-412 .thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.factory-bootstrap-412 .thumbnail a>img,.factory-bootstrap-412 .thumbnail>img{display:block;height:auto;max-width:100%;margin-right:auto;margin-left:auto}.factory-bootstrap-412 a.thumbnail.active,.factory-bootstrap-412 a.thumbnail:focus,.factory-bootstrap-412 a.thumbnail:hover{border-color:#428bca}.factory-bootstrap-412 .thumbnail .caption{padding:9px;color:#333}.factory-bootstrap-412 .alert{border:1px solid transparent;border-radius:4px}.factory-bootstrap-412 .alert h4{margin-top:0;color:inherit}.factory-bootstrap-412 .alert .alert-link{font-weight:700}.factory-bootstrap-412 .alert>p,.factory-bootstrap-412 .alert>ul{margin-bottom:0}.factory-bootstrap-412 .alert>p+p{margin-top:5px}.factory-bootstrap-412 .alert-dismissable{padding-right:35px}.factory-bootstrap-412 .alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.factory-bootstrap-412 .alert-info{color:#31708f;background-color:#d9edf7}.factory-bootstrap-412 .alert-info hr{border-top-color:#a6e1ec}.factory-bootstrap-412 .alert-info .alert-link{color:#245269}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.factory-bootstrap-412 .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.factory-bootstrap-412 .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#2ea2cc;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.factory-bootstrap-412 .progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.factory-bootstrap-412 .progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.factory-bootstrap-412 .progress-bar-success{background-color:#5cb85c}.factory-bootstrap-412 .progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-412 .progress-bar-info{background-color:#5bc0de}.factory-bootstrap-412 .progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-412 .progress-bar-warning{background-color:#f0ad4e}.factory-bootstrap-412 .progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-412 .progress-bar-danger{background-color:#d9534f}.factory-bootstrap-412 .progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-412 .media,.factory-bootstrap-412 .media-body{overflow:hidden;zoom:1}.factory-bootstrap-412 .media,.factory-bootstrap-412 .media .media{margin-top:15px}.factory-bootstrap-412 .media:first-child{margin-top:0}.factory-bootstrap-412 .media-object{display:block}.factory-bootstrap-412 .media-heading{margin:0 0 5px}.factory-bootstrap-412 .media>.pull-left{margin-right:10px}.factory-bootstrap-412 .media>.pull-right{margin-left:10px}.factory-bootstrap-412 .media-list{padding-left:0;list-style:none}.factory-bootstrap-412 .list-group{padding-left:0;margin-bottom:20px}.factory-bootstrap-412 .list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.factory-bootstrap-412 .list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.factory-bootstrap-412 .list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.factory-bootstrap-412 .list-group-item>.badge{float:right}.factory-bootstrap-412 .list-group-item>.badge+.badge{margin-right:5px}.factory-bootstrap-412 a.list-group-item{color:#555}.factory-bootstrap-412 a.list-group-item .list-group-item-heading{color:#333}.factory-bootstrap-412 a.list-group-item:focus,.factory-bootstrap-412 a.list-group-item:hover{text-decoration:none;background-color:#f5f5f5}.factory-bootstrap-412 a.list-group-item.active,.factory-bootstrap-412 a.list-group-item.active:focus,.factory-bootstrap-412 a.list-group-item.active:hover{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.factory-bootstrap-412 a.list-group-item.active .list-group-item-heading,.factory-bootstrap-412 a.list-group-item.active:focus .list-group-item-heading,.factory-bootstrap-412 a.list-group-item.active:hover .list-group-item-heading{color:inherit}.factory-bootstrap-412 a.list-group-item.active .list-group-item-text,.factory-bootstrap-412 a.list-group-item.active:focus .list-group-item-text,.factory-bootstrap-412 a.list-group-item.active:hover .list-group-item-text{color:#e1edf7}.factory-bootstrap-412 .list-group-item-heading{margin-top:0;margin-bottom:5px}.factory-bootstrap-412 .list-group-item-text{margin-bottom:0;line-height:1.3}.factory-bootstrap-412 .panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px}.factory-bootstrap-412 .panel-body{padding:15px}.factory-bootstrap-412 .panel-body:after,.factory-bootstrap-412 .panel-body:before{display:table;content:" "}.factory-bootstrap-412 .panel-body:after{clear:both}.factory-bootstrap-412 .panel>.list-group{margin-bottom:0}.factory-bootstrap-412 .panel>.list-group .list-group-item{border-width:1px 0}.factory-bootstrap-412 .panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-412 .panel>.list-group .list-group-item:last-child{border-bottom:0}.factory-bootstrap-412 .panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.factory-bootstrap-412 .panel>.table,.factory-bootstrap-412 .panel>.table-responsive>.table{margin-bottom:0}.factory-bootstrap-412 .panel>.panel-body+.table,.factory-bootstrap-412 .panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.factory-bootstrap-412 .panel>.table>tbody:first-child td,.factory-bootstrap-412 .panel>.table>tbody:first-child th{border-top:0}.factory-bootstrap-412 .panel>.table-bordered,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered{border:0}.factory-bootstrap-412 .panel>.table-bordered>tbody>tr>td:first-child,.factory-bootstrap-412 .panel>.table-bordered>tbody>tr>th:first-child,.factory-bootstrap-412 .panel>.table-bordered>tfoot>tr>td:first-child,.factory-bootstrap-412 .panel>.table-bordered>tfoot>tr>th:first-child,.factory-bootstrap-412 .panel>.table-bordered>thead>tr>td:first-child,.factory-bootstrap-412 .panel>.table-bordered>thead>tr>th:first-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.factory-bootstrap-412 .panel>.table-bordered>tbody>tr>td:last-child,.factory-bootstrap-412 .panel>.table-bordered>tbody>tr>th:last-child,.factory-bootstrap-412 .panel>.table-bordered>tfoot>tr>td:last-child,.factory-bootstrap-412 .panel>.table-bordered>tfoot>tr>th:last-child,.factory-bootstrap-412 .panel>.table-bordered>thead>tr>td:last-child,.factory-bootstrap-412 .panel>.table-bordered>thead>tr>th:last-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.factory-bootstrap-412 .panel>.table-bordered>tbody>tr:last-child>td,.factory-bootstrap-412 .panel>.table-bordered>tbody>tr:last-child>th,.factory-bootstrap-412 .panel>.table-bordered>tfoot>tr:last-child>td,.factory-bootstrap-412 .panel>.table-bordered>tfoot>tr:last-child>th,.factory-bootstrap-412 .panel>.table-bordered>thead>tr:last-child>td,.factory-bootstrap-412 .panel>.table-bordered>thead>tr:last-child>th,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.factory-bootstrap-412 .panel>.table-responsive>.table-bordered>thead>tr:last-child>th{border-bottom:0}.factory-bootstrap-412 .panel>.table-responsive{margin-bottom:0;border:0}.factory-bootstrap-412 .panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.factory-bootstrap-412 .panel-heading>.dropdown .dropdown-toggle{color:inherit}.factory-bootstrap-412 .panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.factory-bootstrap-412 .panel-title>a{color:inherit}.factory-bootstrap-412 .panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.factory-bootstrap-412 .panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.factory-bootstrap-412 .panel-group .panel+.panel{margin-top:5px}.factory-bootstrap-412 .panel-group .panel-heading{border-bottom:0}.factory-bootstrap-412 .panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.factory-bootstrap-412 .panel-group .panel-footer{border-top:0}.factory-bootstrap-412 .panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.factory-bootstrap-412 .panel-default{border-color:#ddd}.factory-bootstrap-412 .panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.factory-bootstrap-412 .panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.factory-bootstrap-412 .panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.factory-bootstrap-412 .panel-primary{border-color:#428bca}.factory-bootstrap-412 .panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.factory-bootstrap-412 .panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.factory-bootstrap-412 .panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.factory-bootstrap-412 .panel-success{border-color:#d6e9c6}.factory-bootstrap-412 .panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.factory-bootstrap-412 .panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.factory-bootstrap-412 .panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.factory-bootstrap-412 .panel-warning{border-color:#faebcc}.factory-bootstrap-412 .panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.factory-bootstrap-412 .panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.factory-bootstrap-412 .panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.factory-bootstrap-412 .panel-danger{border-color:#ebccd1}.factory-bootstrap-412 .panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.factory-bootstrap-412 .panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.factory-bootstrap-412 .panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.factory-bootstrap-412 .panel-info{border-color:#bce8f1}.factory-bootstrap-412 .panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.factory-bootstrap-412 .panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.factory-bootstrap-412 .panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.factory-bootstrap-412 .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px}.factory-bootstrap-412 .well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.factory-bootstrap-412 .well-lg{padding:24px;border-radius:6px}.factory-bootstrap-412 .well-sm{padding:9px;border-radius:3px}.factory-bootstrap-412 .close{float:right;font-size:14px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.3;filter:alpha(opacity=30)}.factory-bootstrap-412 .alert .close{position:relative;top:-8px;right:-7px}.factory-bootstrap-412 .close:focus,.factory-bootstrap-412 .close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}.factory-bootstrap-412 button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.factory-bootstrap-412 .modal-open{overflow:hidden}.factory-bootstrap-412 .modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll;width:auto;margin-left:0;background-color:transparent;border:0}.factory-bootstrap-412 .modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.factory-bootstrap-412 .modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.factory-bootstrap-412 .modal-dialog{position:relative;z-index:1050;width:auto;margin:10px}.factory-bootstrap-412 .modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box}.factory-bootstrap-412 .modal-backdrop,.factory-bootstrap-412-modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.factory-bootstrap-412 .modal-backdrop.fade,.factory-bootstrap-412-modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.factory-bootstrap-412 .modal-backdrop.in,.factory-bootstrap-412-modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.factory-bootstrap-412 .modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.factory-bootstrap-412 .modal-header .close{margin-top:-2px}.factory-bootstrap-412 .modal-title{margin:0;line-height:1.428571429}.factory-bootstrap-412 .modal-body{position:relative;padding:20px;max-height:none}.factory-bootstrap-412 .modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.factory-bootstrap-412 .modal-footer:after,.factory-bootstrap-412 .modal-footer:before{display:table;content:" "}.factory-bootstrap-412 .modal-footer:after{clear:both}.factory-bootstrap-412 .modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.factory-bootstrap-412 .modal-footer .btn-group .btn+.btn{margin-left:-1px}.factory-bootstrap-412 .modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.factory-bootstrap-412 .modal-dialog{width:600px;margin:30px auto}.factory-bootstrap-412 .modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}}.factory-bootstrap-412 .tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.factory-bootstrap-412 .tooltip.in{opacity:.9;filter:alpha(opacity=90)}.factory-bootstrap-412 .tooltip.top{padding:5px 0;margin-top:-3px}.factory-bootstrap-412 .tooltip.right{padding:0 5px;margin-left:3px}.factory-bootstrap-412 .tooltip.bottom{padding:5px 0;margin-top:3px}.factory-bootstrap-412 .tooltip.left{padding:0 5px;margin-left:-3px}.factory-bootstrap-412 .tooltip-inner{width:400px;padding:15px 20px;color:#fff;text-align:left;text-decoration:none;background-color:#673ab7;border-radius:3px}.factory-bootstrap-412 .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.factory-bootstrap-412 .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#673ab7;border-width:5px 5px 0}.factory-bootstrap-412 .tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#673ab7;border-width:5px 5px 0}.factory-bootstrap-412 .tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#673ab7;border-width:5px 5px 0}.factory-bootstrap-412 .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#673ab7;border-width:5px 5px 5px 0}.factory-bootstrap-412 .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#673ab7;border-width:5px 0 5px 5px}.factory-bootstrap-412 .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#673ab7;border-width:0 5px 5px}.factory-bootstrap-412 .tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#673ab7;border-width:0 5px 5px}.factory-bootstrap-412 .tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#673ab7;border-width:0 5px 5px}.factory-bootstrap-412 .popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);background-clip:padding-box}.factory-bootstrap-412 .popover.top{margin-top:-10px}.factory-bootstrap-412 .popover.right{margin-left:10px}.factory-bootstrap-412 .popover.bottom{margin-top:10px}.factory-bootstrap-412 .popover.left{margin-left:-10px}.factory-bootstrap-412 .popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.factory-bootstrap-412 .popover-content{padding:9px 14px}.factory-bootstrap-412 .popover .arrow,.factory-bootstrap-412 .popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.factory-bootstrap-412 .popover .arrow{border-width:11px}.factory-bootstrap-412 .popover .arrow:after{border-width:10px;content:""}.factory-bootstrap-412 .popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.factory-bootstrap-412 .popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.factory-bootstrap-412 .popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.factory-bootstrap-412 .popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.factory-bootstrap-412 .popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);border-top-width:0}.factory-bootstrap-412 .popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.factory-bootstrap-412 .popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,.25);border-right-width:0}.factory-bootstrap-412 .popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.factory-bootstrap-412 .carousel{position:relative}.factory-bootstrap-412 .carousel-inner{position:relative;width:100%;overflow:hidden}.factory-bootstrap-412 .carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.factory-bootstrap-412 .carousel-inner>.item>a>img,.factory-bootstrap-412 .carousel-inner>.item>img{display:block;height:auto;max-width:100%;line-height:1}.factory-bootstrap-412 .carousel-inner>.active,.factory-bootstrap-412 .carousel-inner>.next,.factory-bootstrap-412 .carousel-inner>.prev{display:block}.factory-bootstrap-412 .carousel-inner>.active{left:0}.factory-bootstrap-412 .carousel-inner>.next,.factory-bootstrap-412 .carousel-inner>.prev{position:absolute;top:0;width:100%}.factory-bootstrap-412 .carousel-inner>.next{left:100%}.factory-bootstrap-412 .carousel-inner>.prev{left:-100%}.factory-bootstrap-412 .carousel-inner>.next.left,.factory-bootstrap-412 .carousel-inner>.prev.right{left:0}.factory-bootstrap-412 .carousel-inner>.active.left{left:-100%}.factory-bootstrap-412 .carousel-inner>.active.right{left:100%}.factory-bootstrap-412 .carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);opacity:.5;filter:alpha(opacity=50)}.factory-bootstrap-412 .carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.factory-bootstrap-412 .carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.factory-bootstrap-412 .carousel-control:focus,.factory-bootstrap-412 .carousel-control:hover{color:#fff;text-decoration:none;outline:0;opacity:.9;filter:alpha(opacity=90)}.factory-bootstrap-412 .carousel-control .glyphicon-chevron-left,.factory-bootstrap-412 .carousel-control .glyphicon-chevron-right,.factory-bootstrap-412 .carousel-control .icon-next,.factory-bootstrap-412 .carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.factory-bootstrap-412 .carousel-control .glyphicon-chevron-left,.factory-bootstrap-412 .carousel-control .icon-prev{left:50%}.factory-bootstrap-412 .carousel-control .glyphicon-chevron-right,.factory-bootstrap-412 .carousel-control .icon-next{right:50%}.factory-bootstrap-412 .carousel-control .icon-next,.factory-bootstrap-412 .carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.factory-bootstrap-412 .carousel-control .icon-prev:before{content:'\2039'}.factory-bootstrap-412 .carousel-control .icon-next:before{content:'\203a'}.factory-bootstrap-412 .carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.factory-bootstrap-412 .carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.factory-bootstrap-412 .carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.factory-bootstrap-412 .carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.factory-bootstrap-412 .carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.factory-bootstrap-412 .clearfix:after,.factory-bootstrap-412 .clearfix:before{display:table;content:" "}.factory-bootstrap-412 .clearfix:after{clear:both}.factory-bootstrap-412 .center-block{display:block;margin-right:auto;margin-left:auto}.factory-bootstrap-412 .pull-right{float:right!important}.factory-bootstrap-412 .pull-left{float:left!important}.factory-bootstrap-412 .hide{display:none!important}.factory-bootstrap-412 .show{display:block!important}.factory-bootstrap-412 .invisible{visibility:hidden}.factory-bootstrap-412 .text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.factory-bootstrap-412 .hidden{display:none!important;visibility:hidden!important}.factory-bootstrap-412 .affix{position:fixed}@-ms-viewport{width:device-width}.factory-bootstrap-412 .visible-lg,.factory-bootstrap-412 .visible-md,.factory-bootstrap-412 .visible-sm,.factory-bootstrap-412 .visible-xs,.factory-bootstrap-412 td.visible-lg,.factory-bootstrap-412 td.visible-md,.factory-bootstrap-412 td.visible-sm,.factory-bootstrap-412 td.visible-xs,.factory-bootstrap-412 th.visible-lg,.factory-bootstrap-412 th.visible-md,.factory-bootstrap-412 th.visible-sm,.factory-bootstrap-412 th.visible-xs,.factory-bootstrap-412 tr.visible-lg,.factory-bootstrap-412 tr.visible-md,.factory-bootstrap-412 tr.visible-sm,.factory-bootstrap-412 tr.visible-xs{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}table.visible-xs.visible-sm{display:table}tr.visible-xs.visible-sm{display:table-row!important}td.visible-xs.visible-sm,th.visible-xs.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}table.visible-xs.visible-md{display:table}tr.visible-xs.visible-md{display:table-row!important}td.visible-xs.visible-md,th.visible-xs.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-xs.visible-lg{display:block!important}table.visible-xs.visible-lg{display:table}tr.visible-xs.visible-lg{display:table-row!important}td.visible-xs.visible-lg,th.visible-xs.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-sm.visible-xs{display:block!important}table.visible-sm.visible-xs{display:table}tr.visible-sm.visible-xs{display:table-row!important}td.visible-sm.visible-xs,th.visible-sm.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}table.visible-sm.visible-md{display:table}tr.visible-sm.visible-md{display:table-row!important}td.visible-sm.visible-md,th.visible-sm.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-sm.visible-lg{display:block!important}table.visible-sm.visible-lg{display:table}tr.visible-sm.visible-lg{display:table-row!important}td.visible-sm.visible-lg,th.visible-sm.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-md.visible-xs{display:block!important}table.visible-md.visible-xs{display:table}tr.visible-md.visible-xs{display:table-row!important}td.visible-md.visible-xs,th.visible-md.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}table.visible-md.visible-sm{display:table}tr.visible-md.visible-sm{display:table-row!important}td.visible-md.visible-sm,th.visible-md.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-md.visible-lg{display:block!important}table.visible-md.visible-lg{display:table}tr.visible-md.visible-lg{display:table-row!important}td.visible-md.visible-lg,th.visible-md.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-lg.visible-xs{display:block!important}table.visible-lg.visible-xs{display:table}tr.visible-lg.visible-xs{display:table-row!important}td.visible-lg.visible-xs,th.visible-lg.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}table.visible-lg.visible-sm{display:table}tr.visible-lg.visible-sm{display:table-row!important}td.visible-lg.visible-sm,th.visible-lg.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}table.visible-lg.visible-md{display:table}tr.visible-lg.visible-md{display:table-row!important}td.visible-lg.visible-md,th.visible-lg.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}.factory-bootstrap-412 .hidden-xs{display:block!important}.factory-bootstrap-412 table.hidden-xs{display:table}.factory-bootstrap-412 tr.hidden-xs{display:table-row!important}.factory-bootstrap-412 td.hidden-xs,.factory-bootstrap-412 th.hidden-xs{display:table-cell!important}@media (max-width:767px){.hidden-xs,td.hidden-xs,th.hidden-xs,tr.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,td.hidden-xs.hidden-md,th.hidden-xs.hidden-md,tr.hidden-xs.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg{display:none!important}}.factory-bootstrap-412 .hidden-sm{display:block!important}.factory-bootstrap-412 table.hidden-sm{display:table}.factory-bootstrap-412 tr.hidden-sm{display:table-row!important}.factory-bootstrap-412 td.hidden-sm,.factory-bootstrap-412 th.hidden-sm{display:table-cell!important}@media (max-width:767px){.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm,td.hidden-sm,th.hidden-sm,tr.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,td.hidden-sm.hidden-md,th.hidden-sm.hidden-md,tr.hidden-sm.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg{display:none!important}}.factory-bootstrap-412 .hidden-md{display:block!important}.factory-bootstrap-412 table.hidden-md{display:table}.factory-bootstrap-412 tr.hidden-md{display:table-row!important}.factory-bootstrap-412 td.hidden-md,.factory-bootstrap-412 th.hidden-md{display:table-cell!important}@media (max-width:767px){.hidden-md.hidden-xs,td.hidden-md.hidden-xs,th.hidden-md.hidden-xs,tr.hidden-md.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,td.hidden-md.hidden-sm,th.hidden-md.hidden-sm,tr.hidden-md.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md,td.hidden-md,th.hidden-md,tr.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-md.hidden-lg,td.hidden-md.hidden-lg,th.hidden-md.hidden-lg,tr.hidden-md.hidden-lg{display:none!important}}.factory-bootstrap-412 .hidden-lg{display:block!important}.factory-bootstrap-412 table.hidden-lg{display:table}.factory-bootstrap-412 tr.hidden-lg{display:table-row!important}.factory-bootstrap-412 td.hidden-lg,.factory-bootstrap-412 th.hidden-lg{display:table-cell!important}@media (max-width:767px){.factory-bootstrap-412 .hidden-lg.hidden-xs,.factory-bootstrap-412 td.hidden-lg.hidden-xs,.factory-bootstrap-412 th.hidden-lg.hidden-xs,.factory-bootstrap-412 tr.hidden-lg.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.factory-bootstrap-412 .hidden-lg.hidden-sm,.factory-bootstrap-412 td.hidden-lg.hidden-sm,.factory-bootstrap-412 th.hidden-lg.hidden-sm,.factory-bootstrap-412 tr.hidden-lg.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.factory-bootstrap-412 .hidden-lg.hidden-md,.factory-bootstrap-412 td.hidden-lg.hidden-md,.factory-bootstrap-412 th.hidden-lg.hidden-md,.factory-bootstrap-412 tr.hidden-lg.hidden-md{display:none!important}}@media (min-width:1200px){.factory-bootstrap-412 .hidden-lg,.factory-bootstrap-412 td.hidden-lg,.factory-bootstrap-412 th.hidden-lg,.factory-bootstrap-412 tr.hidden-lg{display:none!important}}.factory-bootstrap-412 .visible-print,.factory-bootstrap-412 td.visible-print,.factory-bootstrap-412 th.visible-print,.factory-bootstrap-412 tr.visible-print{display:none!important}@media print{.factory-bootstrap-412 .visible-print{display:block!important}.factory-bootstrap-412 table.visible-print{display:table}.factory-bootstrap-412 tr.visible-print{display:table-row!important}.factory-bootstrap-412 td.visible-print,.factory-bootstrap-412 th.visible-print{display:table-cell!important}.factory-bootstrap-412 .hidden-print,.factory-bootstrap-412 td.hidden-print,.factory-bootstrap-412 th.hidden-print,.factory-bootstrap-412 tr.hidden-print{display:none!important}}/*!
12
  * Factory Default Bootstrap Theme
13
  *
14
  * The code is based on Bootstrap v2.1.1
@@ -22,4 +22,4 @@
22
  *
23
  * @package factory-bootstrap
24
  * @since 1.0.0
25
- */.factory-bootstrap-412 .btn-danger,.factory-bootstrap-412 .btn-default,.factory-bootstrap-412 .btn-info,.factory-bootstrap-412 .btn-primary,.factory-bootstrap-412 .btn-success,.factory-bootstrap-412 .btn-warning{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-412 .btn-danger.active,.factory-bootstrap-412 .btn-danger:active,.factory-bootstrap-412 .btn-default.active,.factory-bootstrap-412 .btn-default:active,.factory-bootstrap-412 .btn-info.active,.factory-bootstrap-412 .btn-info:active,.factory-bootstrap-412 .btn-primary.active,.factory-bootstrap-412 .btn-primary:active,.factory-bootstrap-412 .btn-success.active,.factory-bootstrap-412 .btn-success:active,.factory-bootstrap-412 .btn-warning.active,.factory-bootstrap-412 .btn-warning:active{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.1);box-shadow:inset 0 1px 1px rgba(0,0,0,.1)}.factory-bootstrap-412 .btn.active,.factory-bootstrap-412 .btn:active{background-image:none}.factory-bootstrap-412 .btn-default{color:#555;border-color:#ccc;background:#f7f7f7;-webkit-box-shadow:inset 0 1px 0 #fff,0 1px 0 rgba(0,0,0,.08);box-shadow:inset 0 1px 0 #fff,0 1px 0 rgba(0,0,0,.08);vertical-align:top}.factory-bootstrap-412 .btn-default.active,.factory-bootstrap-412 .btn-default:active{background-color:#fff;border-color:#dbdbdb}.factory-bootstrap-412 .btn-gold{font-weight:700;padding:7px 12px;cursor:pointer;line-height:16px;display:inline-block;border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px;box-shadow:#e3e3e3 0 1px 1px;-moz-box-shadow:0 1px 1px rgba(000,000,000,.1),inset 0 1px 1px rgba(255,255,255,.7);-webkit-box-shadow:0 1px 1px rgba(000,000,000,.1),inset 0 1px 1px rgba(255,255,255,.7);text-shadow:1px 1px 0 #ffe8b2;color:#7c5d1b;border:1px solid #d6a437;background:#feeb80}.factory-bootstrap-412 .btn-gold:focus,.factory-bootstrap-412 .btn-gold:hover{background:#fef0a1}.factory-bootstrap-412 .btn-gold.active,.factory-bootstrap-412 .btn-gold:active{background:#fef0a1;-webkit-box-shadow:inset 0 3px 8px 0 #f8ba36;box-shadow:inset 0 3px 8px 0 #f8ba36}.factory-bootstrap-412 .btn-primary{background:#2ea2cc;border-color:#0074a2;-webkit-box-shadow:inset 0 1px 0 rgba(120,200,230,.5),0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 rgba(120,200,230,.5),0 1px 0 rgba(0,0,0,.15);color:#fff;text-decoration:none}.factory-bootstrap-412 .btn-primary:focus,.factory-bootstrap-412 .btn-primary:hover{background:#1e8cbe;border-color:#0074a2;-webkit-box-shadow:inset 0 1px 0 rgba(120,200,230,.6);box-shadow:inset 0 1px 0 rgba(120,200,230,.6);color:#fff}.factory-bootstrap-412 .btn-primary.active,.factory-bootstrap-412 .btn-primary:active{background-color:#2d6ca2;border-color:#2b669a}.factory-bootstrap-412 .btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);background-repeat:repeat-x;border-color:#3e8f3e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-412 .btn-success:focus,.factory-bootstrap-412 .btn-success:hover{background-color:#419641;background-position:0 -15px}.factory-bootstrap-412 .btn-success.active,.factory-bootstrap-412 .btn-success:active{background-color:#419641;border-color:#3e8f3e}.factory-bootstrap-412 .btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);background-repeat:repeat-x;border-color:#e38d13;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-412 .btn-warning:focus,.factory-bootstrap-412 .btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.factory-bootstrap-412 .btn-warning.active,.factory-bootstrap-412 .btn-warning:active{background-color:#eb9316;border-color:#e38d13}.factory-bootstrap-412 .btn-danger{color:#fff;background:#d9534f;border-color:#d43f3a}.factory-bootstrap-412 .btn-danger.active,.factory-bootstrap-412 .btn-danger:active,.factory-bootstrap-412 .btn-danger:focus,.factory-bootstrap-412 .btn-danger:hover,.factory-bootstrap-412 .open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.factory-bootstrap-412 .btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);background-repeat:repeat-x;border-color:#28a4c9;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-412 .btn-info:focus,.factory-bootstrap-412 .btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.factory-bootstrap-412 .btn-info.active,.factory-bootstrap-412 .btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.factory-bootstrap-412 .img-thumbnail,.factory-bootstrap-412 .thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.factory-bootstrap-412 .dropdown-menu>li>a:focus,.factory-bootstrap-412 .dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.factory-bootstrap-412 .dropdown-menu>.active>a,.factory-bootstrap-412 .dropdown-menu>.active>a:focus,.factory-bootstrap-412 .dropdown-menu>.active>a:hover{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.factory-bootstrap-412 .navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.factory-bootstrap-412 .navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.factory-bootstrap-412 .navbar-brand,.factory-bootstrap-412 .navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.factory-bootstrap-412 .navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-412 .navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.factory-bootstrap-412 .navbar-inverse .navbar-brand,.factory-bootstrap-412 .navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.factory-bootstrap-412 .navbar-fixed-bottom,.factory-bootstrap-412 .navbar-fixed-top,.factory-bootstrap-412 .navbar-static-top{border-radius:0}.factory-bootstrap-412 .alert{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.factory-bootstrap-412 .alert .actions{padding-top:10px}.factory-bootstrap-412 .alert-success{color:#3c763d;background-color:#dff0d8;border-bottom:2px solid #c8e5bc}.factory-bootstrap-412 .alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0)}.factory-bootstrap-412 .alert{text-shadow:none;box-shadow:none;margin:0;margin-top:10px;margin-bottom:10px;padding:10px}.factory-bootstrap-412 .alert-normal,.factory-bootstrap-412 .alert-warning{background:#fcf8e3;color:#8a6d3b;border:1px solid #b8823b}.factory-bootstrap-412 .alert-danger{background:#cf4944;color:#fff;border-bottom:2px solid #b23e3a}.factory-bootstrap-412 .alert-danger a:not(.btn),.factory-bootstrap-412 .alert-error a:not(.btn){color:#fff}.factory-bootstrap-412 .progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.factory-bootstrap-412 .progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.factory-bootstrap-412 .progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.factory-bootstrap-412 .progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.factory-bootstrap-412 .progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.factory-bootstrap-412 .progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.factory-bootstrap-412 .list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.factory-bootstrap-412 .list-group-item.active,.factory-bootstrap-412 .list-group-item.active:focus,.factory-bootstrap-412 .list-group-item.active:hover{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0)}.factory-bootstrap-412 .panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.factory-bootstrap-412 .panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.factory-bootstrap-412 .panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.factory-bootstrap-412 .panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.factory-bootstrap-412 .panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.factory-bootstrap-412 .panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.factory-bootstrap-412 .panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.factory-bootstrap-412 .well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}.factory-bootstrap-412 .factory-after{margin-left:7px;display:inline-block}.factory-bootstrap-412 .factory-hidden{display:none}.factory-bootstrap-412 .factory-ajax-loader{width:25px;height:25px;background:url(../assets/images/loader-sm-tr.gif)}.factory-control-error{background-color:rgba(0,0,0,.8);white-space:normal;z-index:10;font-weight:400;line-height:150%;border-radius:4px;color:#fff;font-size:13px;margin-top:5px;padding:4px 10px 3px;max-width:500px;display:inline-block}.factory-control-error i{margin:0 7px 0 1px}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 article,.factory-bootstrap-425 aside,.factory-bootstrap-425 details,.factory-bootstrap-425 figcaption,.factory-bootstrap-425 figure,.factory-bootstrap-425 footer,.factory-bootstrap-425 header,.factory-bootstrap-425 hgroup,.factory-bootstrap-425 main,.factory-bootstrap-425 nav,.factory-bootstrap-425 section,.factory-bootstrap-425 summary{display:block}.factory-bootstrap-425 audio,.factory-bootstrap-425 canvas,.factory-bootstrap-425 video{display:inline-block}.factory-bootstrap-425 audio:not([controls]){display:none;height:0}.factory-bootstrap-425 [hidden],.factory-bootstrap-425 template{display:none}.factory-bootstrap-425 body{margin:0}.factory-bootstrap-425 a{background:0 0}.factory-bootstrap-425 a:focus{outline:thin dotted}.factory-bootstrap-425 a:active,.factory-bootstrap-425 a:hover{outline:0}.factory-bootstrap-425 h1{margin:.67em 0}.factory-bootstrap-425 b,.factory-bootstrap-425 strong{font-weight:700}.factory-bootstrap-425 dfn{font-style:italic}.factory-bootstrap-425 hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}.factory-bootstrap-425 mark{color:#000;background:#ff0}.factory-bootstrap-425 code,.factory-bootstrap-425 kbd,.factory-bootstrap-425 pre,.factory-bootstrap-425 samp{font-size:1em}.factory-bootstrap-425 pre{white-space:pre-wrap}.factory-bootstrap-425 q{quotes:"\201C" "\201D" "\2018" "\2019"}.factory-bootstrap-425 sub,.factory-bootstrap-425 sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}.factory-bootstrap-425 sup{top:-.5em}.factory-bootstrap-425 sub{bottom:-.25em}.factory-bootstrap-425 img{border:0}.factory-bootstrap-425 svg:not(:root){overflow:hidden}.factory-bootstrap-425 figure{margin:0}.factory-bootstrap-425 button,.factory-bootstrap-425 input,.factory-bootstrap-425 select,.factory-bootstrap-425 textarea{margin:0}.factory-bootstrap-425 button,.factory-bootstrap-425 select{text-transform:none}.factory-bootstrap-425 select{padding-right:4px!important}.factory-bootstrap-425 button,.factory-bootstrap-425 input[type=reset],.factory-bootstrap-425 input[type=submit],html .factory-bootstrap-425 input[type=button]{cursor:pointer;-webkit-appearance:button}.factory-bootstrap-425 button[disabled],html .factory-bootstrap-425 input[disabled]{cursor:default}.factory-bootstrap-425 input[type=checkbox],.factory-bootstrap-425 input[type=radio]{padding:0;box-sizing:border-box}.factory-bootstrap-425 input[type=search]{-webkit-appearance:textfield}.factory-bootstrap-425 input[type=search]::-webkit-search-cancel-button,.factory-bootstrap-425 input[type=search]::-webkit-search-decoration{-webkit-appearance:none}.factory-bootstrap-425 button::-moz-focus-inner,.factory-bootstrap-425 input::-moz-focus-inner{padding:0;border:0}.factory-bootstrap-425 textarea{overflow:auto;vertical-align:top}.factory-bootstrap-425 table{border-collapse:collapse;border-spacing:0}@media print{.factory-bootstrap-425 *{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}.factory-bootstrap-425 a,.factory-bootstrap-425 a:visited{text-decoration:underline}.factory-bootstrap-425 a[href]:after{content:" (" attr(href) ")"}.factory-bootstrap-425 abbr[title]:after{content:" (" attr(title) ")"}.factory-bootstrap-425 a[href^="javascript:"]:after,.factory-bootstrap-425 a[href^="#"]:after{content:""}.factory-bootstrap-425 blockquote,.factory-bootstrap-425 pre{border:1px solid #999;page-break-inside:avoid}.factory-bootstrap-425 thead{display:table-header-group}.factory-bootstrap-425 img,.factory-bootstrap-425 tr{page-break-inside:avoid}.factory-bootstrap-425 img{max-width:100%!important}@page{margin:2cm .5cm}.factory-bootstrap-425 h2,.factory-bootstrap-425 h3,.factory-bootstrap-425 p{orphans:3;widows:3}.factory-bootstrap-425 h2,.factory-bootstrap-425 h3{page-break-after:avoid}.factory-bootstrap-425 select{background:#fff!important}.factory-bootstrap-425 .navbar{display:none}.factory-bootstrap-425 .table td,.factory-bootstrap-425 .table th{background-color:#fff!important}.factory-bootstrap-425 .btn>.caret,.factory-bootstrap-425 .dropup>.btn>.caret{border-top-color:#000!important}.factory-bootstrap-425 .label{border:1px solid #000}.factory-bootstrap-425 .table{border-collapse:collapse!important}.factory-bootstrap-425 .table-bordered td,.factory-bootstrap-425 .table-bordered th{border:1px solid #ddd!important}}.factory-bootstrap-425 *,.factory-bootstrap-425 :after,.factory-bootstrap-425 :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html .factory-bootstrap-425{-webkit-tap-highlight-color:rgba(0,0,0,0)}.factory-bootstrap-425 body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}.factory-bootstrap-425 button,.factory-bootstrap-425 input,.factory-bootstrap-425 select,.factory-bootstrap-425 textarea{font-family:inherit;font-size:inherit;line-height:inherit}.factory-bootstrap-425 img{vertical-align:middle}.factory-bootstrap-425 .img-responsive{display:block;height:auto;max-width:100%}.factory-bootstrap-425 .img-rounded{border-radius:6px}.factory-bootstrap-425 .img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.factory-bootstrap-425 .img-circle{border-radius:50%}.factory-bootstrap-425 hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.factory-bootstrap-425 .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.factory-bootstrap-425 .h1,.factory-bootstrap-425 .h2,.factory-bootstrap-425 .h3,.factory-bootstrap-425 .h4,.factory-bootstrap-425 .h5,.factory-bootstrap-425 .h6,.factory-bootstrap-425 h1,.factory-bootstrap-425 h2,.factory-bootstrap-425 h3,.factory-bootstrap-425 h4,.factory-bootstrap-425 h5,.factory-bootstrap-425 h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit}.factory-bootstrap-425 .h1 .small,.factory-bootstrap-425 .h1 small,.factory-bootstrap-425 .h2 .small,.factory-bootstrap-425 .h2 small,.factory-bootstrap-425 .h3 .small,.factory-bootstrap-425 .h3 small,.factory-bootstrap-425 .h4 .small,.factory-bootstrap-425 .h4 small,.factory-bootstrap-425 .h5 .small,.factory-bootstrap-425 .h5 small,.factory-bootstrap-425 .h6 .small,.factory-bootstrap-425 .h6 small,.factory-bootstrap-425 h1 .small,.factory-bootstrap-425 h1 small,.factory-bootstrap-425 h2 .small,.factory-bootstrap-425 h2 small,.factory-bootstrap-425 h3 .small,.factory-bootstrap-425 h3 small,.factory-bootstrap-425 h4 .small,.factory-bootstrap-425 h4 small,.factory-bootstrap-425 h5 .small,.factory-bootstrap-425 h5 small,.factory-bootstrap-425 h6 .small,.factory-bootstrap-425 h6 small{font-weight:400;line-height:1;color:#999}.factory-bootstrap-425 h1,.factory-bootstrap-425 h2,.factory-bootstrap-425 h3{margin-top:20px;margin-bottom:10px}.factory-bootstrap-425 h1 .small,.factory-bootstrap-425 h1 small,.factory-bootstrap-425 h2 .small,.factory-bootstrap-425 h2 small,.factory-bootstrap-425 h3 .small,.factory-bootstrap-425 h3 small{font-size:65%}.factory-bootstrap-425 h4,.factory-bootstrap-425 h5,.factory-bootstrap-425 h6{margin-top:10px;margin-bottom:10px}.factory-bootstrap-425 h4 .small,.factory-bootstrap-425 h4 small,.factory-bootstrap-425 h5 .small,.factory-bootstrap-425 h5 small,.factory-bootstrap-425 h6 .small,.factory-bootstrap-425 h6 small{font-size:75%}.factory-bootstrap-425 .h1,.factory-bootstrap-425 h1{font-size:36px}.factory-bootstrap-425 .h2,.factory-bootstrap-425 h2{font-size:30px}.factory-bootstrap-425 .h3,.factory-bootstrap-425 h3{font-size:24px}.factory-bootstrap-425 .h4,.factory-bootstrap-425 h4{font-size:18px}.factory-bootstrap-425 .h5,.factory-bootstrap-425 h5{font-size:14px}.factory-bootstrap-425 .h6,.factory-bootstrap-425 h6{font-size:12px}.factory-bootstrap-425 p{margin:0 0 10px}.factory-bootstrap-425 .lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.factory-bootstrap-425 .small,.factory-bootstrap-425 small{font-size:85%}.factory-bootstrap-425 cite{font-style:normal}.factory-bootstrap-425 .text-muted{color:#999}.factory-bootstrap-425 .text-primary{color:#428bca}.factory-bootstrap-425 .text-primary:hover{color:#3071a9}.factory-bootstrap-425 .text-warning{color:#8a6d3b}.factory-bootstrap-425 .text-warning:hover{color:#66512c}.factory-bootstrap-425 .text-danger{color:#a94442}.factory-bootstrap-425 .text-danger:hover{color:#843534}.factory-bootstrap-425 .text-success{color:#3c763d}.factory-bootstrap-425 .text-success:hover{color:#2b542c}.factory-bootstrap-425 .text-info{color:#31708f}.factory-bootstrap-425 .text-info:hover{color:#245269}.factory-bootstrap-425 .text-left{text-align:left}.factory-bootstrap-425 .text-right{text-align:right}.factory-bootstrap-425 .text-center{text-align:center}.factory-bootstrap-425 .page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}.factory-bootstrap-425 ol,.factory-bootstrap-425 ul{margin-top:0;margin-bottom:10px}.factory-bootstrap-425 ol ol,.factory-bootstrap-425 ol ul,.factory-bootstrap-425 ul ol,.factory-bootstrap-425 ul ul{margin-bottom:0}.factory-bootstrap-425 .list-inline,.factory-bootstrap-425 .list-unstyled{padding-left:0;list-style:none}.factory-bootstrap-425 .list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.factory-bootstrap-425 .list-inline>li:first-child{padding-left:0}.factory-bootstrap-425 dl{margin-top:0;margin-bottom:20px}.factory-bootstrap-425 dd,.factory-bootstrap-425 dt{line-height:1.428571429}.factory-bootstrap-425 dt{font-weight:700}.factory-bootstrap-425 dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:after,.dl-horizontal dd:before{display:table;content:" "}.dl-horizontal dd:after{clear:both}}.factory-bootstrap-425 abbr[data-original-title],.factory-bootstrap-425 abbr[title]{cursor:help;border-bottom:1px dotted #999}.factory-bootstrap-425 .initialism{font-size:90%;text-transform:uppercase}.factory-bootstrap-425 blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}.factory-bootstrap-425 blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}.factory-bootstrap-425 blockquote p:last-child{margin-bottom:0}.factory-bootstrap-425 blockquote .small,.factory-bootstrap-425 blockquote small{display:block;line-height:1.428571429;color:#999}.factory-bootstrap-425 blockquote .small:before,.factory-bootstrap-425 blockquote small:before{content:'\2014 \00A0'}.factory-bootstrap-425 blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}.factory-bootstrap-425 blockquote.pull-right .small,.factory-bootstrap-425 blockquote.pull-right p,.factory-bootstrap-425 blockquote.pull-right small{text-align:right}.factory-bootstrap-425 blockquote.pull-right .small:before,.factory-bootstrap-425 blockquote.pull-right small:before{content:''}.factory-bootstrap-425 blockquote.pull-right .small:after,.factory-bootstrap-425 blockquote.pull-right small:after{content:'\00A0 \2014'}.factory-bootstrap-425 blockquote:after,.factory-bootstrap-425 blockquote:before{content:""}.factory-bootstrap-425 address{margin-bottom:20px;font-style:normal;line-height:1.428571429}.factory-bootstrap-425 code,.factory-bootstrap-425 kbd,.factory-bootstrap-425 pre,.factory-bootstrap-425 samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}.factory-bootstrap-425 code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}.factory-bootstrap-425 pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}.factory-bootstrap-425 pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.factory-bootstrap-425 .pre-scrollable{max-height:340px;overflow-y:scroll}.factory-bootstrap-425 .container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.factory-bootstrap-425 .container:after,.factory-bootstrap-425 .container:before{display:table;content:" "}.factory-bootstrap-425 .container:after{clear:both}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.factory-bootstrap-425 .row{margin-right:-15px;margin-left:-15px}.factory-bootstrap-425 .row:after,.factory-bootstrap-425 .row:before{display:table;content:" "}.factory-bootstrap-425 .row:after{clear:both}.factory-bootstrap-425 .col-lg-1,.factory-bootstrap-425 .col-lg-10,.factory-bootstrap-425 .col-lg-11,.factory-bootstrap-425 .col-lg-12,.factory-bootstrap-425 .col-lg-2,.factory-bootstrap-425 .col-lg-3,.factory-bootstrap-425 .col-lg-4,.factory-bootstrap-425 .col-lg-5,.factory-bootstrap-425 .col-lg-6,.factory-bootstrap-425 .col-lg-7,.factory-bootstrap-425 .col-lg-8,.factory-bootstrap-425 .col-lg-9,.factory-bootstrap-425 .col-md-1,.factory-bootstrap-425 .col-md-10,.factory-bootstrap-425 .col-md-11,.factory-bootstrap-425 .col-md-12,.factory-bootstrap-425 .col-md-2,.factory-bootstrap-425 .col-md-3,.factory-bootstrap-425 .col-md-4,.factory-bootstrap-425 .col-md-5,.factory-bootstrap-425 .col-md-6,.factory-bootstrap-425 .col-md-7,.factory-bootstrap-425 .col-md-8,.factory-bootstrap-425 .col-md-9,.factory-bootstrap-425 .col-sm-1,.factory-bootstrap-425 .col-sm-10,.factory-bootstrap-425 .col-sm-11,.factory-bootstrap-425 .col-sm-12,.factory-bootstrap-425 .col-sm-2,.factory-bootstrap-425 .col-sm-3,.factory-bootstrap-425 .col-sm-4,.factory-bootstrap-425 .col-sm-5,.factory-bootstrap-425 .col-sm-6,.factory-bootstrap-425 .col-sm-7,.factory-bootstrap-425 .col-sm-8,.factory-bootstrap-425 .col-sm-9,.factory-bootstrap-425 .col-xs-1,.factory-bootstrap-425 .col-xs-10,.factory-bootstrap-425 .col-xs-11,.factory-bootstrap-425 .col-xs-12,.factory-bootstrap-425 .col-xs-2,.factory-bootstrap-425 .col-xs-3,.factory-bootstrap-425 .col-xs-4,.factory-bootstrap-425 .col-xs-5,.factory-bootstrap-425 .col-xs-6,.factory-bootstrap-425 .col-xs-7,.factory-bootstrap-425 .col-xs-8,.factory-bootstrap-425 .col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.factory-bootstrap-425 .col-xs-1,.factory-bootstrap-425 .col-xs-10,.factory-bootstrap-425 .col-xs-11,.factory-bootstrap-425 .col-xs-12,.factory-bootstrap-425 .col-xs-2,.factory-bootstrap-425 .col-xs-3,.factory-bootstrap-425 .col-xs-4,.factory-bootstrap-425 .col-xs-5,.factory-bootstrap-425 .col-xs-6,.factory-bootstrap-425 .col-xs-7,.factory-bootstrap-425 .col-xs-8,.factory-bootstrap-425 .col-xs-9{float:left}.factory-bootstrap-425 .col-xs-12{width:100%}.factory-bootstrap-425 .col-xs-11{width:91.66666666666666%}.factory-bootstrap-425 .col-xs-10{width:83.33333333333334%}.factory-bootstrap-425 .col-xs-9{width:75%}.factory-bootstrap-425 .col-xs-8{width:66.66666666666666%}.factory-bootstrap-425 .col-xs-7{width:58.333333333333336%}.factory-bootstrap-425 .col-xs-6{width:50%}.factory-bootstrap-425 .col-xs-5{width:41.66666666666667%}.factory-bootstrap-425 .col-xs-4{width:33.33333333333333%}.factory-bootstrap-425 .col-xs-3{width:25%}.factory-bootstrap-425 .col-xs-2{width:16.666666666666664%}.factory-bootstrap-425 .col-xs-1{width:8.333333333333332%}.factory-bootstrap-425 .col-xs-pull-12{right:100%}.factory-bootstrap-425 .col-xs-pull-11{right:91.66666666666666%}.factory-bootstrap-425 .col-xs-pull-10{right:83.33333333333334%}.factory-bootstrap-425 .col-xs-pull-9{right:75%}.factory-bootstrap-425 .col-xs-pull-8{right:66.66666666666666%}.factory-bootstrap-425 .col-xs-pull-7{right:58.333333333333336%}.factory-bootstrap-425 .col-xs-pull-6{right:50%}.factory-bootstrap-425 .col-xs-pull-5{right:41.66666666666667%}.factory-bootstrap-425 .col-xs-pull-4{right:33.33333333333333%}.factory-bootstrap-425 .col-xs-pull-3{right:25%}.factory-bootstrap-425 .col-xs-pull-2{right:16.666666666666664%}.factory-bootstrap-425 .col-xs-pull-1{right:8.333333333333332%}.factory-bootstrap-425 .col-xs-pull-0{right:0}.factory-bootstrap-425 .col-xs-push-12{left:100%}.factory-bootstrap-425 .col-xs-push-11{left:91.66666666666666%}.factory-bootstrap-425 .col-xs-push-10{left:83.33333333333334%}.factory-bootstrap-425 .col-xs-push-9{left:75%}.factory-bootstrap-425 .col-xs-push-8{left:66.66666666666666%}.factory-bootstrap-425 .col-xs-push-7{left:58.333333333333336%}.factory-bootstrap-425 .col-xs-push-6{left:50%}.factory-bootstrap-425 .col-xs-push-5{left:41.66666666666667%}.factory-bootstrap-425 .col-xs-push-4{left:33.33333333333333%}.factory-bootstrap-425 .col-xs-push-3{left:25%}.factory-bootstrap-425 .col-xs-push-2{left:16.666666666666664%}.factory-bootstrap-425 .col-xs-push-1{left:8.333333333333332%}.factory-bootstrap-425 .col-xs-push-0{left:0}.factory-bootstrap-425 .col-xs-offset-12{margin-left:100%}.factory-bootstrap-425 .col-xs-offset-11{margin-left:91.66666666666666%}.factory-bootstrap-425 .col-xs-offset-10{margin-left:83.33333333333334%}.factory-bootstrap-425 .col-xs-offset-9{margin-left:75%}.factory-bootstrap-425 .col-xs-offset-8{margin-left:66.66666666666666%}.factory-bootstrap-425 .col-xs-offset-7{margin-left:58.333333333333336%}.factory-bootstrap-425 .col-xs-offset-6{margin-left:50%}.factory-bootstrap-425 .col-xs-offset-5{margin-left:41.66666666666667%}.factory-bootstrap-425 .col-xs-offset-4{margin-left:33.33333333333333%}.factory-bootstrap-425 .col-xs-offset-3{margin-left:25%}.factory-bootstrap-425 .col-xs-offset-2{margin-left:16.666666666666664%}.factory-bootstrap-425 .col-xs-offset-1{margin-left:8.333333333333332%}.factory-bootstrap-425 .col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}.factory-bootstrap-425 table{max-width:100%;background-color:transparent}.factory-bootstrap-425 th{text-align:left}.factory-bootstrap-425 .table{width:100%;margin-bottom:20px}.factory-bootstrap-425 .table>tbody>tr>td,.factory-bootstrap-425 .table>tbody>tr>th,.factory-bootstrap-425 .table>tfoot>tr>td,.factory-bootstrap-425 .table>tfoot>tr>th,.factory-bootstrap-425 .table>thead>tr>td,.factory-bootstrap-425 .table>thead>tr>th{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.factory-bootstrap-425 .table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.factory-bootstrap-425 .table>caption+thead>tr:first-child>td,.factory-bootstrap-425 .table>caption+thead>tr:first-child>th,.factory-bootstrap-425 .table>colgroup+thead>tr:first-child>td,.factory-bootstrap-425 .table>colgroup+thead>tr:first-child>th,.factory-bootstrap-425 .table>thead:first-child>tr:first-child>td,.factory-bootstrap-425 .table>thead:first-child>tr:first-child>th{border-top:0}.factory-bootstrap-425 .table>tbody+tbody{border-top:2px solid #ddd}.factory-bootstrap-425 .table .table{background-color:#fff}.factory-bootstrap-425 .table-condensed>tbody>tr>td,.factory-bootstrap-425 .table-condensed>tbody>tr>th,.factory-bootstrap-425 .table-condensed>tfoot>tr>td,.factory-bootstrap-425 .table-condensed>tfoot>tr>th,.factory-bootstrap-425 .table-condensed>thead>tr>td,.factory-bootstrap-425 .table-condensed>thead>tr>th{padding:5px}.factory-bootstrap-425 .table-bordered,.factory-bootstrap-425 .table-bordered>tbody>tr>td,.factory-bootstrap-425 .table-bordered>tbody>tr>th,.factory-bootstrap-425 .table-bordered>tfoot>tr>td,.factory-bootstrap-425 .table-bordered>tfoot>tr>th,.factory-bootstrap-425 .table-bordered>thead>tr>td,.factory-bootstrap-425 .table-bordered>thead>tr>th{border:1px solid #ddd}.factory-bootstrap-425 .table-bordered>thead>tr>td,.factory-bootstrap-425 .table-bordered>thead>tr>th{border-bottom-width:2px}.factory-bootstrap-425 .table-striped>tbody>tr:nth-child(odd)>td,.factory-bootstrap-425 .table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.factory-bootstrap-425 .table-hover>tbody>tr:hover>td,.factory-bootstrap-425 .table-hover>tbody>tr:hover>th{background-color:#f5f5f5}.factory-bootstrap-425 table col[class*=col-]{position:static;display:table-column;float:none}.factory-bootstrap-425 table td[class*=col-],.factory-bootstrap-425 table th[class*=col-]{display:table-cell;float:none}.factory-bootstrap-425 .table>tbody>.active>td,.factory-bootstrap-425 .table>tbody>.active>th,.factory-bootstrap-425 .table>tbody>tr>.active,.factory-bootstrap-425 .table>tfoot>.active>td,.factory-bootstrap-425 .table>tfoot>.active>th,.factory-bootstrap-425 .table>tfoot>tr>.active,.factory-bootstrap-425 .table>thead>.active>td,.factory-bootstrap-425 .table>thead>.active>th,.factory-bootstrap-425 .table>thead>tr>.active{background-color:#f5f5f5}.factory-bootstrap-425 .table-hover>tbody>.active:hover>td,.factory-bootstrap-425 .table-hover>tbody>.active:hover>th,.factory-bootstrap-425 .table-hover>tbody>tr>.active:hover{background-color:#e8e8e8}.factory-bootstrap-425 .table>tbody>.success>td,.factory-bootstrap-425 .table>tbody>.success>th,.factory-bootstrap-425 .table>tbody>tr>.success,.factory-bootstrap-425 .table>tfoot>.success>td,.factory-bootstrap-425 .table>tfoot>.success>th,.factory-bootstrap-425 .table>tfoot>tr>.success,.factory-bootstrap-425 .table>thead>.success>td,.factory-bootstrap-425 .table>thead>.success>th,.factory-bootstrap-425 .table>thead>tr>.success{background-color:#dff0d8}.factory-bootstrap-425 .table-hover>tbody>.success:hover>td,.factory-bootstrap-425 .table-hover>tbody>.success:hover>th,.factory-bootstrap-425 .table-hover>tbody>tr>.success:hover{background-color:#d0e9c6}.factory-bootstrap-425 .table>tbody>.danger>td,.factory-bootstrap-425 .table>tbody>.danger>th,.factory-bootstrap-425 .table>tbody>tr>.danger,.factory-bootstrap-425 .table>tfoot>.danger>td,.factory-bootstrap-425 .table>tfoot>.danger>th,.factory-bootstrap-425 .table>tfoot>tr>.danger,.factory-bootstrap-425 .table>thead>.danger>td,.factory-bootstrap-425 .table>thead>.danger>th,.factory-bootstrap-425 .table>thead>tr>.danger{background-color:#f2dede}.factory-bootstrap-425 .table-hover>tbody>.danger:hover>td,.factory-bootstrap-425 .table-hover>tbody>.danger:hover>th,.factory-bootstrap-425 .table-hover>tbody>tr>.danger:hover{background-color:#ebcccc}.factory-bootstrap-425 .table>tbody>.warning>td,.factory-bootstrap-425 .table>tbody>.warning>th,.factory-bootstrap-425 .table>tbody>tr>.warning,.factory-bootstrap-425 .table>tfoot>.warning>td,.factory-bootstrap-425 .table>tfoot>.warning>th,.factory-bootstrap-425 .table>tfoot>tr>.warning,.factory-bootstrap-425 .table>thead>.warning>td,.factory-bootstrap-425 .table>thead>.warning>th,.factory-bootstrap-425 .table>thead>tr>.warning{background-color:#fcf8e3}.factory-bootstrap-425 .table-hover>tbody>.warning:hover>td,.factory-bootstrap-425 .table-hover>tbody>.warning:hover>th,.factory-bootstrap-425 .table-hover>tbody>tr>.warning:hover{background-color:#faf2cc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}.factory-bootstrap-425 fieldset{padding:0;margin:0;border:0}.factory-bootstrap-425 legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5;-moz-box-sizing:content-box;box-sizing:content-box}.factory-bootstrap-425 label{display:inline-block;margin-bottom:5px;font-weight:700}.factory-bootstrap-425 input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.factory-bootstrap-425 input[type=checkbox],.factory-bootstrap-425 input[type=radio]{margin:4px 0 0;margin-top:1px \9;line-height:normal}.factory-bootstrap-425 input[type=file]{display:block}.factory-bootstrap-425 select[multiple],.factory-bootstrap-425 select[size]{height:auto}.factory-bootstrap-425 select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}.factory-bootstrap-425 input[type=checkbox]:focus,.factory-bootstrap-425 input[type=file]:focus,.factory-bootstrap-425 input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.factory-bootstrap-425 input[type=number]::-webkit-inner-spin-button,.factory-bootstrap-425 input[type=number]::-webkit-outer-spin-button{height:auto}.factory-bootstrap-425 output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.factory-bootstrap-425 .form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.factory-bootstrap-425 .form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-425 .form-control:-moz-placeholder{color:#999}.factory-bootstrap-425 .form-control::-moz-placeholder{color:#999;opacity:1}.factory-bootstrap-425 .form-control:-ms-input-placeholder{color:#999}.factory-bootstrap-425 .form-control::-webkit-input-placeholder{color:#999}.factory-bootstrap-425 .form-control[disabled],.factory-bootstrap-425 .form-control[readonly],.factory-bootstrap-425 fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}.factory-bootstrap-425 textarea.form-control{height:auto}.factory-bootstrap-425 .form-group{margin-bottom:15px}.factory-bootstrap-425 .checkbox,.factory-bootstrap-425 .radio{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.factory-bootstrap-425 .checkbox label,.factory-bootstrap-425 .radio label{display:inline;margin-bottom:0;font-weight:400;cursor:pointer}.factory-bootstrap-425 .checkbox input[type=checkbox],.factory-bootstrap-425 .checkbox-inline input[type=checkbox],.factory-bootstrap-425 .radio input[type=radio],.factory-bootstrap-425 .radio-inline input[type=radio]{float:left;margin-left:-20px}.factory-bootstrap-425 .checkbox+.checkbox,.factory-bootstrap-425 .radio+.radio{margin-top:-5px}.factory-bootstrap-425 .checkbox-inline,.factory-bootstrap-425 .radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.factory-bootstrap-425 .checkbox-inline+.checkbox-inline,.factory-bootstrap-425 .radio-inline+.radio-inline{margin-top:0;margin-left:10px}.factory-bootstrap-425 .checkbox-inline[disabled],.factory-bootstrap-425 .checkbox[disabled],.factory-bootstrap-425 .radio-inline[disabled],.factory-bootstrap-425 .radio[disabled],.factory-bootstrap-425 fieldset[disabled] .checkbox,.factory-bootstrap-425 fieldset[disabled] .checkbox-inline,.factory-bootstrap-425 fieldset[disabled] .radio,.factory-bootstrap-425 fieldset[disabled] .radio-inline,.factory-bootstrap-425 fieldset[disabled] input[type=checkbox],.factory-bootstrap-425 fieldset[disabled] input[type=radio],.factory-bootstrap-425 input[type=checkbox][disabled],.factory-bootstrap-425 input[type=radio][disabled]{cursor:not-allowed}.factory-bootstrap-425 .input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-425 select.input-sm{height:30px;line-height:30px}.factory-bootstrap-425 textarea.input-sm{height:auto}.factory-bootstrap-425 .input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-425 select.input-lg{height:46px;line-height:46px}.factory-bootstrap-425 textarea.input-lg{height:auto}.factory-bootstrap-425 .has-warning .checkbox,.factory-bootstrap-425 .has-warning .checkbox-inline,.factory-bootstrap-425 .has-warning .control-label,.factory-bootstrap-425 .has-warning .help-block,.factory-bootstrap-425 .has-warning .radio,.factory-bootstrap-425 .has-warning .radio-inline{color:#8a6d3b}.factory-bootstrap-425 .has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-425 .has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.factory-bootstrap-425 .has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.factory-bootstrap-425 .has-error .checkbox,.factory-bootstrap-425 .has-error .checkbox-inline,.factory-bootstrap-425 .has-error .control-label,.factory-bootstrap-425 .has-error .help-block,.factory-bootstrap-425 .has-error .radio,.factory-bootstrap-425 .has-error .radio-inline{color:#a94442}.factory-bootstrap-425 .controls{display:block}.factory-bootstrap-425 .has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-425 .has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.factory-bootstrap-425 .has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.factory-bootstrap-425 .has-success .checkbox,.factory-bootstrap-425 .has-success .checkbox-inline,.factory-bootstrap-425 .has-success .control-label,.factory-bootstrap-425 .has-success .help-block,.factory-bootstrap-425 .has-success .radio,.factory-bootstrap-425 .has-success .radio-inline{color:#3c763d}.factory-bootstrap-425 .has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-425 .has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.factory-bootstrap-425 .has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.factory-bootstrap-425 .form-control-static{margin-bottom:0}.factory-bootstrap-425 .help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373;font-weight:400}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline select.form-control{width:auto}.form-inline .checkbox,.form-inline .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{float:none;margin-left:0}}.factory-bootstrap-425 .form-horizontal .checkbox,.factory-bootstrap-425 .form-horizontal .checkbox-inline,.factory-bootstrap-425 .form-horizontal .control-label,.factory-bootstrap-425 .form-horizontal .radio,.factory-bootstrap-425 .form-horizontal .radio-inline{position:relative;padding-top:7px;margin-top:0;margin-bottom:0}.factory-bootstrap-425 .form-horizontal .control-label{max-width:200px}.factory-bootstrap-425 .form-horizontal .checkbox,.factory-bootstrap-425 .form-horizontal .radio{min-height:27px}.factory-bootstrap-425 .form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.factory-bootstrap-425 .form-horizontal .form-group:after,.factory-bootstrap-425 .form-horizontal .form-group:before{display:table;content:" "}.factory-bootstrap-425 .form-horizontal .form-group:after{clear:both}.factory-bootstrap-425 .form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.factory-bootstrap-425 .btn{display:inline-block;padding:5px 12px;margin-bottom:0;font-size:13px;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;border-radius:3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.factory-bootstrap-425 .btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.factory-bootstrap-425 .btn{text-decoration:none}.factory-bootstrap-425 .btn:focus,.factory-bootstrap-425 .btn:hover{color:#333;text-decoration:none}.factory-bootstrap-425 .btn.disabled,.factory-bootstrap-425 .btn[disabled],.factory-bootstrap-425 fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-425 .btn-default.active,.factory-bootstrap-425 .btn-default:active,.factory-bootstrap-425 .btn-default:focus,.factory-bootstrap-425 .btn-default:hover,.factory-bootstrap-425 .open .dropdown-toggle.btn-default{background:#fafafa;border-color:#999;color:#222}.factory-bootstrap-425 .btn-default.active,.factory-bootstrap-425 .btn-default:active,.factory-bootstrap-425 .open .dropdown-toggle.btn-default{background-image:none}.factory-bootstrap-425 .btn-default.disabled,.factory-bootstrap-425 .btn-default.disabled.active,.factory-bootstrap-425 .btn-default.disabled:active,.factory-bootstrap-425 .btn-default.disabled:focus,.factory-bootstrap-425 .btn-default.disabled:hover,.factory-bootstrap-425 .btn-default[disabled],.factory-bootstrap-425 .btn-default[disabled].active,.factory-bootstrap-425 .btn-default[disabled]:active,.factory-bootstrap-425 .btn-default[disabled]:focus,.factory-bootstrap-425 .btn-default[disabled]:hover,.factory-bootstrap-425 fieldset[disabled] .btn-default,.factory-bootstrap-425 fieldset[disabled] .btn-default.active,.factory-bootstrap-425 fieldset[disabled] .btn-default:active,.factory-bootstrap-425 fieldset[disabled] .btn-default:focus,.factory-bootstrap-425 fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.factory-bootstrap-425 .btn-default .badge{color:#fff;background-color:#fff}.factory-bootstrap-425 .btn-primary.active,.factory-bootstrap-425 .btn-primary:active,.factory-bootstrap-425 .btn-primary:focus,.factory-bootstrap-425 .btn-primary:hover,.factory-bootstrap-425 .open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.factory-bootstrap-425 .btn-primary.active,.factory-bootstrap-425 .btn-primary:active,.factory-bootstrap-425 .open .dropdown-toggle.btn-primary{background-image:none}.factory-bootstrap-425 .btn-primary.disabled,.factory-bootstrap-425 .btn-primary.disabled.active,.factory-bootstrap-425 .btn-primary.disabled:active,.factory-bootstrap-425 .btn-primary.disabled:focus,.factory-bootstrap-425 .btn-primary.disabled:hover,.factory-bootstrap-425 .btn-primary[disabled],.factory-bootstrap-425 .btn-primary[disabled].active,.factory-bootstrap-425 .btn-primary[disabled]:active,.factory-bootstrap-425 .btn-primary[disabled]:focus,.factory-bootstrap-425 .btn-primary[disabled]:hover,.factory-bootstrap-425 fieldset[disabled] .btn-primary,.factory-bootstrap-425 fieldset[disabled] .btn-primary.active,.factory-bootstrap-425 fieldset[disabled] .btn-primary:active,.factory-bootstrap-425 fieldset[disabled] .btn-primary:focus,.factory-bootstrap-425 fieldset[disabled] .btn-primary:hover{background-color:#428bca;border-color:#357ebd}.factory-bootstrap-425 .btn-primary .badge{color:#428bca;background-color:#fff}.factory-bootstrap-425 .btn-warning{color:#fff;background-color:#f0ad4e}.factory-bootstrap-425 .btn-warning.active,.factory-bootstrap-425 .btn-warning:active,.factory-bootstrap-425 .btn-warning:focus,.factory-bootstrap-425 .btn-warning:hover,.factory-bootstrap-425 .open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.factory-bootstrap-425 .btn-warning.active,.factory-bootstrap-425 .btn-warning:active,.factory-bootstrap-425 .open .dropdown-toggle.btn-warning{background-image:none}.factory-bootstrap-425 .btn-warning.disabled,.factory-bootstrap-425 .btn-warning.disabled.active,.factory-bootstrap-425 .btn-warning.disabled:active,.factory-bootstrap-425 .btn-warning.disabled:focus,.factory-bootstrap-425 .btn-warning.disabled:hover,.factory-bootstrap-425 .btn-warning[disabled],.factory-bootstrap-425 .btn-warning[disabled].active,.factory-bootstrap-425 .btn-warning[disabled]:active,.factory-bootstrap-425 .btn-warning[disabled]:focus,.factory-bootstrap-425 .btn-warning[disabled]:hover,.factory-bootstrap-425 fieldset[disabled] .btn-warning,.factory-bootstrap-425 fieldset[disabled] .btn-warning.active,.factory-bootstrap-425 fieldset[disabled] .btn-warning:active,.factory-bootstrap-425 fieldset[disabled] .btn-warning:focus,.factory-bootstrap-425 fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.factory-bootstrap-425 .btn-warning .badge{color:#f0ad4e;background-color:#fff}.factory-bootstrap-425 .btn-success{color:#fff;background-color:#5cb85c}.factory-bootstrap-425 .btn-success.active,.factory-bootstrap-425 .btn-success:active,.factory-bootstrap-425 .btn-success:focus,.factory-bootstrap-425 .btn-success:hover,.factory-bootstrap-425 .open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.factory-bootstrap-425 .btn-success.active,.factory-bootstrap-425 .btn-success:active,.factory-bootstrap-425 .open .dropdown-toggle.btn-success{background-image:none}.factory-bootstrap-425 .btn-success.disabled,.factory-bootstrap-425 .btn-success.disabled.active,.factory-bootstrap-425 .btn-success.disabled:active,.factory-bootstrap-425 .btn-success.disabled:focus,.factory-bootstrap-425 .btn-success.disabled:hover,.factory-bootstrap-425 .btn-success[disabled],.factory-bootstrap-425 .btn-success[disabled].active,.factory-bootstrap-425 .btn-success[disabled]:active,.factory-bootstrap-425 .btn-success[disabled]:focus,.factory-bootstrap-425 .btn-success[disabled]:hover,.factory-bootstrap-425 fieldset[disabled] .btn-success,.factory-bootstrap-425 fieldset[disabled] .btn-success.active,.factory-bootstrap-425 fieldset[disabled] .btn-success:active,.factory-bootstrap-425 fieldset[disabled] .btn-success:focus,.factory-bootstrap-425 fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.factory-bootstrap-425 .btn-success .badge{color:#5cb85c;background-color:#fff}.factory-bootstrap-425 .btn-info{color:#fff;background-color:#5bc0de}.factory-bootstrap-425 .btn-info.active,.factory-bootstrap-425 .btn-info:active,.factory-bootstrap-425 .btn-info:focus,.factory-bootstrap-425 .btn-info:hover,.factory-bootstrap-425 .open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.factory-bootstrap-425 .btn-info.active,.factory-bootstrap-425 .btn-info:active,.factory-bootstrap-425 .open .dropdown-toggle.btn-info{background-image:none}.factory-bootstrap-425 .btn-info.disabled,.factory-bootstrap-425 .btn-info.disabled.active,.factory-bootstrap-425 .btn-info.disabled:active,.factory-bootstrap-425 .btn-info.disabled:focus,.factory-bootstrap-425 .btn-info.disabled:hover,.factory-bootstrap-425 .btn-info[disabled],.factory-bootstrap-425 .btn-info[disabled].active,.factory-bootstrap-425 .btn-info[disabled]:active,.factory-bootstrap-425 .btn-info[disabled]:focus,.factory-bootstrap-425 .btn-info[disabled]:hover,.factory-bootstrap-425 fieldset[disabled] .btn-info,.factory-bootstrap-425 fieldset[disabled] .btn-info.active,.factory-bootstrap-425 fieldset[disabled] .btn-info:active,.factory-bootstrap-425 fieldset[disabled] .btn-info:focus,.factory-bootstrap-425 fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.factory-bootstrap-425 .btn-info .badge{color:#5bc0de;background-color:#fff}.factory-bootstrap-425 .btn-link{font-weight:400;color:#428bca;cursor:pointer;border-radius:0}.factory-bootstrap-425 .btn-link,.factory-bootstrap-425 .btn-link:active,.factory-bootstrap-425 .btn-link[disabled],.factory-bootstrap-425 fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-425 .btn-link,.factory-bootstrap-425 .btn-link:active,.factory-bootstrap-425 .btn-link:focus,.factory-bootstrap-425 .btn-link:hover{border-color:transparent}.factory-bootstrap-425 .btn-link:focus,.factory-bootstrap-425 .btn-link:hover{color:#2a6496;text-decoration:underline;background-color:transparent}.factory-bootstrap-425 .btn-link[disabled]:focus,.factory-bootstrap-425 .btn-link[disabled]:hover,.factory-bootstrap-425 fieldset[disabled] .btn-link:focus,.factory-bootstrap-425 fieldset[disabled] .btn-link:hover{color:#999;text-decoration:none}.factory-bootstrap-425 .btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-425 .btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-425 .btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-425 .btn-block{display:block;width:100%;padding-right:0;padding-left:0}.factory-bootstrap-425 .btn-block+.btn-block{margin-top:5px}.factory-bootstrap-425 input[type=button].btn-block,.factory-bootstrap-425 input[type=reset].btn-block,.factory-bootstrap-425 input[type=submit].btn-block{width:100%}.factory-bootstrap-425 .fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.factory-bootstrap-425 .fade.in{opacity:1}.factory-bootstrap-425 .collapse{display:none}.factory-bootstrap-425 .collapse.in{display:block}.factory-bootstrap-425 .collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular) format('svg')}.factory-bootstrap-425 .glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale}.factory-bootstrap-425 .glyphicon:empty{width:1em}.factory-bootstrap-425 .glyphicon-asterisk:before{content:"\2a"}.factory-bootstrap-425 .glyphicon-plus:before{content:"\2b"}.factory-bootstrap-425 .glyphicon-euro:before{content:"\20ac"}.factory-bootstrap-425 .glyphicon-minus:before{content:"\2212"}.factory-bootstrap-425 .glyphicon-cloud:before{content:"\2601"}.factory-bootstrap-425 .glyphicon-envelope:before{content:"\2709"}.factory-bootstrap-425 .glyphicon-pencil:before{content:"\270f"}.factory-bootstrap-425 .glyphicon-glass:before{content:"\e001"}.factory-bootstrap-425 .glyphicon-music:before{content:"\e002"}.factory-bootstrap-425 .glyphicon-search:before{content:"\e003"}.factory-bootstrap-425 .glyphicon-heart:before{content:"\e005"}.factory-bootstrap-425 .glyphicon-star:before{content:"\e006"}.factory-bootstrap-425 .glyphicon-star-empty:before{content:"\e007"}.factory-bootstrap-425 .glyphicon-user:before{content:"\e008"}.factory-bootstrap-425 .glyphicon-film:before{content:"\e009"}.factory-bootstrap-425 .glyphicon-th-large:before{content:"\e010"}.factory-bootstrap-425 .glyphicon-th:before{content:"\e011"}.factory-bootstrap-425 .glyphicon-th-list:before{content:"\e012"}.factory-bootstrap-425 .glyphicon-ok:before{content:"\e013"}.factory-bootstrap-425 .glyphicon-remove:before{content:"\e014"}.factory-bootstrap-425 .glyphicon-zoom-in:before{content:"\e015"}.factory-bootstrap-425 .glyphicon-zoom-out:before{content:"\e016"}.factory-bootstrap-425 .glyphicon-off:before{content:"\e017"}.factory-bootstrap-425 .glyphicon-signal:before{content:"\e018"}.factory-bootstrap-425 .glyphicon-cog:before{content:"\e019"}.factory-bootstrap-425 .glyphicon-trash:before{content:"\e020"}.factory-bootstrap-425 .glyphicon-home:before{content:"\e021"}.factory-bootstrap-425 .glyphicon-file:before{content:"\e022"}.factory-bootstrap-425 .glyphicon-time:before{content:"\e023"}.factory-bootstrap-425 .glyphicon-road:before{content:"\e024"}.factory-bootstrap-425 .glyphicon-download-alt:before{content:"\e025"}.factory-bootstrap-425 .glyphicon-download:before{content:"\e026"}.factory-bootstrap-425 .glyphicon-upload:before{content:"\e027"}.factory-bootstrap-425 .glyphicon-inbox:before{content:"\e028"}.factory-bootstrap-425 .glyphicon-play-circle:before{content:"\e029"}.factory-bootstrap-425 .glyphicon-repeat:before{content:"\e030"}.factory-bootstrap-425 .glyphicon-refresh:before{content:"\e031"}.factory-bootstrap-425 .glyphicon-list-alt:before{content:"\e032"}.factory-bootstrap-425 .glyphicon-lock:before{content:"\e033"}.factory-bootstrap-425 .glyphicon-flag:before{content:"\e034"}.factory-bootstrap-425 .glyphicon-headphones:before{content:"\e035"}.factory-bootstrap-425 .glyphicon-volume-off:before{content:"\e036"}.factory-bootstrap-425 .glyphicon-volume-down:before{content:"\e037"}.factory-bootstrap-425 .glyphicon-volume-up:before{content:"\e038"}.factory-bootstrap-425 .glyphicon-qrcode:before{content:"\e039"}.factory-bootstrap-425 .glyphicon-barcode:before{content:"\e040"}.factory-bootstrap-425 .glyphicon-tag:before{content:"\e041"}.factory-bootstrap-425 .glyphicon-tags:before{content:"\e042"}.factory-bootstrap-425 .glyphicon-book:before{content:"\e043"}.factory-bootstrap-425 .glyphicon-bookmark:before{content:"\e044"}.factory-bootstrap-425 .glyphicon-print:before{content:"\e045"}.factory-bootstrap-425 .glyphicon-camera:before{content:"\e046"}.factory-bootstrap-425 .glyphicon-font:before{content:"\e047"}.factory-bootstrap-425 .glyphicon-bold:before{content:"\e048"}.factory-bootstrap-425 .glyphicon-italic:before{content:"\e049"}.factory-bootstrap-425 .glyphicon-text-height:before{content:"\e050"}.factory-bootstrap-425 .glyphicon-text-width:before{content:"\e051"}.factory-bootstrap-425 .glyphicon-align-left:before{content:"\e052"}.factory-bootstrap-425 .glyphicon-align-center:before{content:"\e053"}.factory-bootstrap-425 .glyphicon-align-right:before{content:"\e054"}.factory-bootstrap-425 .glyphicon-align-justify:before{content:"\e055"}.factory-bootstrap-425 .glyphicon-list:before{content:"\e056"}.factory-bootstrap-425 .glyphicon-indent-left:before{content:"\e057"}.factory-bootstrap-425 .glyphicon-indent-right:before{content:"\e058"}.factory-bootstrap-425 .glyphicon-facetime-video:before{content:"\e059"}.factory-bootstrap-425 .glyphicon-picture:before{content:"\e060"}.factory-bootstrap-425 .glyphicon-map-marker:before{content:"\e062"}.factory-bootstrap-425 .glyphicon-adjust:before{content:"\e063"}.factory-bootstrap-425 .glyphicon-tint:before{content:"\e064"}.factory-bootstrap-425 .glyphicon-edit:before{content:"\e065"}.factory-bootstrap-425 .glyphicon-share:before{content:"\e066"}.factory-bootstrap-425 .glyphicon-check:before{content:"\e067"}.factory-bootstrap-425 .glyphicon-move:before{content:"\e068"}.factory-bootstrap-425 .glyphicon-step-backward:before{content:"\e069"}.factory-bootstrap-425 .glyphicon-fast-backward:before{content:"\e070"}.factory-bootstrap-425 .glyphicon-backward:before{content:"\e071"}.factory-bootstrap-425 .glyphicon-play:before{content:"\e072"}.factory-bootstrap-425 .glyphicon-pause:before{content:"\e073"}.factory-bootstrap-425 .glyphicon-stop:before{content:"\e074"}.factory-bootstrap-425 .glyphicon-forward:before{content:"\e075"}.factory-bootstrap-425 .glyphicon-fast-forward:before{content:"\e076"}.factory-bootstrap-425 .glyphicon-step-forward:before{content:"\e077"}.factory-bootstrap-425 .glyphicon-eject:before{content:"\e078"}.factory-bootstrap-425 .glyphicon-chevron-left:before{content:"\e079"}.factory-bootstrap-425 .glyphicon-chevron-right:before{content:"\e080"}.factory-bootstrap-425 .glyphicon-plus-sign:before{content:"\e081"}.factory-bootstrap-425 .glyphicon-minus-sign:before{content:"\e082"}.factory-bootstrap-425 .glyphicon-remove-sign:before{content:"\e083"}.factory-bootstrap-425 .glyphicon-ok-sign:before{content:"\e084"}.factory-bootstrap-425 .glyphicon-question-sign:before{content:"\e085"}.factory-bootstrap-425 .glyphicon-info-sign:before{content:"\e086"}.factory-bootstrap-425 .glyphicon-screenshot:before{content:"\e087"}.factory-bootstrap-425 .glyphicon-remove-circle:before{content:"\e088"}.factory-bootstrap-425 .glyphicon-ok-circle:before{content:"\e089"}.factory-bootstrap-425 .glyphicon-ban-circle:before{content:"\e090"}.factory-bootstrap-425 .glyphicon-arrow-left:before{content:"\e091"}.factory-bootstrap-425 .glyphicon-arrow-right:before{content:"\e092"}.factory-bootstrap-425 .glyphicon-arrow-up:before{content:"\e093"}.factory-bootstrap-425 .glyphicon-arrow-down:before{content:"\e094"}.factory-bootstrap-425 .glyphicon-share-alt:before{content:"\e095"}.factory-bootstrap-425 .glyphicon-resize-full:before{content:"\e096"}.factory-bootstrap-425 .glyphicon-resize-small:before{content:"\e097"}.factory-bootstrap-425 .glyphicon-exclamation-sign:before{content:"\e101"}.factory-bootstrap-425 .glyphicon-gift:before{content:"\e102"}.factory-bootstrap-425 .glyphicon-leaf:before{content:"\e103"}.factory-bootstrap-425 .glyphicon-fire:before{content:"\e104"}.factory-bootstrap-425 .glyphicon-eye-open:before{content:"\e105"}.factory-bootstrap-425 .glyphicon-eye-close:before{content:"\e106"}.factory-bootstrap-425 .glyphicon-warning-sign:before{content:"\e107"}.factory-bootstrap-425 .glyphicon-plane:before{content:"\e108"}.factory-bootstrap-425 .glyphicon-calendar:before{content:"\e109"}.factory-bootstrap-425 .glyphicon-random:before{content:"\e110"}.factory-bootstrap-425 .glyphicon-comment:before{content:"\e111"}.factory-bootstrap-425 .glyphicon-magnet:before{content:"\e112"}.factory-bootstrap-425 .glyphicon-chevron-up:before{content:"\e113"}.factory-bootstrap-425 .glyphicon-chevron-down:before{content:"\e114"}.factory-bootstrap-425 .glyphicon-retweet:before{content:"\e115"}.factory-bootstrap-425 .glyphicon-shopping-cart:before{content:"\e116"}.factory-bootstrap-425 .glyphicon-folder-close:before{content:"\e117"}.factory-bootstrap-425 .glyphicon-folder-open:before{content:"\e118"}.factory-bootstrap-425 .glyphicon-resize-vertical:before{content:"\e119"}.factory-bootstrap-425 .glyphicon-resize-horizontal:before{content:"\e120"}.factory-bootstrap-425 .glyphicon-hdd:before{content:"\e121"}.factory-bootstrap-425 .glyphicon-bullhorn:before{content:"\e122"}.factory-bootstrap-425 .glyphicon-bell:before{content:"\e123"}.factory-bootstrap-425 .glyphicon-certificate:before{content:"\e124"}.factory-bootstrap-425 .glyphicon-thumbs-up:before{content:"\e125"}.factory-bootstrap-425 .glyphicon-thumbs-down:before{content:"\e126"}.factory-bootstrap-425 .glyphicon-hand-right:before{content:"\e127"}.factory-bootstrap-425 .glyphicon-hand-left:before{content:"\e128"}.factory-bootstrap-425 .glyphicon-hand-up:before{content:"\e129"}.factory-bootstrap-425 .glyphicon-hand-down:before{content:"\e130"}.factory-bootstrap-425 .glyphicon-circle-arrow-right:before{content:"\e131"}.factory-bootstrap-425 .glyphicon-circle-arrow-left:before{content:"\e132"}.factory-bootstrap-425 .glyphicon-circle-arrow-up:before{content:"\e133"}.factory-bootstrap-425 .glyphicon-circle-arrow-down:before{content:"\e134"}.factory-bootstrap-425 .glyphicon-globe:before{content:"\e135"}.factory-bootstrap-425 .glyphicon-wrench:before{content:"\e136"}.factory-bootstrap-425 .glyphicon-tasks:before{content:"\e137"}.factory-bootstrap-425 .glyphicon-filter:before{content:"\e138"}.factory-bootstrap-425 .glyphicon-briefcase:before{content:"\e139"}.factory-bootstrap-425 .glyphicon-fullscreen:before{content:"\e140"}.factory-bootstrap-425 .glyphicon-dashboard:before{content:"\e141"}.factory-bootstrap-425 .glyphicon-paperclip:before{content:"\e142"}.factory-bootstrap-425 .glyphicon-heart-empty:before{content:"\e143"}.factory-bootstrap-425 .glyphicon-link:before{content:"\e144"}.factory-bootstrap-425 .glyphicon-phone:before{content:"\e145"}.factory-bootstrap-425 .glyphicon-pushpin:before{content:"\e146"}.factory-bootstrap-425 .glyphicon-usd:before{content:"\e148"}.factory-bootstrap-425 .glyphicon-gbp:before{content:"\e149"}.factory-bootstrap-425 .glyphicon-sort:before{content:"\e150"}.factory-bootstrap-425 .glyphicon-sort-by-alphabet:before{content:"\e151"}.factory-bootstrap-425 .glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.factory-bootstrap-425 .glyphicon-sort-by-order:before{content:"\e153"}.factory-bootstrap-425 .glyphicon-sort-by-order-alt:before{content:"\e154"}.factory-bootstrap-425 .glyphicon-sort-by-attributes:before{content:"\e155"}.factory-bootstrap-425 .glyphicon-sort-by-attributes-alt:before{content:"\e156"}.factory-bootstrap-425 .glyphicon-unchecked:before{content:"\e157"}.factory-bootstrap-425 .glyphicon-expand:before{content:"\e158"}.factory-bootstrap-425 .glyphicon-collapse-down:before{content:"\e159"}.factory-bootstrap-425 .glyphicon-collapse-up:before{content:"\e160"}.factory-bootstrap-425 .glyphicon-log-in:before{content:"\e161"}.factory-bootstrap-425 .glyphicon-flash:before{content:"\e162"}.factory-bootstrap-425 .glyphicon-log-out:before{content:"\e163"}.factory-bootstrap-425 .glyphicon-new-window:before{content:"\e164"}.factory-bootstrap-425 .glyphicon-record:before{content:"\e165"}.factory-bootstrap-425 .glyphicon-save:before{content:"\e166"}.factory-bootstrap-425 .glyphicon-open:before{content:"\e167"}.factory-bootstrap-425 .glyphicon-saved:before{content:"\e168"}.factory-bootstrap-425 .glyphicon-import:before{content:"\e169"}.factory-bootstrap-425 .glyphicon-export:before{content:"\e170"}.factory-bootstrap-425 .glyphicon-send:before{content:"\e171"}.factory-bootstrap-425 .glyphicon-floppy-disk:before{content:"\e172"}.factory-bootstrap-425 .glyphicon-floppy-saved:before{content:"\e173"}.factory-bootstrap-425 .glyphicon-floppy-remove:before{content:"\e174"}.factory-bootstrap-425 .glyphicon-floppy-save:before{content:"\e175"}.factory-bootstrap-425 .glyphicon-floppy-open:before{content:"\e176"}.factory-bootstrap-425 .glyphicon-credit-card:before{content:"\e177"}.factory-bootstrap-425 .glyphicon-transfer:before{content:"\e178"}.factory-bootstrap-425 .glyphicon-cutlery:before{content:"\e179"}.factory-bootstrap-425 .glyphicon-header:before{content:"\e180"}.factory-bootstrap-425 .glyphicon-compressed:before{content:"\e181"}.factory-bootstrap-425 .glyphicon-earphone:before{content:"\e182"}.factory-bootstrap-425 .glyphicon-phone-alt:before{content:"\e183"}.factory-bootstrap-425 .glyphicon-tower:before{content:"\e184"}.factory-bootstrap-425 .glyphicon-stats:before{content:"\e185"}.factory-bootstrap-425 .glyphicon-sd-video:before{content:"\e186"}.factory-bootstrap-425 .glyphicon-hd-video:before{content:"\e187"}.factory-bootstrap-425 .glyphicon-subtitles:before{content:"\e188"}.factory-bootstrap-425 .glyphicon-sound-stereo:before{content:"\e189"}.factory-bootstrap-425 .glyphicon-sound-dolby:before{content:"\e190"}.factory-bootstrap-425 .glyphicon-sound-5-1:before{content:"\e191"}.factory-bootstrap-425 .glyphicon-sound-6-1:before{content:"\e192"}.factory-bootstrap-425 .glyphicon-sound-7-1:before{content:"\e193"}.factory-bootstrap-425 .glyphicon-copyright-mark:before{content:"\e194"}.factory-bootstrap-425 .glyphicon-registration-mark:before{content:"\e195"}.factory-bootstrap-425 .glyphicon-cloud-download:before{content:"\e197"}.factory-bootstrap-425 .glyphicon-cloud-upload:before{content:"\e198"}.factory-bootstrap-425 .glyphicon-tree-conifer:before{content:"\e199"}.factory-bootstrap-425 .glyphicon-tree-deciduous:before{content:"\e200"}.factory-bootstrap-425 .caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.factory-bootstrap-425 .dropdown{position:relative}.factory-bootstrap-425 .dropdown-toggle:focus{outline:0}.factory-bootstrap-425 .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.factory-bootstrap-425 .dropdown-menu.pull-right{right:0;left:auto}.factory-bootstrap-425 .dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.factory-bootstrap-425 .dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429;color:#333;white-space:nowrap}.factory-bootstrap-425 .dropdown-menu>li>a:focus,.factory-bootstrap-425 .dropdown-menu>li>a:hover{color:#262626;text-decoration:none}.factory-bootstrap-425 .dropdown-menu>.active>a,.factory-bootstrap-425 .dropdown-menu>.active>a:focus,.factory-bootstrap-425 .dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0}.factory-bootstrap-425 .dropdown-menu>.disabled>a,.factory-bootstrap-425 .dropdown-menu>.disabled>a:focus,.factory-bootstrap-425 .dropdown-menu>.disabled>a:hover{color:#999}.factory-bootstrap-425 .dropdown-menu>.disabled>a:focus,.factory-bootstrap-425 .dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-425 .open>.dropdown-menu{display:block}.factory-bootstrap-425 .open>a{outline:0}.factory-bootstrap-425 .dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.factory-bootstrap-425 .dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.factory-bootstrap-425 .pull-right>.dropdown-menu{right:0;left:auto}.factory-bootstrap-425 .dropup .caret,.factory-bootstrap-425 .navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.factory-bootstrap-425 .dropup .dropdown-menu,.factory-bootstrap-425 .navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.factory-bootstrap-425 .btn-group,.factory-bootstrap-425 .btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.factory-bootstrap-425 .btn-group-vertical>.btn,.factory-bootstrap-425 .btn-group>.btn{position:relative;float:left}.factory-bootstrap-425 .btn-group-vertical>.btn.active,.factory-bootstrap-425 .btn-group-vertical>.btn:active,.factory-bootstrap-425 .btn-group-vertical>.btn:focus,.factory-bootstrap-425 .btn-group-vertical>.btn:hover,.factory-bootstrap-425 .btn-group>.btn.active,.factory-bootstrap-425 .btn-group>.btn:active,.factory-bootstrap-425 .btn-group>.btn:focus,.factory-bootstrap-425 .btn-group>.btn:hover{z-index:2}.factory-bootstrap-425 .btn-group-vertical>.btn:focus,.factory-bootstrap-425 .btn-group>.btn:focus{outline:0}.factory-bootstrap-425 .btn-group .btn+.btn,.factory-bootstrap-425 .btn-group .btn+.btn-group,.factory-bootstrap-425 .btn-group .btn-group+.btn,.factory-bootstrap-425 .btn-group .btn-group+.btn-group{margin-left:-1px}.factory-bootstrap-425 .btn-toolbar:after,.factory-bootstrap-425 .btn-toolbar:before{display:table;content:" "}.factory-bootstrap-425 .btn-toolbar:after{clear:both}.factory-bootstrap-425 .btn-toolbar .btn-group{float:left}.factory-bootstrap-425 .btn-toolbar>.btn+.btn,.factory-bootstrap-425 .btn-toolbar>.btn+.btn-group,.factory-bootstrap-425 .btn-toolbar>.btn-group+.btn,.factory-bootstrap-425 .btn-toolbar>.btn-group+.btn-group{margin-left:5px}.factory-bootstrap-425 .btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.factory-bootstrap-425 .btn-group>.btn:first-child{margin-left:0}.factory-bootstrap-425 .btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-425 .btn-group>.btn:last-child:not(:first-child),.factory-bootstrap-425 .btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-425 .btn-group>.btn-group{float:left}.factory-bootstrap-425 .btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.factory-bootstrap-425 .btn-group>.btn-group:first-child>.btn:last-child,.factory-bootstrap-425 .btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-425 .btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-425 .btn-group .dropdown-toggle:active,.factory-bootstrap-425 .btn-group.open .dropdown-toggle{outline:0}.factory-bootstrap-425 .btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-425 .btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-425 .btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-425 .btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.factory-bootstrap-425 .btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.factory-bootstrap-425 .btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.factory-bootstrap-425 .btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-425 .btn-group{border:4px solid #f9f9f9;border-radius:4px}.factory-bootstrap-425 .btn-group .btn.active.value{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-425 .btn .caret{margin-left:0}.factory-bootstrap-425 .btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.factory-bootstrap-425 .dropup .btn-lg .caret{border-width:0 5px 5px}.factory-bootstrap-425 .btn-group-vertical>.btn,.factory-bootstrap-425 .btn-group-vertical>.btn-group,.factory-bootstrap-425 .btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.factory-bootstrap-425 .btn-group-vertical>.btn-group:after,.factory-bootstrap-425 .btn-group-vertical>.btn-group:before{display:table;content:" "}.factory-bootstrap-425 .btn-group-vertical>.btn-group:after{clear:both}.factory-bootstrap-425 .btn-group-vertical>.btn-group>.btn{float:none}.factory-bootstrap-425 .btn-group-vertical>.btn+.btn,.factory-bootstrap-425 .btn-group-vertical>.btn+.btn-group,.factory-bootstrap-425 .btn-group-vertical>.btn-group+.btn,.factory-bootstrap-425 .btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.factory-bootstrap-425 .btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.factory-bootstrap-425 .btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-425 .btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.factory-bootstrap-425 .btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.factory-bootstrap-425 .btn-group-vertical>.btn-group:first-child>.btn:last-child,.factory-bootstrap-425 .btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-425 .btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-425 .btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.factory-bootstrap-425 .btn-group-justified>.btn,.factory-bootstrap-425 .btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.factory-bootstrap-425 .btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=checkbox],[data-toggle=buttons]>.btn>input[type=radio]{display:none}.factory-bootstrap-425 .input-group{position:relative;display:table;border-collapse:separate}.factory-bootstrap-425 .input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.factory-bootstrap-425 .input-group .form-control{width:100%;margin-bottom:0}.factory-bootstrap-425 .input-group-lg>.form-control,.factory-bootstrap-425 .input-group-lg>.input-group-addon,.factory-bootstrap-425 .input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-425 select.input-group-lg>.form-control,.factory-bootstrap-425 select.input-group-lg>.input-group-addon,.factory-bootstrap-425 select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}.factory-bootstrap-425 textarea.input-group-lg>.form-control,.factory-bootstrap-425 textarea.input-group-lg>.input-group-addon,.factory-bootstrap-425 textarea.input-group-lg>.input-group-btn>.btn{height:auto}.factory-bootstrap-425 .input-group-sm>.form-control,.factory-bootstrap-425 .input-group-sm>.input-group-addon,.factory-bootstrap-425 .input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-425 select.input-group-sm>.form-control,.factory-bootstrap-425 select.input-group-sm>.input-group-addon,.factory-bootstrap-425 select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}.factory-bootstrap-425 textarea.input-group-sm>.form-control,.factory-bootstrap-425 textarea.input-group-sm>.input-group-addon,.factory-bootstrap-425 textarea.input-group-sm>.input-group-btn>.btn{height:auto}.factory-bootstrap-425 .input-group .form-control,.factory-bootstrap-425 .input-group-addon,.factory-bootstrap-425 .input-group-btn{display:table-cell}.factory-bootstrap-425 .input-group .form-control:not(:first-child):not(:last-child),.factory-bootstrap-425 .input-group-addon:not(:first-child):not(:last-child),.factory-bootstrap-425 .input-group-btn:not(:first-child):not(:last-child){border-radius:0}.factory-bootstrap-425 .input-group-addon,.factory-bootstrap-425 .input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.factory-bootstrap-425 .input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.factory-bootstrap-425 .input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.factory-bootstrap-425 .input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.factory-bootstrap-425 .input-group-addon input[type=checkbox],.factory-bootstrap-425 .input-group-addon input[type=radio]{margin-top:0}.factory-bootstrap-425 .input-group .form-control:first-child,.factory-bootstrap-425 .input-group-addon:first-child,.factory-bootstrap-425 .input-group-btn:first-child>.btn,.factory-bootstrap-425 .input-group-btn:first-child>.dropdown-toggle,.factory-bootstrap-425 .input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-425 .input-group-addon:first-child{border-right:0}.factory-bootstrap-425 .input-group .form-control:last-child,.factory-bootstrap-425 .input-group-addon:last-child,.factory-bootstrap-425 .input-group-btn:first-child>.btn:not(:first-child),.factory-bootstrap-425 .input-group-btn:last-child>.btn,.factory-bootstrap-425 .input-group-btn:last-child>.dropdown-toggle{border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-425 .input-group-addon:last-child{border-left:0}.factory-bootstrap-425 .input-group-btn{position:relative;white-space:nowrap}.factory-bootstrap-425 .input-group-btn:first-child>.btn{margin-right:-1px}.factory-bootstrap-425 .input-group-btn:last-child>.btn{margin-left:-1px}.factory-bootstrap-425 .input-group-btn>.btn{position:relative}.factory-bootstrap-425 .input-group-btn>.btn+.btn{margin-left:-4px}.factory-bootstrap-425 .input-group-btn>.btn:active,.factory-bootstrap-425 .input-group-btn>.btn:hover{z-index:2}.factory-bootstrap-425 .nav{padding-left:0;margin-bottom:0;list-style:none}.factory-bootstrap-425 .nav:after,.factory-bootstrap-425 .nav:before{display:table;content:" "}.factory-bootstrap-425 .nav:after{clear:both}.factory-bootstrap-425 .nav>li{position:relative;display:block}.factory-bootstrap-425 .nav>li>a{position:relative;display:block;padding:10px 15px}.factory-bootstrap-425 .nav>li>a:focus,.factory-bootstrap-425 .nav>li>a:hover{text-decoration:none;background-color:#eee}.factory-bootstrap-425 .nav>li.disabled>a{color:#999}.factory-bootstrap-425 .nav>li.disabled>a:focus,.factory-bootstrap-425 .nav>li.disabled>a:hover{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.factory-bootstrap-425 .nav .open>a,.factory-bootstrap-425 .nav .open>a:focus,.factory-bootstrap-425 .nav .open>a:hover{background-color:#eee;border-color:#428bca}.factory-bootstrap-425 .nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.factory-bootstrap-425 .nav>li>a>img{max-width:none}.factory-bootstrap-425 .nav-tabs{border-bottom:1px solid #ddd}.factory-bootstrap-425 .nav-tabs>li{float:left;margin-bottom:-1px}.factory-bootstrap-425 .nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.factory-bootstrap-425 .nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.factory-bootstrap-425 .nav-tabs>li.active>a,.factory-bootstrap-425 .nav-tabs>li.active>a:focus,.factory-bootstrap-425 .nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.factory-bootstrap-425 .nav-tabs.nav-justified{width:100%;border-bottom:0}.factory-bootstrap-425 .nav-tabs.nav-justified>li{float:none}.factory-bootstrap-425 .nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.factory-bootstrap-425 .nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.factory-bootstrap-425 .nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.factory-bootstrap-425 .nav-tabs.nav-justified>.active>a,.factory-bootstrap-425 .nav-tabs.nav-justified>.active>a:focus,.factory-bootstrap-425 .nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.factory-bootstrap-425 .nav-pills>li{float:left}.factory-bootstrap-425 .nav-pills>li>a{border-radius:4px}.factory-bootstrap-425 .nav-pills>li+li{margin-left:2px}.factory-bootstrap-425 .nav-pills>li.active>a,.factory-bootstrap-425 .nav-pills>li.active>a:focus,.factory-bootstrap-425 .nav-pills>li.active>a:hover{color:#fff;background-color:#428bca}.factory-bootstrap-425 .nav-stacked>li{float:none}.factory-bootstrap-425 .nav-stacked>li+li{margin-top:2px;margin-left:0}.factory-bootstrap-425 .nav-justified{width:100%}.factory-bootstrap-425 .nav-justified>li{float:none}.factory-bootstrap-425 .nav-justified>li>a{margin-bottom:5px;text-align:center}.factory-bootstrap-425 .nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.factory-bootstrap-425 .nav-tabs-justified{border-bottom:0}.factory-bootstrap-425 .nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.factory-bootstrap-425 .nav-tabs-justified>.active>a,.factory-bootstrap-425 .nav-tabs-justified>.active>a:focus,.factory-bootstrap-425 .nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.factory-bootstrap-425 .tab-content>.tab-pane{display:none}.factory-bootstrap-425 .tab-content>.active{display:block}.factory-bootstrap-425 .nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-425 .navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.factory-bootstrap-425 .navbar:after,.factory-bootstrap-425 .navbar:before{display:table;content:" "}.factory-bootstrap-425 .navbar:after{clear:both}@media (min-width:768px){.navbar{border-radius:4px}}.factory-bootstrap-425 .navbar-header:after,.factory-bootstrap-425 .navbar-header:before{display:table;content:" "}.factory-bootstrap-425 .navbar-header:after{clear:both}@media (min-width:768px){.navbar-header{float:left}}.factory-bootstrap-425 .navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.factory-bootstrap-425 .navbar-collapse:after,.factory-bootstrap-425 .navbar-collapse:before{display:table;content:" "}.factory-bootstrap-425 .navbar-collapse:after{clear:both}.factory-bootstrap-425 .navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.factory-bootstrap-425 .container>.navbar-collapse,.factory-bootstrap-425 .container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.factory-bootstrap-425 .navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.factory-bootstrap-425 .navbar-fixed-bottom,.factory-bootstrap-425 .navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.factory-bootstrap-425 .navbar-fixed-top{top:0;border-width:0 0 1px}.factory-bootstrap-425 .navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.factory-bootstrap-425 .navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px}.factory-bootstrap-425 .navbar-brand:focus,.factory-bootstrap-425 .navbar-brand:hover{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.factory-bootstrap-425 .navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.factory-bootstrap-425 .navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.factory-bootstrap-425 .navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.factory-bootstrap-425 .navbar-nav{margin:7.5px -15px}.factory-bootstrap-425 .navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.factory-bootstrap-425 .navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form select.form-control{width:auto}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{float:none;margin-left:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.factory-bootstrap-425 .navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-425 .navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-425 .navbar-nav.pull-right>li>.dropdown-menu,.factory-bootstrap-425 .navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.factory-bootstrap-425 .navbar-btn{margin-top:8px;margin-bottom:8px}.factory-bootstrap-425 .navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.factory-bootstrap-425 .navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.factory-bootstrap-425 .navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.factory-bootstrap-425 .navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.factory-bootstrap-425 .navbar-default .navbar-brand{color:#777}.factory-bootstrap-425 .navbar-default .navbar-brand:focus,.factory-bootstrap-425 .navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.factory-bootstrap-425 .navbar-default .navbar-nav>li>a,.factory-bootstrap-425 .navbar-default .navbar-text{color:#777}.factory-bootstrap-425 .navbar-default .navbar-nav>li>a:focus,.factory-bootstrap-425 .navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.factory-bootstrap-425 .navbar-default .navbar-nav>.active>a,.factory-bootstrap-425 .navbar-default .navbar-nav>.active>a:focus,.factory-bootstrap-425 .navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.factory-bootstrap-425 .navbar-default .navbar-nav>.disabled>a,.factory-bootstrap-425 .navbar-default .navbar-nav>.disabled>a:focus,.factory-bootstrap-425 .navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.factory-bootstrap-425 .navbar-default .navbar-toggle{border-color:#ddd}.factory-bootstrap-425 .navbar-default .navbar-toggle:focus,.factory-bootstrap-425 .navbar-default .navbar-toggle:hover{background-color:#ddd}.factory-bootstrap-425 .navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.factory-bootstrap-425 .navbar-default .navbar-collapse,.factory-bootstrap-425 .navbar-default .navbar-form{border-color:#e7e7e7}.factory-bootstrap-425 .navbar-default .navbar-nav>.open>a,.factory-bootstrap-425 .navbar-default .navbar-nav>.open>a:focus,.factory-bootstrap-425 .navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.factory-bootstrap-425 .navbar-default .navbar-link{color:#777}.factory-bootstrap-425 .navbar-default .navbar-link:hover{color:#333}.factory-bootstrap-425 .navbar-inverse{background-color:#222;border-color:#080808}.factory-bootstrap-425 .navbar-inverse .navbar-brand{color:#999}.factory-bootstrap-425 .navbar-inverse .navbar-brand:focus,.factory-bootstrap-425 .navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.factory-bootstrap-425 .navbar-inverse .navbar-nav>li>a,.factory-bootstrap-425 .navbar-inverse .navbar-text{color:#999}.factory-bootstrap-425 .navbar-inverse .navbar-nav>li>a:focus,.factory-bootstrap-425 .navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.factory-bootstrap-425 .navbar-inverse .navbar-nav>.active>a,.factory-bootstrap-425 .navbar-inverse .navbar-nav>.active>a:focus,.factory-bootstrap-425 .navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.factory-bootstrap-425 .navbar-inverse .navbar-nav>.disabled>a,.factory-bootstrap-425 .navbar-inverse .navbar-nav>.disabled>a:focus,.factory-bootstrap-425 .navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.factory-bootstrap-425 .navbar-inverse .navbar-toggle{border-color:#333}.factory-bootstrap-425 .navbar-inverse .navbar-toggle:focus,.factory-bootstrap-425 .navbar-inverse .navbar-toggle:hover{background-color:#333}.factory-bootstrap-425 .navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.factory-bootstrap-425 .navbar-inverse .navbar-collapse,.factory-bootstrap-425 .navbar-inverse .navbar-form{border-color:#101010}.factory-bootstrap-425 .navbar-inverse .navbar-nav>.open>a,.factory-bootstrap-425 .navbar-inverse .navbar-nav>.open>a:focus,.factory-bootstrap-425 .navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.factory-bootstrap-425 .navbar-inverse .navbar-link{color:#999}.factory-bootstrap-425 .navbar-inverse .navbar-link:hover{color:#fff}.factory-bootstrap-425 .breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.factory-bootstrap-425 .breadcrumb>li{display:inline-block}.factory-bootstrap-425 .breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.factory-bootstrap-425 .breadcrumb>.active{color:#999}.factory-bootstrap-425 .pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.factory-bootstrap-425 .pagination>li{display:inline}.factory-bootstrap-425 .pagination>li>a,.factory-bootstrap-425 .pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.factory-bootstrap-425 .pagination>li:first-child>a,.factory-bootstrap-425 .pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.factory-bootstrap-425 .pagination>li:last-child>a,.factory-bootstrap-425 .pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.factory-bootstrap-425 .pagination>li>a:focus,.factory-bootstrap-425 .pagination>li>a:hover,.factory-bootstrap-425 .pagination>li>span:focus,.factory-bootstrap-425 .pagination>li>span:hover{background-color:#eee}.factory-bootstrap-425 .pagination>.active>a,.factory-bootstrap-425 .pagination>.active>a:focus,.factory-bootstrap-425 .pagination>.active>a:hover,.factory-bootstrap-425 .pagination>.active>span,.factory-bootstrap-425 .pagination>.active>span:focus,.factory-bootstrap-425 .pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#1e8cbe;border-color:#0074a2}.factory-bootstrap-425 .pagination>.disabled>a,.factory-bootstrap-425 .pagination>.disabled>a:focus,.factory-bootstrap-425 .pagination>.disabled>a:hover,.factory-bootstrap-425 .pagination>.disabled>span,.factory-bootstrap-425 .pagination>.disabled>span:focus,.factory-bootstrap-425 .pagination>.disabled>span:hover{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.factory-bootstrap-425 .pagination-lg>li>a,.factory-bootstrap-425 .pagination-lg>li>span{padding:10px 16px;font-size:18px}.factory-bootstrap-425 .pagination-lg>li:first-child>a,.factory-bootstrap-425 .pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.factory-bootstrap-425 .pagination-lg>li:last-child>a,.factory-bootstrap-425 .pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.factory-bootstrap-425 .pagination-sm>li>a,.factory-bootstrap-425 .pagination-sm>li>span{padding:5px 10px;font-size:12px}.factory-bootstrap-425 .pagination-sm>li:first-child>a,.factory-bootstrap-425 .pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.factory-bootstrap-425 .pagination-sm>li:last-child>a,.factory-bootstrap-425 .pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.factory-bootstrap-425 .pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.factory-bootstrap-425 .pager:after,.factory-bootstrap-425 .pager:before{display:table;content:" "}.factory-bootstrap-425 .pager:after{clear:both}.factory-bootstrap-425 .pager li{display:inline}.factory-bootstrap-425 .pager li>a,.factory-bootstrap-425 .pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.factory-bootstrap-425 .pager li>a:focus,.factory-bootstrap-425 .pager li>a:hover{text-decoration:none;background-color:#eee}.factory-bootstrap-425 .pager .next>a,.factory-bootstrap-425 .pager .next>span{float:right}.factory-bootstrap-425 .pager .previous>a,.factory-bootstrap-425 .pager .previous>span{float:left}.factory-bootstrap-425 .pager .disabled>a,.factory-bootstrap-425 .pager .disabled>a:focus,.factory-bootstrap-425 .pager .disabled>a:hover,.factory-bootstrap-425 .pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.factory-bootstrap-425 .label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.factory-bootstrap-425 .label[href]:focus,.factory-bootstrap-425 .label[href]:hover{color:#fff;text-decoration:none;cursor:pointer}.factory-bootstrap-425 .label:empty{display:none}.factory-bootstrap-425 .btn .label{position:relative;top:-1px}.factory-bootstrap-425 .label-default{background-color:#999}.factory-bootstrap-425 .label-default[href]:focus,.factory-bootstrap-425 .label-default[href]:hover{background-color:gray}.factory-bootstrap-425 .label-primary{background-color:#428bca}.factory-bootstrap-425 .label-primary[href]:focus,.factory-bootstrap-425 .label-primary[href]:hover{background-color:#3071a9}.factory-bootstrap-425 .label-success{background-color:#5cb85c}.factory-bootstrap-425 .label-success[href]:focus,.factory-bootstrap-425 .label-success[href]:hover{background-color:#449d44}.factory-bootstrap-425 .label-info{background-color:#5bc0de}.factory-bootstrap-425 .label-info[href]:focus,.factory-bootstrap-425 .label-info[href]:hover{background-color:#31b0d5}.factory-bootstrap-425 .label-warning{background-color:#f0ad4e}.factory-bootstrap-425 .label-warning[href]:focus,.factory-bootstrap-425 .label-warning[href]:hover{background-color:#ec971f}.factory-bootstrap-425 .label-danger{background-color:#d9534f}.factory-bootstrap-425 .label-danger[href]:focus,.factory-bootstrap-425 .label-danger[href]:hover{background-color:#c9302c}.factory-bootstrap-425 .badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.factory-bootstrap-425 .badge:empty{display:none}.factory-bootstrap-425 .btn .badge{position:relative;top:-1px}.factory-bootstrap-425 a.badge:focus,.factory-bootstrap-425 a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.factory-bootstrap-425 .nav-pills>.active>a>.badge,.factory-bootstrap-425 a.list-group-item.active>.badge{color:#428bca;background-color:#fff}.factory-bootstrap-425 .nav-pills>li>a>.badge{margin-left:3px}.factory-bootstrap-425 .jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.factory-bootstrap-425 .jumbotron .h1,.factory-bootstrap-425 .jumbotron h1{line-height:1;color:inherit}.factory-bootstrap-425 .jumbotron p{line-height:1.4}.factory-bootstrap-425 .container .jumbotron{border-radius:6px}.factory-bootstrap-425 .jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.factory-bootstrap-425 .thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.factory-bootstrap-425 .thumbnail a>img,.factory-bootstrap-425 .thumbnail>img{display:block;height:auto;max-width:100%;margin-right:auto;margin-left:auto}.factory-bootstrap-425 a.thumbnail.active,.factory-bootstrap-425 a.thumbnail:focus,.factory-bootstrap-425 a.thumbnail:hover{border-color:#428bca}.factory-bootstrap-425 .thumbnail .caption{padding:9px;color:#333}.factory-bootstrap-425 .alert{border:1px solid transparent;border-radius:4px}.factory-bootstrap-425 .alert h4{margin-top:0;color:inherit}.factory-bootstrap-425 .alert .alert-link{font-weight:700}.factory-bootstrap-425 .alert>p,.factory-bootstrap-425 .alert>ul{margin-bottom:0}.factory-bootstrap-425 .alert>p+p{margin-top:5px}.factory-bootstrap-425 .alert-dismissable{padding-right:35px}.factory-bootstrap-425 .alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.factory-bootstrap-425 .alert-info{color:#31708f;background-color:#d9edf7}.factory-bootstrap-425 .alert-info hr{border-top-color:#a6e1ec}.factory-bootstrap-425 .alert-info .alert-link{color:#245269}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.factory-bootstrap-425 .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.factory-bootstrap-425 .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#2ea2cc;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.factory-bootstrap-425 .progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.factory-bootstrap-425 .progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.factory-bootstrap-425 .progress-bar-success{background-color:#5cb85c}.factory-bootstrap-425 .progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-425 .progress-bar-info{background-color:#5bc0de}.factory-bootstrap-425 .progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-425 .progress-bar-warning{background-color:#f0ad4e}.factory-bootstrap-425 .progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-425 .progress-bar-danger{background-color:#d9534f}.factory-bootstrap-425 .progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-425 .media,.factory-bootstrap-425 .media-body{overflow:hidden;zoom:1}.factory-bootstrap-425 .media,.factory-bootstrap-425 .media .media{margin-top:15px}.factory-bootstrap-425 .media:first-child{margin-top:0}.factory-bootstrap-425 .media-object{display:block}.factory-bootstrap-425 .media-heading{margin:0 0 5px}.factory-bootstrap-425 .media>.pull-left{margin-right:10px}.factory-bootstrap-425 .media>.pull-right{margin-left:10px}.factory-bootstrap-425 .media-list{padding-left:0;list-style:none}.factory-bootstrap-425 .list-group{padding-left:0;margin-bottom:20px}.factory-bootstrap-425 .list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.factory-bootstrap-425 .list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.factory-bootstrap-425 .list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.factory-bootstrap-425 .list-group-item>.badge{float:right}.factory-bootstrap-425 .list-group-item>.badge+.badge{margin-right:5px}.factory-bootstrap-425 a.list-group-item{color:#555}.factory-bootstrap-425 a.list-group-item .list-group-item-heading{color:#333}.factory-bootstrap-425 a.list-group-item:focus,.factory-bootstrap-425 a.list-group-item:hover{text-decoration:none;background-color:#f5f5f5}.factory-bootstrap-425 a.list-group-item.active,.factory-bootstrap-425 a.list-group-item.active:focus,.factory-bootstrap-425 a.list-group-item.active:hover{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.factory-bootstrap-425 a.list-group-item.active .list-group-item-heading,.factory-bootstrap-425 a.list-group-item.active:focus .list-group-item-heading,.factory-bootstrap-425 a.list-group-item.active:hover .list-group-item-heading{color:inherit}.factory-bootstrap-425 a.list-group-item.active .list-group-item-text,.factory-bootstrap-425 a.list-group-item.active:focus .list-group-item-text,.factory-bootstrap-425 a.list-group-item.active:hover .list-group-item-text{color:#e1edf7}.factory-bootstrap-425 .list-group-item-heading{margin-top:0;margin-bottom:5px}.factory-bootstrap-425 .list-group-item-text{margin-bottom:0;line-height:1.3}.factory-bootstrap-425 .panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px}.factory-bootstrap-425 .panel-body{padding:15px}.factory-bootstrap-425 .panel-body:after,.factory-bootstrap-425 .panel-body:before{display:table;content:" "}.factory-bootstrap-425 .panel-body:after{clear:both}.factory-bootstrap-425 .panel>.list-group{margin-bottom:0}.factory-bootstrap-425 .panel>.list-group .list-group-item{border-width:1px 0}.factory-bootstrap-425 .panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-425 .panel>.list-group .list-group-item:last-child{border-bottom:0}.factory-bootstrap-425 .panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.factory-bootstrap-425 .panel>.table,.factory-bootstrap-425 .panel>.table-responsive>.table{margin-bottom:0}.factory-bootstrap-425 .panel>.panel-body+.table,.factory-bootstrap-425 .panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.factory-bootstrap-425 .panel>.table>tbody:first-child td,.factory-bootstrap-425 .panel>.table>tbody:first-child th{border-top:0}.factory-bootstrap-425 .panel>.table-bordered,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered{border:0}.factory-bootstrap-425 .panel>.table-bordered>tbody>tr>td:first-child,.factory-bootstrap-425 .panel>.table-bordered>tbody>tr>th:first-child,.factory-bootstrap-425 .panel>.table-bordered>tfoot>tr>td:first-child,.factory-bootstrap-425 .panel>.table-bordered>tfoot>tr>th:first-child,.factory-bootstrap-425 .panel>.table-bordered>thead>tr>td:first-child,.factory-bootstrap-425 .panel>.table-bordered>thead>tr>th:first-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.factory-bootstrap-425 .panel>.table-bordered>tbody>tr>td:last-child,.factory-bootstrap-425 .panel>.table-bordered>tbody>tr>th:last-child,.factory-bootstrap-425 .panel>.table-bordered>tfoot>tr>td:last-child,.factory-bootstrap-425 .panel>.table-bordered>tfoot>tr>th:last-child,.factory-bootstrap-425 .panel>.table-bordered>thead>tr>td:last-child,.factory-bootstrap-425 .panel>.table-bordered>thead>tr>th:last-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.factory-bootstrap-425 .panel>.table-bordered>tbody>tr:last-child>td,.factory-bootstrap-425 .panel>.table-bordered>tbody>tr:last-child>th,.factory-bootstrap-425 .panel>.table-bordered>tfoot>tr:last-child>td,.factory-bootstrap-425 .panel>.table-bordered>tfoot>tr:last-child>th,.factory-bootstrap-425 .panel>.table-bordered>thead>tr:last-child>td,.factory-bootstrap-425 .panel>.table-bordered>thead>tr:last-child>th,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.factory-bootstrap-425 .panel>.table-responsive>.table-bordered>thead>tr:last-child>th{border-bottom:0}.factory-bootstrap-425 .panel>.table-responsive{margin-bottom:0;border:0}.factory-bootstrap-425 .panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.factory-bootstrap-425 .panel-heading>.dropdown .dropdown-toggle{color:inherit}.factory-bootstrap-425 .panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.factory-bootstrap-425 .panel-title>a{color:inherit}.factory-bootstrap-425 .panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.factory-bootstrap-425 .panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.factory-bootstrap-425 .panel-group .panel+.panel{margin-top:5px}.factory-bootstrap-425 .panel-group .panel-heading{border-bottom:0}.factory-bootstrap-425 .panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.factory-bootstrap-425 .panel-group .panel-footer{border-top:0}.factory-bootstrap-425 .panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.factory-bootstrap-425 .panel-default{border-color:#ddd}.factory-bootstrap-425 .panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.factory-bootstrap-425 .panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.factory-bootstrap-425 .panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.factory-bootstrap-425 .panel-primary{border-color:#428bca}.factory-bootstrap-425 .panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.factory-bootstrap-425 .panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.factory-bootstrap-425 .panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.factory-bootstrap-425 .panel-success{border-color:#d6e9c6}.factory-bootstrap-425 .panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.factory-bootstrap-425 .panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.factory-bootstrap-425 .panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.factory-bootstrap-425 .panel-warning{border-color:#faebcc}.factory-bootstrap-425 .panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.factory-bootstrap-425 .panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.factory-bootstrap-425 .panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.factory-bootstrap-425 .panel-danger{border-color:#ebccd1}.factory-bootstrap-425 .panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.factory-bootstrap-425 .panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.factory-bootstrap-425 .panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.factory-bootstrap-425 .panel-info{border-color:#bce8f1}.factory-bootstrap-425 .panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.factory-bootstrap-425 .panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.factory-bootstrap-425 .panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.factory-bootstrap-425 .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px}.factory-bootstrap-425 .well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.factory-bootstrap-425 .well-lg{padding:24px;border-radius:6px}.factory-bootstrap-425 .well-sm{padding:9px;border-radius:3px}.factory-bootstrap-425 .close{float:right;font-size:14px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.3;filter:alpha(opacity=30)}.factory-bootstrap-425 .alert .close{position:relative;top:-8px;right:-7px}.factory-bootstrap-425 .close:focus,.factory-bootstrap-425 .close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}.factory-bootstrap-425 button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.factory-bootstrap-425 .modal-open{overflow:hidden}.factory-bootstrap-425 .modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll;width:auto;margin-left:0;background-color:transparent;border:0}.factory-bootstrap-425 .modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.factory-bootstrap-425 .modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.factory-bootstrap-425 .modal-dialog{position:relative;z-index:1050;width:auto;margin:10px}.factory-bootstrap-425 .modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box}.factory-bootstrap-425 .modal-backdrop,.factory-bootstrap-425-modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.factory-bootstrap-425 .modal-backdrop.fade,.factory-bootstrap-425-modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.factory-bootstrap-425 .modal-backdrop.in,.factory-bootstrap-425-modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.factory-bootstrap-425 .modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.factory-bootstrap-425 .modal-header .close{margin-top:-2px}.factory-bootstrap-425 .modal-title{margin:0;line-height:1.428571429}.factory-bootstrap-425 .modal-body{position:relative;padding:20px;max-height:none}.factory-bootstrap-425 .modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.factory-bootstrap-425 .modal-footer:after,.factory-bootstrap-425 .modal-footer:before{display:table;content:" "}.factory-bootstrap-425 .modal-footer:after{clear:both}.factory-bootstrap-425 .modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.factory-bootstrap-425 .modal-footer .btn-group .btn+.btn{margin-left:-1px}.factory-bootstrap-425 .modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.factory-bootstrap-425 .modal-dialog{width:600px;margin:30px auto}.factory-bootstrap-425 .modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}}.factory-bootstrap-425 .tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.factory-bootstrap-425 .tooltip.in{opacity:.9;filter:alpha(opacity=90)}.factory-bootstrap-425 .tooltip.top{padding:5px 0;margin-top:-3px}.factory-bootstrap-425 .tooltip.right{padding:0 5px;margin-left:3px}.factory-bootstrap-425 .tooltip.bottom{padding:5px 0;margin-top:3px}.factory-bootstrap-425 .tooltip.left{padding:0 5px;margin-left:-3px}.factory-bootstrap-425 .tooltip-inner{width:400px;padding:15px 20px;color:#fff;text-align:left;text-decoration:none;background-color:#673ab7;border-radius:3px}.factory-bootstrap-425 .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.factory-bootstrap-425 .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#673ab7;border-width:5px 5px 0}.factory-bootstrap-425 .tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#673ab7;border-width:5px 5px 0}.factory-bootstrap-425 .tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#673ab7;border-width:5px 5px 0}.factory-bootstrap-425 .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#673ab7;border-width:5px 5px 5px 0}.factory-bootstrap-425 .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#673ab7;border-width:5px 0 5px 5px}.factory-bootstrap-425 .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#673ab7;border-width:0 5px 5px}.factory-bootstrap-425 .tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#673ab7;border-width:0 5px 5px}.factory-bootstrap-425 .tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#673ab7;border-width:0 5px 5px}.factory-bootstrap-425 .popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);background-clip:padding-box}.factory-bootstrap-425 .popover.top{margin-top:-10px}.factory-bootstrap-425 .popover.right{margin-left:10px}.factory-bootstrap-425 .popover.bottom{margin-top:10px}.factory-bootstrap-425 .popover.left{margin-left:-10px}.factory-bootstrap-425 .popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.factory-bootstrap-425 .popover-content{padding:9px 14px}.factory-bootstrap-425 .popover .arrow,.factory-bootstrap-425 .popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.factory-bootstrap-425 .popover .arrow{border-width:11px}.factory-bootstrap-425 .popover .arrow:after{border-width:10px;content:""}.factory-bootstrap-425 .popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.factory-bootstrap-425 .popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.factory-bootstrap-425 .popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.factory-bootstrap-425 .popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.factory-bootstrap-425 .popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);border-top-width:0}.factory-bootstrap-425 .popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.factory-bootstrap-425 .popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,.25);border-right-width:0}.factory-bootstrap-425 .popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.factory-bootstrap-425 .carousel{position:relative}.factory-bootstrap-425 .carousel-inner{position:relative;width:100%;overflow:hidden}.factory-bootstrap-425 .carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.factory-bootstrap-425 .carousel-inner>.item>a>img,.factory-bootstrap-425 .carousel-inner>.item>img{display:block;height:auto;max-width:100%;line-height:1}.factory-bootstrap-425 .carousel-inner>.active,.factory-bootstrap-425 .carousel-inner>.next,.factory-bootstrap-425 .carousel-inner>.prev{display:block}.factory-bootstrap-425 .carousel-inner>.active{left:0}.factory-bootstrap-425 .carousel-inner>.next,.factory-bootstrap-425 .carousel-inner>.prev{position:absolute;top:0;width:100%}.factory-bootstrap-425 .carousel-inner>.next{left:100%}.factory-bootstrap-425 .carousel-inner>.prev{left:-100%}.factory-bootstrap-425 .carousel-inner>.next.left,.factory-bootstrap-425 .carousel-inner>.prev.right{left:0}.factory-bootstrap-425 .carousel-inner>.active.left{left:-100%}.factory-bootstrap-425 .carousel-inner>.active.right{left:100%}.factory-bootstrap-425 .carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);opacity:.5;filter:alpha(opacity=50)}.factory-bootstrap-425 .carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.factory-bootstrap-425 .carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.factory-bootstrap-425 .carousel-control:focus,.factory-bootstrap-425 .carousel-control:hover{color:#fff;text-decoration:none;outline:0;opacity:.9;filter:alpha(opacity=90)}.factory-bootstrap-425 .carousel-control .glyphicon-chevron-left,.factory-bootstrap-425 .carousel-control .glyphicon-chevron-right,.factory-bootstrap-425 .carousel-control .icon-next,.factory-bootstrap-425 .carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.factory-bootstrap-425 .carousel-control .glyphicon-chevron-left,.factory-bootstrap-425 .carousel-control .icon-prev{left:50%}.factory-bootstrap-425 .carousel-control .glyphicon-chevron-right,.factory-bootstrap-425 .carousel-control .icon-next{right:50%}.factory-bootstrap-425 .carousel-control .icon-next,.factory-bootstrap-425 .carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.factory-bootstrap-425 .carousel-control .icon-prev:before{content:'\2039'}.factory-bootstrap-425 .carousel-control .icon-next:before{content:'\203a'}.factory-bootstrap-425 .carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.factory-bootstrap-425 .carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.factory-bootstrap-425 .carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.factory-bootstrap-425 .carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.factory-bootstrap-425 .carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.factory-bootstrap-425 .clearfix:after,.factory-bootstrap-425 .clearfix:before{display:table;content:" "}.factory-bootstrap-425 .clearfix:after{clear:both}.factory-bootstrap-425 .center-block{display:block;margin-right:auto;margin-left:auto}.factory-bootstrap-425 .pull-right{float:right!important}.factory-bootstrap-425 .pull-left{float:left!important}.factory-bootstrap-425 .hide{display:none!important}.factory-bootstrap-425 .show{display:block!important}.factory-bootstrap-425 .invisible{visibility:hidden}.factory-bootstrap-425 .text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.factory-bootstrap-425 .hidden{display:none!important;visibility:hidden!important}.factory-bootstrap-425 .affix{position:fixed}@-ms-viewport{width:device-width}.factory-bootstrap-425 .visible-lg,.factory-bootstrap-425 .visible-md,.factory-bootstrap-425 .visible-sm,.factory-bootstrap-425 .visible-xs,.factory-bootstrap-425 td.visible-lg,.factory-bootstrap-425 td.visible-md,.factory-bootstrap-425 td.visible-sm,.factory-bootstrap-425 td.visible-xs,.factory-bootstrap-425 th.visible-lg,.factory-bootstrap-425 th.visible-md,.factory-bootstrap-425 th.visible-sm,.factory-bootstrap-425 th.visible-xs,.factory-bootstrap-425 tr.visible-lg,.factory-bootstrap-425 tr.visible-md,.factory-bootstrap-425 tr.visible-sm,.factory-bootstrap-425 tr.visible-xs{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}table.visible-xs.visible-sm{display:table}tr.visible-xs.visible-sm{display:table-row!important}td.visible-xs.visible-sm,th.visible-xs.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}table.visible-xs.visible-md{display:table}tr.visible-xs.visible-md{display:table-row!important}td.visible-xs.visible-md,th.visible-xs.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-xs.visible-lg{display:block!important}table.visible-xs.visible-lg{display:table}tr.visible-xs.visible-lg{display:table-row!important}td.visible-xs.visible-lg,th.visible-xs.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-sm.visible-xs{display:block!important}table.visible-sm.visible-xs{display:table}tr.visible-sm.visible-xs{display:table-row!important}td.visible-sm.visible-xs,th.visible-sm.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}table.visible-sm.visible-md{display:table}tr.visible-sm.visible-md{display:table-row!important}td.visible-sm.visible-md,th.visible-sm.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-sm.visible-lg{display:block!important}table.visible-sm.visible-lg{display:table}tr.visible-sm.visible-lg{display:table-row!important}td.visible-sm.visible-lg,th.visible-sm.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-md.visible-xs{display:block!important}table.visible-md.visible-xs{display:table}tr.visible-md.visible-xs{display:table-row!important}td.visible-md.visible-xs,th.visible-md.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}table.visible-md.visible-sm{display:table}tr.visible-md.visible-sm{display:table-row!important}td.visible-md.visible-sm,th.visible-md.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-md.visible-lg{display:block!important}table.visible-md.visible-lg{display:table}tr.visible-md.visible-lg{display:table-row!important}td.visible-md.visible-lg,th.visible-md.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-lg.visible-xs{display:block!important}table.visible-lg.visible-xs{display:table}tr.visible-lg.visible-xs{display:table-row!important}td.visible-lg.visible-xs,th.visible-lg.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}table.visible-lg.visible-sm{display:table}tr.visible-lg.visible-sm{display:table-row!important}td.visible-lg.visible-sm,th.visible-lg.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}table.visible-lg.visible-md{display:table}tr.visible-lg.visible-md{display:table-row!important}td.visible-lg.visible-md,th.visible-lg.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}.factory-bootstrap-425 .hidden-xs{display:block!important}.factory-bootstrap-425 table.hidden-xs{display:table}.factory-bootstrap-425 tr.hidden-xs{display:table-row!important}.factory-bootstrap-425 td.hidden-xs,.factory-bootstrap-425 th.hidden-xs{display:table-cell!important}@media (max-width:767px){.hidden-xs,td.hidden-xs,th.hidden-xs,tr.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,td.hidden-xs.hidden-md,th.hidden-xs.hidden-md,tr.hidden-xs.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg{display:none!important}}.factory-bootstrap-425 .hidden-sm{display:block!important}.factory-bootstrap-425 table.hidden-sm{display:table}.factory-bootstrap-425 tr.hidden-sm{display:table-row!important}.factory-bootstrap-425 td.hidden-sm,.factory-bootstrap-425 th.hidden-sm{display:table-cell!important}@media (max-width:767px){.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm,td.hidden-sm,th.hidden-sm,tr.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,td.hidden-sm.hidden-md,th.hidden-sm.hidden-md,tr.hidden-sm.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg{display:none!important}}.factory-bootstrap-425 .hidden-md{display:block!important}.factory-bootstrap-425 table.hidden-md{display:table}.factory-bootstrap-425 tr.hidden-md{display:table-row!important}.factory-bootstrap-425 td.hidden-md,.factory-bootstrap-425 th.hidden-md{display:table-cell!important}@media (max-width:767px){.hidden-md.hidden-xs,td.hidden-md.hidden-xs,th.hidden-md.hidden-xs,tr.hidden-md.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,td.hidden-md.hidden-sm,th.hidden-md.hidden-sm,tr.hidden-md.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md,td.hidden-md,th.hidden-md,tr.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-md.hidden-lg,td.hidden-md.hidden-lg,th.hidden-md.hidden-lg,tr.hidden-md.hidden-lg{display:none!important}}.factory-bootstrap-425 .hidden-lg{display:block!important}.factory-bootstrap-425 table.hidden-lg{display:table}.factory-bootstrap-425 tr.hidden-lg{display:table-row!important}.factory-bootstrap-425 td.hidden-lg,.factory-bootstrap-425 th.hidden-lg{display:table-cell!important}@media (max-width:767px){.factory-bootstrap-425 .hidden-lg.hidden-xs,.factory-bootstrap-425 td.hidden-lg.hidden-xs,.factory-bootstrap-425 th.hidden-lg.hidden-xs,.factory-bootstrap-425 tr.hidden-lg.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.factory-bootstrap-425 .hidden-lg.hidden-sm,.factory-bootstrap-425 td.hidden-lg.hidden-sm,.factory-bootstrap-425 th.hidden-lg.hidden-sm,.factory-bootstrap-425 tr.hidden-lg.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.factory-bootstrap-425 .hidden-lg.hidden-md,.factory-bootstrap-425 td.hidden-lg.hidden-md,.factory-bootstrap-425 th.hidden-lg.hidden-md,.factory-bootstrap-425 tr.hidden-lg.hidden-md{display:none!important}}@media (min-width:1200px){.factory-bootstrap-425 .hidden-lg,.factory-bootstrap-425 td.hidden-lg,.factory-bootstrap-425 th.hidden-lg,.factory-bootstrap-425 tr.hidden-lg{display:none!important}}.factory-bootstrap-425 .visible-print,.factory-bootstrap-425 td.visible-print,.factory-bootstrap-425 th.visible-print,.factory-bootstrap-425 tr.visible-print{display:none!important}@media print{.factory-bootstrap-425 .visible-print{display:block!important}.factory-bootstrap-425 table.visible-print{display:table}.factory-bootstrap-425 tr.visible-print{display:table-row!important}.factory-bootstrap-425 td.visible-print,.factory-bootstrap-425 th.visible-print{display:table-cell!important}.factory-bootstrap-425 .hidden-print,.factory-bootstrap-425 td.hidden-print,.factory-bootstrap-425 th.hidden-print,.factory-bootstrap-425 tr.hidden-print{display:none!important}}/*!
12
  * Factory Default Bootstrap Theme
13
  *
14
  * The code is based on Bootstrap v2.1.1
22
  *
23
  * @package factory-bootstrap
24
  * @since 1.0.0
25
+ */.factory-bootstrap-425 .btn-danger,.factory-bootstrap-425 .btn-default,.factory-bootstrap-425 .btn-info,.factory-bootstrap-425 .btn-primary,.factory-bootstrap-425 .btn-success,.factory-bootstrap-425 .btn-warning{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-425 .btn-danger.active,.factory-bootstrap-425 .btn-danger:active,.factory-bootstrap-425 .btn-default.active,.factory-bootstrap-425 .btn-default:active,.factory-bootstrap-425 .btn-info.active,.factory-bootstrap-425 .btn-info:active,.factory-bootstrap-425 .btn-primary.active,.factory-bootstrap-425 .btn-primary:active,.factory-bootstrap-425 .btn-success.active,.factory-bootstrap-425 .btn-success:active,.factory-bootstrap-425 .btn-warning.active,.factory-bootstrap-425 .btn-warning:active{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.1);box-shadow:inset 0 1px 1px rgba(0,0,0,.1)}.factory-bootstrap-425 .btn.active,.factory-bootstrap-425 .btn:active{background-image:none}.factory-bootstrap-425 .btn-default{color:#555;border-color:#ccc;background:#f7f7f7;-webkit-box-shadow:inset 0 1px 0 #fff,0 1px 0 rgba(0,0,0,.08);box-shadow:inset 0 1px 0 #fff,0 1px 0 rgba(0,0,0,.08);vertical-align:top}.factory-bootstrap-425 .btn-default.active,.factory-bootstrap-425 .btn-default:active{background-color:#fff;border-color:#dbdbdb}.factory-bootstrap-425 .btn-gold{font-weight:700;padding:7px 12px;cursor:pointer;line-height:16px;display:inline-block;border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px;box-shadow:#e3e3e3 0 1px 1px;-moz-box-shadow:0 1px 1px rgba(000,000,000,.1),inset 0 1px 1px rgba(255,255,255,.7);-webkit-box-shadow:0 1px 1px rgba(000,000,000,.1),inset 0 1px 1px rgba(255,255,255,.7);text-shadow:1px 1px 0 #ffe8b2;color:#7c5d1b;border:1px solid #d6a437;background:#feeb80}.factory-bootstrap-425 .btn-gold:focus,.factory-bootstrap-425 .btn-gold:hover{background:#fef0a1}.factory-bootstrap-425 .btn-gold.active,.factory-bootstrap-425 .btn-gold:active{background:#fef0a1;-webkit-box-shadow:inset 0 3px 8px 0 #f8ba36;box-shadow:inset 0 3px 8px 0 #f8ba36}.factory-bootstrap-425 .btn-primary{background:#2ea2cc;border-color:#0074a2;-webkit-box-shadow:inset 0 1px 0 rgba(120,200,230,.5),0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 rgba(120,200,230,.5),0 1px 0 rgba(0,0,0,.15);color:#fff;text-decoration:none}.factory-bootstrap-425 .btn-primary:focus,.factory-bootstrap-425 .btn-primary:hover{background:#1e8cbe;border-color:#0074a2;-webkit-box-shadow:inset 0 1px 0 rgba(120,200,230,.6);box-shadow:inset 0 1px 0 rgba(120,200,230,.6);color:#fff}.factory-bootstrap-425 .btn-primary.active,.factory-bootstrap-425 .btn-primary:active{background-color:#2d6ca2;border-color:#2b669a}.factory-bootstrap-425 .btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);background-repeat:repeat-x;border-color:#3e8f3e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-425 .btn-success:focus,.factory-bootstrap-425 .btn-success:hover{background-color:#419641;background-position:0 -15px}.factory-bootstrap-425 .btn-success.active,.factory-bootstrap-425 .btn-success:active{background-color:#419641;border-color:#3e8f3e}.factory-bootstrap-425 .btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);background-repeat:repeat-x;border-color:#e38d13;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-425 .btn-warning:focus,.factory-bootstrap-425 .btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.factory-bootstrap-425 .btn-warning.active,.factory-bootstrap-425 .btn-warning:active{background-color:#eb9316;border-color:#e38d13}.factory-bootstrap-425 .btn-danger{color:#fff;background:#d9534f;border-color:#d43f3a}.factory-bootstrap-425 .btn-danger.active,.factory-bootstrap-425 .btn-danger:active,.factory-bootstrap-425 .btn-danger:focus,.factory-bootstrap-425 .btn-danger:hover,.factory-bootstrap-425 .open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.factory-bootstrap-425 .btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);background-repeat:repeat-x;border-color:#28a4c9;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-425 .btn-info:focus,.factory-bootstrap-425 .btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.factory-bootstrap-425 .btn-info.active,.factory-bootstrap-425 .btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.factory-bootstrap-425 .img-thumbnail,.factory-bootstrap-425 .thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.factory-bootstrap-425 .dropdown-menu>li>a:focus,.factory-bootstrap-425 .dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.factory-bootstrap-425 .dropdown-menu>.active>a,.factory-bootstrap-425 .dropdown-menu>.active>a:focus,.factory-bootstrap-425 .dropdown-menu>.active>a:hover{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.factory-bootstrap-425 .navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.factory-bootstrap-425 .navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.factory-bootstrap-425 .navbar-brand,.factory-bootstrap-425 .navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.factory-bootstrap-425 .navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-425 .navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.factory-bootstrap-425 .navbar-inverse .navbar-brand,.factory-bootstrap-425 .navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.factory-bootstrap-425 .navbar-fixed-bottom,.factory-bootstrap-425 .navbar-fixed-top,.factory-bootstrap-425 .navbar-static-top{border-radius:0}.factory-bootstrap-425 .alert{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.factory-bootstrap-425 .alert .actions{padding-top:10px}.factory-bootstrap-425 .alert-success{color:#3c763d;background-color:#dff0d8;border-bottom:2px solid #c8e5bc}.factory-bootstrap-425 .alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0)}.factory-bootstrap-425 .alert{text-shadow:none;box-shadow:none;margin:0;margin-top:10px;margin-bottom:10px;padding:10px}.factory-bootstrap-425 .alert-normal,.factory-bootstrap-425 .alert-warning{background:#fcf8e3;color:#8a6d3b;border:1px solid #b8823b}.factory-bootstrap-425 .alert-danger{background:#cf4944;color:#fff;border-bottom:2px solid #b23e3a}.factory-bootstrap-425 .alert-danger a:not(.btn),.factory-bootstrap-425 .alert-error a:not(.btn){color:#fff}.factory-bootstrap-425 .progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.factory-bootstrap-425 .progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.factory-bootstrap-425 .progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.factory-bootstrap-425 .progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.factory-bootstrap-425 .progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.factory-bootstrap-425 .progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.factory-bootstrap-425 .list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.factory-bootstrap-425 .list-group-item.active,.factory-bootstrap-425 .list-group-item.active:focus,.factory-bootstrap-425 .list-group-item.active:hover{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0)}.factory-bootstrap-425 .panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.factory-bootstrap-425 .panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.factory-bootstrap-425 .panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.factory-bootstrap-425 .panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.factory-bootstrap-425 .panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.factory-bootstrap-425 .panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.factory-bootstrap-425 .panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.factory-bootstrap-425 .well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}.factory-bootstrap-425 .factory-after{margin-left:7px;display:inline-block}.factory-bootstrap-425 .factory-hidden{display:none}.factory-bootstrap-425 .factory-ajax-loader{width:25px;height:25px;background:url(../assets/images/loader-sm-tr.gif)}.factory-control-error{background-color:rgba(0,0,0,.8);white-space:normal;z-index:10;font-weight:400;line-height:150%;border-radius:4px;color:#fff;font-size:13px;margin-top:5px;padding:4px 10px 3px;max-width:500px;display:inline-block}.factory-control-error i{margin:0 7px 0 1px}
libs/factory/bootstrap/assets/css-min/bootstrap.ectoplasm.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .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-412 .btn-primary:focus,.factory-bootstrap-412 .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-412 .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-412 .btn-primary:disabled,.factory-bootstrap-412 .btn-primary[disabled]{color:#cfd1c7!important;background:#89993a!important;border-color:#727f30!important;text-shadow:none!important}.factory-bootstrap-412 .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-412 .pagination>.active>a,.factory-bootstrap-412 .pagination>.active>a:focus,.factory-bootstrap-412 .pagination>.active>a:hover,.factory-bootstrap-412 .pagination>.active>span,.factory-bootstrap-412 .pagination>.active>span:focus,.factory-bootstrap-412 .pagination>.active>span:hover{background-color:#a3b745;border-color:#839237}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .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-425 .btn-primary:focus,.factory-bootstrap-425 .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-425 .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-425 .btn-primary:disabled,.factory-bootstrap-425 .btn-primary[disabled]{color:#cfd1c7!important;background:#89993a!important;border-color:#727f30!important;text-shadow:none!important}.factory-bootstrap-425 .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-425 .pagination>.active>a,.factory-bootstrap-425 .pagination>.active>a:focus,.factory-bootstrap-425 .pagination>.active>a:hover,.factory-bootstrap-425 .pagination>.active>span,.factory-bootstrap-425 .pagination>.active>span:focus,.factory-bootstrap-425 .pagination>.active>span:hover{background-color:#a3b745;border-color:#839237}
libs/factory/bootstrap/assets/css-min/bootstrap.form-group.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .factory-form-group .factory-legend{padding:9px 12px;background-color:#f9f9f9}.factory-bootstrap-412 .factory-form-group .factory-title{font-weight:700;font-size:14px;line-height:14px;color:#555;margin:0}.factory-bootstrap-412 .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-412 .factory-form-group .factory-hint-icon.factory-hint-icon-green{background:#8bc34a}.factory-bootstrap-412 .factory-form-group .factory-hint-icon.factory-hint-icon-grey{background:#9e9e9e}.factory-bootstrap-412 .factory-form-group .factory-hint-icon.factory-hint-icon-red{background:#E91E63}.factory-bootstrap-412 .factory-form-group .factory-hint{margin:0;font-size:12px;line-height:16px;margin-top:6px}.factory-bootstrap-412 .factory-form-group+.factory-form-group{margin-top:30px}.factory-bootstrap-412 .factory-form-group legend+.control-group{margin-top:0}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .factory-form-group .factory-legend{padding:9px 12px;background-color:#f9f9f9}.factory-bootstrap-425 .factory-form-group .factory-title{font-weight:700;font-size:14px;line-height:14px;color:#555;margin:0}.factory-bootstrap-425 .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-425 .factory-form-group .factory-hint-icon.factory-hint-icon-green{background:#8bc34a}.factory-bootstrap-425 .factory-form-group .factory-hint-icon.factory-hint-icon-grey{background:#9e9e9e}.factory-bootstrap-425 .factory-form-group .factory-hint-icon.factory-hint-icon-red{background:#E91E63}.factory-bootstrap-425 .factory-form-group .factory-hint{margin:0;font-size:12px;line-height:16px;margin-top:6px}.factory-bootstrap-425 .factory-form-group+.factory-form-group{margin-top:30px}.factory-bootstrap-425 .factory-form-group legend+.control-group{margin-top:0}
libs/factory/bootstrap/assets/css-min/bootstrap.light.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .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-412 .btn-primary:focus,.factory-bootstrap-412 .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-412 .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-412 .btn-primary:disabled,.factory-bootstrap-412 .btn-primary[disabled]{color:#c7cfd1!important;background:#0384a4!important;border-color:#036881!important;text-shadow:none!important}.factory-bootstrap-412 .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-412 .pagination>.active>a,.factory-bootstrap-412 .pagination>.active>a:focus,.factory-bootstrap-412 .pagination>.active>a:hover,.factory-bootstrap-412 .pagination>.active>span,.factory-bootstrap-412 .pagination>.active>span:focus,.factory-bootstrap-412 .pagination>.active>span:hover{background-color:#04a4cc;border-color:#037c9a}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .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-425 .btn-primary:focus,.factory-bootstrap-425 .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-425 .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-425 .btn-primary:disabled,.factory-bootstrap-425 .btn-primary[disabled]{color:#c7cfd1!important;background:#0384a4!important;border-color:#036881!important;text-shadow:none!important}.factory-bootstrap-425 .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-425 .pagination>.active>a,.factory-bootstrap-425 .pagination>.active>a:focus,.factory-bootstrap-425 .pagination>.active>a:hover,.factory-bootstrap-425 .pagination>.active>span,.factory-bootstrap-425 .pagination>.active>span:focus,.factory-bootstrap-425 .pagination>.active>span:hover{background-color:#04a4cc;border-color:#037c9a}
libs/factory/bootstrap/assets/css-min/bootstrap.midnight.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .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-412 .btn-primary:focus,.factory-bootstrap-412 .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-412 .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-412 .btn-primary:disabled,.factory-bootstrap-412 .btn-primary[disabled]{color:#d1c7c7!important;background:#d92c23!important;border-color:#ba251e!important;text-shadow:none!important}.factory-bootstrap-412 .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-412 .pagination>.active>a,.factory-bootstrap-412 .pagination>.active>a:focus,.factory-bootstrap-412 .pagination>.active>a:hover,.factory-bootstrap-412 .pagination>.active>span,.factory-bootstrap-412 .pagination>.active>span:focus,.factory-bootstrap-412 .pagination>.active>span:hover{background-color:#e14d43;border-color:#d02a21}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .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-425 .btn-primary:focus,.factory-bootstrap-425 .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-425 .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-425 .btn-primary:disabled,.factory-bootstrap-425 .btn-primary[disabled]{color:#d1c7c7!important;background:#d92c23!important;border-color:#ba251e!important;text-shadow:none!important}.factory-bootstrap-425 .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-425 .pagination>.active>a,.factory-bootstrap-425 .pagination>.active>a:focus,.factory-bootstrap-425 .pagination>.active>a:hover,.factory-bootstrap-425 .pagination>.active>span,.factory-bootstrap-425 .pagination>.active>span:focus,.factory-bootstrap-425 .pagination>.active>span:hover{background-color:#e14d43;border-color:#d02a21}
libs/factory/bootstrap/assets/css-min/bootstrap.ocean.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .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-412 .btn-primary:focus,.factory-bootstrap-412 .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-412 .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-412 .btn-primary:disabled,.factory-bootstrap-412 .btn-primary[disabled]{color:#c7d1c8!important;background:#86a988!important;border-color:#719a74!important;text-shadow:none!important}.factory-bootstrap-412 .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-412 .pagination>.active>a,.factory-bootstrap-412 .pagination>.active>a:focus,.factory-bootstrap-412 .pagination>.active>a:hover,.factory-bootstrap-412 .pagination>.active>span,.factory-bootstrap-412 .pagination>.active>span:focus,.factory-bootstrap-412 .pagination>.active>span:hover{background-color:#9ebaa0;border-color:#80a583}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .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-425 .btn-primary:focus,.factory-bootstrap-425 .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-425 .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-425 .btn-primary:disabled,.factory-bootstrap-425 .btn-primary[disabled]{color:#c7d1c8!important;background:#86a988!important;border-color:#719a74!important;text-shadow:none!important}.factory-bootstrap-425 .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-425 .pagination>.active>a,.factory-bootstrap-425 .pagination>.active>a:focus,.factory-bootstrap-425 .pagination>.active>a:hover,.factory-bootstrap-425 .pagination>.active>span,.factory-bootstrap-425 .pagination>.active>span:focus,.factory-bootstrap-425 .pagination>.active>span:hover{background-color:#9ebaa0;border-color:#80a583}
libs/factory/bootstrap/assets/css-min/bootstrap.separator.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .factory-separator{border-bottom:1px solid #f9f9f9;border-top:1px solid #d1d1d1;margin-bottom:25px}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .factory-separator{border-bottom:1px solid #f9f9f9;border-top:1px solid #d1d1d1;margin-bottom:25px}
libs/factory/bootstrap/assets/css-min/bootstrap.sunrise.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .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-412 .btn-primary:focus,.factory-bootstrap-412 .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-412 .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-412 .btn-primary:disabled,.factory-bootstrap-412 .btn-primary[disabled]{color:#d1cbc7!important;background:#cc6c23!important;border-color:#ad5c1e!important;text-shadow:none!important}.factory-bootstrap-412 .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-412 .pagination>.active>a,.factory-bootstrap-412 .pagination>.active>a:focus,.factory-bootstrap-412 .pagination>.active>a:hover,.factory-bootstrap-412 .pagination>.active>span,.factory-bootstrap-412 .pagination>.active>span:focus,.factory-bootstrap-412 .pagination>.active>span:hover{background-color:#dd823b;border-color:#c36822}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .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-425 .btn-primary:focus,.factory-bootstrap-425 .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-425 .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-425 .btn-primary:disabled,.factory-bootstrap-425 .btn-primary[disabled]{color:#d1cbc7!important;background:#cc6c23!important;border-color:#ad5c1e!important;text-shadow:none!important}.factory-bootstrap-425 .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-425 .pagination>.active>a,.factory-bootstrap-425 .pagination>.active>a:focus,.factory-bootstrap-425 .pagination>.active>a:hover,.factory-bootstrap-425 .pagination>.active>span,.factory-bootstrap-425 .pagination>.active>span:focus,.factory-bootstrap-425 .pagination>.active>span:hover{background-color:#dd823b;border-color:#c36822}
libs/factory/bootstrap/assets/css-min/control.checkbox.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- #side-sortables .factory-bootstrap-412 .factory-buttons-way{float:right;position:relative;top:-25px;left:5px;border:3px solid #f9f9f9;border-radius:4px}.factory-bootstrap-412 .factory-buttons-way{border:3px solid #f9f9f9;border-radius:4px}.factory-bootstrap-412 .factory-buttons-way button{padding-left:10px;padding-right:10px}.factory-bootstrap-412 .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-412 .factory-checkbox-tumbler-hint{margin-top:5px}.factory-bootstrap-412 .factory-checkbox-tumbler-hint .factory-tumbler-content{display:inline-block;background-color:#ffd;padding:1px 5px}.admin-color-light .factory-bootstrap-412 .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-412 .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-412 .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-412 .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-412 .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-412 .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-412 .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}
8
  */
9
 
10
 
11
+ #side-sortables .factory-bootstrap-425 .factory-buttons-way{float:right;position:relative;top:-25px;left:5px;border:3px solid #f9f9f9;border-radius:4px}.factory-bootstrap-425 .factory-buttons-way{border:3px solid #f9f9f9;border-radius:4px}.factory-bootstrap-425 .factory-buttons-way button{padding-left:10px;padding-right:10px}.factory-bootstrap-425 .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-425 .factory-checkbox-tumbler-hint{margin-top:5px}.factory-bootstrap-425 .factory-checkbox-tumbler-hint .factory-tumbler-content{display:inline-block;background-color:#ffd;padding:1px 5px}.admin-color-light .factory-bootstrap-425 .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-425 .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-425 .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-425 .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-425 .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-425 .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-425 .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}
libs/factory/bootstrap/assets/css-min/control.dropdown.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .factory-dropdown.factory-buttons-way .fa{margin-right:6px;position:relative}.factory-bootstrap-412 .factory-dropdown.factory-buttons-way{border:0;border-radius:0}.factory-bootstrap-412 .factory-hints .factory-hint{margin-top:5px;display:inline-block;background-color:#ffd;padding:1px 5px}.admin-color-light .factory-bootstrap-412 .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-412 .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-412 .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-412 .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-412 .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-412 .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-412 .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-412 .factory-dropdown.factory-ddslick-way .dd-select{background-color:#fff!important}.factory-bootstrap-412 .factory-dropdown.factory-ddslick-way label{margin-bottom:1px}.factory-bootstrap-412 .factory-dropdown.factory-ddslick-way .dd-option,.factory-bootstrap-412 .factory-dropdown.factory-ddslick-way .dd-selected{padding:8px 12px 8px 11px!important}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .factory-dropdown.factory-buttons-way .fa{margin-right:6px;position:relative}.factory-bootstrap-425 .factory-dropdown.factory-buttons-way{border:0;border-radius:0}.factory-bootstrap-425 .factory-hints .factory-hint{margin-top:5px;display:inline-block;background-color:#ffd;padding:1px 5px}.admin-color-light .factory-bootstrap-425 .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-425 .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-425 .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-425 .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-425 .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-425 .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-425 .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-425 .factory-dropdown.factory-ddslick-way .dd-select{background-color:#fff!important}.factory-bootstrap-425 .factory-dropdown.factory-ddslick-way label{margin-bottom:1px}.factory-bootstrap-425 .factory-dropdown.factory-ddslick-way .dd-option,.factory-bootstrap-425 .factory-dropdown.factory-ddslick-way .dd-selected{padding:8px 12px 8px 11px!important}
libs/factory/bootstrap/assets/css-min/control.multiple-textbox.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .factory-mtextbox-item{position:relative;margin-bottom:5px}.factory-bootstrap-412 .factory-mtextbox-item input,.factory-mtextbox-remove-item{display:inline-block}.factory-bootstrap-412 .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-412 .factory-mtextbox-item .factory-mtextbox-remove-item:focus,.factory-bootstrap-412 .factory-mtextbox-item .factory-mtextbox-remove-item:hover{box-shadow:none;outline:0}.factory-bootstrap-412 .factory-mtextbox-add-item{display:block;margin-top:10px}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .factory-mtextbox-item{position:relative;margin-bottom:5px}.factory-bootstrap-425 .factory-mtextbox-item input,.factory-mtextbox-remove-item{display:inline-block}.factory-bootstrap-425 .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-425 .factory-mtextbox-item .factory-mtextbox-remove-item:focus,.factory-bootstrap-425 .factory-mtextbox-item .factory-mtextbox-remove-item:hover{box-shadow:none;outline:0}.factory-bootstrap-425 .factory-mtextbox-add-item{display:block;margin-top:10px}
libs/factory/bootstrap/assets/css-min/holder.more-link.min.css CHANGED
@@ -8,4 +8,4 @@
8
  */
9
 
10
 
11
- .factory-bootstrap-412 .factory-more-link-content{border-top:1px dashed #DDD;padding-top:25px;width:100%;padding-right:20px;position:relative}.factory-bootstrap-412 .factory-tab .factory-more-link-show{display:inline-block;text-decoration:none;border-bottom:1px dotted #21759b;position:relative}.factory-bootstrap-412 .factory-tab .factory-more-link-show:hover{border-color:#d54e21}.factory-bootstrap-412 .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-412 .factory-tab .factory-more-link-hide:hover{color:#999}
8
  */
9
 
10
 
11
+ .factory-bootstrap-425 .factory-more-link-content{border-top:1px dashed #DDD;padding-top:25px;width:100%;padding-right:20px;position:relative}.factory-bootstrap-425 .factory-tab .factory-more-link-show{display:inline-block;text-decoration:none;border-bottom:1px dotted #21759b;position:relative}.factory-bootstrap-425 .factory-tab .factory-more-link-show:hover{border-color:#d54e21}.factory-bootstrap-425 .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-425 .factory-tab .factory-more-link-hide:hover{color:#999}
libs/factory/bootstrap/assets/css-min/index.php DELETED
File without changes
libs/factory/bootstrap/assets/images/index.php DELETED
File without changes
libs/factory/bootstrap/assets/index.php DELETED
File without changes
libs/factory/bootstrap/assets/js-min/bootstrap.dropdown.min.js CHANGED
@@ -7,4 +7,4 @@
7
  * Support: http://webcraftic.com/contact-us/
8
  */
9
 
10
- +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.factoryBootstrap412_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.factoryBootstrap412_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);
7
  * Support: http://webcraftic.com/contact-us/
8
  */
9
 
10
+ +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.factoryBootstrap425_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.factoryBootstrap425_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);
libs/factory/bootstrap/assets/js-min/control.checkbox.min.js CHANGED
@@ -7,4 +7,4 @@
7
  * Support: http://webcraftic.com/contact-us/
8
  */
9
 
10
- !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.attr("checked","checked"),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.removeAttr("checked"),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]&&(console.log(l[m]),a(m).val(l[m]))}}}},this.executeEvents(this.$result)};a.fn.factoryBootstrap412_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.factoryBootstrap412_checkboxControl.Constructor=b,a(function(){a(".factory-bootstrap-412 .factory-checkbox.factory-buttons-way").factoryBootstrap412_checkboxControl()})}(jQuery);
7
  * Support: http://webcraftic.com/contact-us/
8
  */
9
 
10
+ !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.attr("checked","checked"),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.removeAttr("checked"),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]&&(console.log(l[m]),a(m).val(l[m]))}}}},this.executeEvents(this.$result)};a.fn.factoryBootstrap425_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.factoryBootstrap425_checkboxControl.Constructor=b,a(function(){a(".factory-bootstrap-425 .factory-checkbox.factory-buttons-way").factoryBootstrap425_checkboxControl()})}(jQuery);
libs/factory/bootstrap/assets/js-min/control.dropdown.min.js CHANGED
@@ -7,4 +7,4 @@
7
  * Support: http://webcraftic.com/contact-us/
8
  */
9
 
10
- !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.factoryBootstrap412_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.factoryBootstrap412_dropdownControl.Constructor=b,a(function(){a(".factory-bootstrap-412 .factory-dropdown").factoryBootstrap412_dropdownControl()})}(jQuery);
7
  * Support: http://webcraftic.com/contact-us/
8
  */
9
 
10
+ !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.factoryBootstrap425_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.factoryBootstrap425_dropdownControl.Constructor=b,a(function(){a(".factory-bootstrap-425 .factory-dropdown").factoryBootstrap425_dropdownControl()})}(jQuery);
libs/factory/bootstrap/assets/js-min/control.list.min.js CHANGED
@@ -7,4 +7,4 @@
7
  * Support: http://webcraftic.com/contact-us/
8
  */
9
 
10
- !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.factoryBootstrap412_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.factoryBootstrap412_listControl.Constructor=b,a(function(){a(".factory-bootstrap-412 .factory-list").factoryBootstrap412_listControl()})}(jQuery);
7
  * Support: http://webcraftic.com/contact-us/
8
  */
9
 
10
+ !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.factoryBootstrap425_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.factoryBootstrap425_listControl.Constructor=b,a(function(){a(".factory-bootstrap-425 .factory-list").factoryBootstrap425_listControl()})}(jQuery);
libs/factory/bootstrap/assets/js-min/control.multiple-textbox.min.js CHANGED
@@ -7,4 +7,4 @@
7
  * Support: http://webcraftic.com/contact-us/
8
  */
9
 
10
- !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.factoryBootstrap412_MultipleTextboxControl=function(){return this.each(function(){new b(this)})},a(function(){a(".factory-bootstrap-412 .factory-multiple-textbox-group").factoryBootstrap412_MultipleTextboxControl()})}(jQuery);
7
  * Support: http://webcraftic.com/contact-us/
8
  */
9
 
10
+ !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.factoryBootstrap425_MultipleTextboxControl=function(){return this.each(function(){new b(this)})},a(function(){a(".factory-bootstrap-425 .factory-multiple-textbox-group").factoryBootstrap425_MultipleTextboxControl()})}(jQuery);
libs/factory/bootstrap/assets/js-min/index.php DELETED
File without changes
libs/factory/bootstrap/boot.php CHANGED
@@ -1,37 +1,46 @@
1
  <?php
2
- /**
3
- * Factory Bootstrap
4
- *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
- * @copyright (c) 2018, Webcraftic Ltd
7
- *
8
- * @package factory-bootstrap
9
- * @since 1.0.0
10
- */
11
-
12
- // Exit if accessed directly
13
- if( !defined('ABSPATH') ) {
14
- exit;
15
- }
16
-
17
- // module provides function only for the admin area
18
- if( !is_admin() ) {
19
- return;
20
- }
21
-
22
- if( defined('FACTORY_BOOTSTRAP_412_LOADED') ) {
23
- return;
24
- }
25
- define('FACTORY_BOOTSTRAP_412_LOADED', true);
26
-
27
- define('FACTORY_BOOTSTRAP_412_DIR', dirname(__FILE__));
28
- define('FACTORY_BOOTSTRAP_412_URL', plugins_url(null, __FILE__));
29
-
30
- // sets version of admin interface
31
- define('FACTORY_BOOTSTRAP_412_VERSION', 'FACTORY_BOOTSTRAP_412');
32
-
33
- if( !defined('FACTORY_FLAT_ADMIN') ) {
34
- define('FACTORY_FLAT_ADMIN', true);
35
- }
36
-
37
- include_once(FACTORY_BOOTSTRAP_412_DIR . '/includes/functions.php');
 
 
 
 
 
 
 
 
 
1
  <?php
2
+ /**
3
+ * Factory Bootstrap
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @since 1.0.0
7
+ * @package factory-bootstrap
8
+ * @copyright (c) 2018, Webcraftic Ltd
9
+ *
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+ // module provides function only for the admin area
18
+ if ( ! is_admin() ) {
19
+ return;
20
+ }
21
+
22
+ if ( defined( 'FACTORY_BOOTSTRAP_425_LOADED' ) ) {
23
+ return;
24
+ }
25
+
26
+ define( 'FACTORY_BOOTSTRAP_425_VERSION', '4.2.5' );
27
+ define( 'FACTORY_BOOTSTRAP_425_LOADED', true );
28
+
29
+ if ( ! defined( 'FACTORY_FLAT_ADMIN' ) ) {
30
+ define( 'FACTORY_FLAT_ADMIN', true );
31
+ }
32
+
33
+ define( 'FACTORY_BOOTSTRAP_425_DIR', dirname( __FILE__ ) );
34
+ define( 'FACTORY_BOOTSTRAP_425_URL', plugins_url( null, __FILE__ ) );
35
+
36
+ require_once( FACTORY_BOOTSTRAP_425_DIR . '/includes/functions.php' );
37
+
38
+ /**
39
+ * @param Wbcr_Factory424_Plugin $plugin
40
+ */
41
+ add_action( 'wbcr_factory_bootstrap_425_plugin_created', function ( $plugin ) {
42
+ $manager = new Wbcr_FactoryBootstrap425_Manager( $plugin );
43
+ $plugin->setBootstap( $manager );
44
+ } );
45
+
46
+
libs/factory/bootstrap/includes/functions.php CHANGED
@@ -1,292 +1,236 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /**
3
- * This file manages assets of the Factory Bootstap.
4
  *
5
- * @author Alex Kovalev <alex@byonepress.com>
6
- * @author Paul Kashtanoff <paul@byonepress.com>
7
- * @copyright (c) 2018, OnePress Ltd
 
 
 
 
8
  *
9
- * @package factory-bootstrap
10
- * @since 1.0.0
11
  */
12
-
13
- add_action('wbcr_factory_bootstrap_412_plugin_created', 'wbcr_factory_bootstrap_412_plugin_created');
14
-
15
  /**
16
- * @param Wbcr_Factory412_Plugin $plugin
 
 
17
  */
18
- function wbcr_factory_bootstrap_412_plugin_created($plugin)
19
- {
20
- $manager = new Wbcr_FactoryBootstrap412_Manager($plugin);
21
- $plugin->setBootstap($manager);
 
22
  }
23
-
24
- if( !class_exists('Wbcr_FactoryBootstrap412_Manager') ) {
25
-
26
- /**
27
- * The Bootstrap Manager class.
28
- *
29
- * @since 3.2.0
30
- */
31
- class Wbcr_FactoryBootstrap412_Manager {
32
-
33
- /**
34
- * A plugin for which the manager was created.
35
- *
36
- * @since 3.2.0
37
- * @var Wbcr_Factory412_Plugin
38
- */
39
- public $plugin;
40
-
41
- /**
42
- * Contains scripts to include.
43
- *
44
- * @since 3.2.0
45
- * @var string[]
46
- */
47
- public $scripts = array();
48
-
49
- /**
50
- * Contains styles to include.
51
- *
52
- * @since 3.2.0
53
- * @var string[]
54
- */
55
- public $styles = array();
56
-
57
- /**
58
- * Createas a new instance of the license api for a given plugin.
59
- *
60
- * @since 1.0.0
61
- */
62
- public function __construct(Wbcr_Factory412_Plugin $plugin)
63
- {
64
- $this->plugin = $plugin;
65
-
66
- add_action('admin_enqueue_scripts', array($this, 'loadAssets'));
67
- add_filter('admin_body_class', array($this, 'adminBodyClass'));
68
- }
69
-
70
- /**
71
- * Includes the Bootstrap scripts.
72
- * @since 3.2.0
73
- * @param array|string $scripts
74
- */
75
- public function enqueueScript($scripts)
76
- {
77
- if( is_array($scripts) ) {
78
- foreach($scripts as $script) {
79
- if( !in_array($script, $this->scripts) ) {
80
- $this->scripts[] = $script;
81
- }
82
- }
83
- } else {
84
- if( !in_array($scripts, $this->scripts) ) {
85
- $this->scripts[] = $scripts;
86
- }
87
  }
88
  }
89
-
90
- /**
91
- * * Includes the Bootstrap styles.
92
- *
93
- * @since 3.2.0
94
- * @param array|string $styles
95
- */
96
- public function enqueueStyle($styles)
97
- {
98
-
99
- if( is_array($styles) ) {
100
- foreach($styles as $style) {
101
- if( !in_array($style, $this->styles) ) {
102
- $this->styles[] = $style;
103
- }
104
- }
105
- } else {
106
- if( !in_array($styles, $this->styles) ) {
107
- $this->styles[] = $styles;
108
- }
109
- }
110
  }
111
-
112
- /**
113
- * Loads Bootstrap assets.
114
- *
115
- * @see admin_enqueue_scripts
116
- *
117
- * @since 3.2.0
118
- * @return void
119
- */
120
- public function loadAssets($hook)
121
- {
122
-
123
- do_action('wbcr_factory_412_bootstrap_enqueue_scripts', $hook);
124
- do_action('wbcr_factory_412_bootstrap_enqueue_scripts_' . $this->plugin->getPluginName(), $hook);
125
 
126
- $dependencies = array();
127
- if( !empty($this->scripts) ) {
128
- $dependencies[] = 'jquery';
129
- $dependencies[] = 'jquery-ui-core';
130
- $dependencies[] = 'jquery-ui-widget';
131
- }
132
-
133
- foreach($this->scripts as $script) {
134
- switch( $script ) {
135
- case 'plugin.iris':
136
- $dependencies[] = 'jquery-ui-widget';
137
- $dependencies[] = 'jquery-ui-slider';
138
- $dependencies[] = 'jquery-ui-draggable';
139
- break;
140
- }
141
- }
142
 
143
- if( !empty($this->scripts) ) {
144
- $this->enqueueScripts($this->scripts, 'js', $dependencies);
145
- }
146
- if( !empty($this->styles) ) {
147
- $this->enqueueScripts($this->styles, 'css', $dependencies);
148
  }
 
 
 
 
 
 
 
149
 
150
- $user_id = get_current_user_id();
151
- $color_name = get_user_meta($user_id, 'admin_color', true);
152
-
153
- if( $color_name !== 'fresh' ) {
154
- if( file_exists(FACTORY_BOOTSTRAP_412_DIR . '/assets/flat/css/bootstrap.' . $color_name . '.css') ) {
155
- wp_enqueue_style('wbcr-factory-bootstrap-412-colors', FACTORY_BOOTSTRAP_412_URL . '/assets/flat/css/bootstrap.' . $color_name . '.css');
156
- }
157
- }
158
-
159
- if( $color_name == 'light' ) {
160
- $primary_dark = '#037c9a';
161
- $primary_light = '#04a4cc';
162
- } elseif( $color_name == 'blue' ) {
163
- $primary_dark = '#d39323';
164
- $primary_light = '#e1a948';
165
- } elseif( $color_name == 'coffee' ) {
166
- $primary_dark = '#b78a66';
167
- $primary_light = '#c7a589';
168
- } elseif( $color_name == 'ectoplasm' ) {
169
- $primary_dark = '#839237';
170
- $primary_light = '#a3b745';
171
- } elseif( $color_name == 'ocean' ) {
172
- $primary_dark = '#80a583';
173
- $primary_light = '#9ebaa0';
174
- } elseif( $color_name == 'midnight' ) {
175
- $primary_dark = '#d02a21';
176
- $primary_light = '#e14d43';
177
- } elseif( $color_name == 'sunrise' ) {
178
- $primary_dark = '#c36822';
179
- $primary_light = '#dd823b';
180
- } else {
181
- $primary_dark = '#0074a2';
182
- $primary_light = '#2ea2cc';
183
- }
184
-
185
- ?>
186
-
187
- <script>
188
- if( !window.factory ) {
189
- window.factory = {};
190
- }
191
- if( !window.factory.factoryBootstrap412 ) {
192
- window.factory.factoryBootstrap412 = {};
193
- }
194
- window.factory.factoryBootstrap412.colors = {
195
- primaryDark: '<?php echo $primary_dark ?>',
196
- primaryLight: '<?php echo $primary_light ?>'
197
- };
198
- </script>
199
- <?php
200
  }
 
201
 
202
- /**
203
- * @param array $sripts
204
- * @param string $type
205
- * @param array $dependencies
206
- */
207
- protected function enqueueScripts(array $sripts, $type = 'js', array $dependencies)
208
- {
209
 
210
- $is_first = true;
211
- $cache_id = md5(implode(',', $this->scripts) . $type . $this->plugin->getPluginVersion());
212
- $cache_dir_path = FACTORY_BOOTSTRAP_412_DIR . '/assets/cache/';
213
- $cache_dir_url = FACTORY_BOOTSTRAP_412_URL . '/assets/cache/';
 
 
214
 
215
- $cache_filepath = $cache_dir_path . $cache_id . ".min." . $type;
216
- $cache_fileurl = $cache_dir_url . $cache_id . ".min." . $type;
217
 
218
- if( file_exists($cache_filepath) ) {
219
- if( $type == 'js' ) {
220
- wp_enqueue_script('wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, $dependencies, $this->plugin->getPluginVersion());
221
- } else {
222
- wp_enqueue_style('wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, array(), $this->plugin->getPluginVersion());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  }
224
  } else {
225
- $cache_dir_exists = false;
226
- if( !file_exists($cache_dir_path) ) {
227
- if( @mkdir($cache_dir_path, 0777) && wp_is_writable($cache_dir_path) ) {
228
- $cache_dir_exists = true;
229
- }
230
  } else {
231
- if( wp_is_writable($cache_dir_path) ) {
232
- $cache_dir_exists = true;
233
- }
234
- }
235
-
236
- $concat_files = array();
237
- foreach($sripts as $script_to_load) {
238
- $script_to_load = sanitize_text_field($script_to_load);
239
- if( $cache_dir_exists ) {
240
- $fname = FACTORY_BOOTSTRAP_412_DIR . "/assets/$type-min/$script_to_load.min." . $type;
241
- if( file_exists($fname) ) {
242
- $f = @fopen($fname, 'r');
243
- $concat_files[] = @fread($f, filesize($fname));
244
- @fclose($f);
245
- }
246
- } else {
247
- if( $type == 'js' ) {
248
- wp_enqueue_script(md5($script_to_load), FACTORY_BOOTSTRAP_412_URL . "/assets/$type-min/$script_to_load.min." . $type, $is_first
249
- ? $dependencies
250
- : false, $this->plugin->getPluginVersion());
251
- } else {
252
- wp_enqueue_style(md5($script_to_load), FACTORY_BOOTSTRAP_412_URL . "/assets/$type-min/$script_to_load.min." . $type, array(), $this->plugin->getPluginVersion());
253
- }
254
- $is_first = false;
255
- }
256
  }
 
 
 
257
 
258
- if( $cache_dir_exists && !empty($concat_files) ) {
259
 
260
- $cf = @fopen($cache_filepath, 'w');
261
- $write_content = implode(PHP_EOL, $concat_files);
262
- @fwrite($cf, $write_content);
263
- @fclose($cf);
 
264
 
265
- if( file_exists($cache_filepath) ) {
266
- if( $type == 'js' ) {
267
- wp_enqueue_script('wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, $dependencies, $this->plugin->getPluginVersion());
268
- } else {
269
- wp_enqueue_style('wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, array(), $this->plugin->getPluginVersion());
270
- }
271
- }
272
  }
273
  }
274
  }
 
 
275
 
276
- /**
277
- * Adds the body classes: 'factory-flat or 'factory-volumetric'.
278
- *
279
- * @since 3.2.0
280
- * @param string $classes
281
- * @return string
282
- */
283
- public function adminBodyClass($classes)
284
- {
285
- $classes .= FACTORY_FLAT_ADMIN
286
- ? ' factory-flat '
287
- : ' factory-volumetric ';
288
 
289
- return $classes;
290
- }
291
- }
292
- }
1
  <?php
2
+ /**
3
+ * This file manages assets of the Factory Bootstap.
4
+ *
5
+ * @author Alex Kovalev <alex@byonepress.com>
6
+ * @author Paul Kashtanoff <paul@byonepress.com>
7
+ * @since 1.0.0
8
+ * @package factory-bootstrap
9
+ * @copyright (c) 2018, OnePress Ltd
10
+ *
11
+ */
12
+
13
+ // Exit if accessed directly
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit;
16
+ }
17
+
18
+ /**
19
+ * The Bootstrap Manager class.
20
+ *
21
+ * @since 3.2.0
22
+ */
23
+ class Wbcr_FactoryBootstrap425_Manager {
24
+
25
+ /**
26
+ * A plugin for which the manager was created.
27
+ *
28
+ * @since 3.2.0
29
+ * @var Wbcr_Factory424_Plugin
30
+ */
31
+ public $plugin;
32
+
33
  /**
34
+ * Contains scripts to include.
35
  *
36
+ * @since 3.2.0
37
+ * @var string[]
38
+ */
39
+ public $scripts = [];
40
+
41
+ /**
42
+ * Contains styles to include.
43
  *
44
+ * @since 3.2.0
45
+ * @var string[]
46
  */
47
+ public $styles = [];
48
+
 
49
  /**
50
+ * Createas a new instance of the license api for a given plugin.
51
+ *
52
+ * @since 1.0.0
53
  */
54
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
55
+ $this->plugin = $plugin;
56
+
57
+ add_action( 'admin_enqueue_scripts', [ $this, 'loadAssets' ] );
58
+ add_filter( 'admin_body_class', [ $this, 'adminBodyClass' ] );
59
  }
60
+
61
+ /**
62
+ * Includes the Bootstrap scripts.
63
+ *
64
+ * @since 3.2.0
65
+ *
66
+ * @param array|string $scripts
67
+ */
68
+ public function enqueueScript( $scripts ) {
69
+ if ( is_array( $scripts ) ) {
70
+ foreach ( $scripts as $script ) {
71
+ if ( ! in_array( $script, $this->scripts ) ) {
72
+ $this->scripts[] = $script;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  }
74
  }
75
+ } else {
76
+ if ( ! in_array( $scripts, $this->scripts ) ) {
77
+ $this->scripts[] = $scripts;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
79
+ }
80
+ }
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
+ /**
83
+ * * Includes the Bootstrap styles.
84
+ *
85
+ * @since 3.2.0
86
+ *
87
+ * @param array|string $styles
88
+ */
89
+ public function enqueueStyle( $styles ) {
 
 
 
 
 
 
 
 
90
 
91
+ if ( is_array( $styles ) ) {
92
+ foreach ( $styles as $style ) {
93
+ if ( ! in_array( $style, $this->styles ) ) {
94
+ $this->styles[] = $style;
 
95
  }
96
+ }
97
+ } else {
98
+ if ( ! in_array( $styles, $this->styles ) ) {
99
+ $this->styles[] = $styles;
100
+ }
101
+ }
102
+ }
103
 
104
+ /**
105
+ * Loads Bootstrap assets.
106
+ *
107
+ * @since 3.2.0
108
+ * @return void
109
+ * @see admin_enqueue_scripts
110
+ *
111
+ */
112
+ public function loadAssets( $hook ) {
113
+
114
+ do_action( 'wbcr_factory_424_bootstrap_enqueue_scripts', $hook );
115
+ do_action( 'wbcr_factory_424_bootstrap_enqueue_scripts_' . $this->plugin->getPluginName(), $hook );
116
+
117
+ $dependencies = [];
118
+ if ( ! empty( $this->scripts ) ) {
119
+ $dependencies[] = 'jquery';
120
+ $dependencies[] = 'jquery-ui-core';
121
+ $dependencies[] = 'jquery-ui-widget';
122
+ }
123
+
124
+ foreach ( $this->scripts as $script ) {
125
+ switch ( $script ) {
126
+ case 'plugin.iris':
127
+ $dependencies[] = 'jquery-ui-widget';
128
+ $dependencies[] = 'jquery-ui-slider';
129
+ $dependencies[] = 'jquery-ui-draggable';
130
+ break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  }
132
+ }
133
 
134
+ if ( ! empty( $this->scripts ) ) {
135
+ $this->enqueueScripts( $this->scripts, 'js', $dependencies );
136
+ }
137
+ if ( ! empty( $this->styles ) ) {
138
+ $this->enqueueScripts( $this->styles, 'css', $dependencies );
139
+ }
140
+ }
141
 
142
+ /**
143
+ * @param array $scripts
144
+ * @param string $type
145
+ * @param array $dependencies
146
+ */
147
+ protected function enqueueScripts( array $scripts, $type, array $dependencies ) {
148
 
149
+ $is_first = true;
 
150
 
151
+ /**
152
+ * Sets permission for file caching and combining into one file.
153
+ *
154
+ * @since 4.1.0
155
+ */
156
+ $cache_enable = apply_filters( 'wbcr/factory/bootstrap/cache_enable', true );
157
+
158
+ $cache_id = md5( implode( ',', $this->scripts ) . $type . $this->plugin->getPluginVersion() );
159
+ $cache_dir_path = FACTORY_BOOTSTRAP_425_DIR . '/assets/cache/';
160
+ $cache_dir_url = FACTORY_BOOTSTRAP_425_URL . '/assets/cache/';
161
+
162
+ $cache_filepath = $cache_dir_path . $cache_id . ".min." . $type;
163
+ $cache_fileurl = $cache_dir_url . $cache_id . ".min." . $type;
164
+
165
+ if ( $cache_enable && file_exists( $cache_filepath ) ) {
166
+ if ( $type == 'js' ) {
167
+ wp_enqueue_script( 'wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, $dependencies, $this->plugin->getPluginVersion() );
168
+ } else {
169
+ wp_enqueue_style( 'wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, [], $this->plugin->getPluginVersion() );
170
+ }
171
+ } else {
172
+ $cache_dir_exists = false;
173
+ if ( ! file_exists( $cache_dir_path ) ) {
174
+ if ( @mkdir( $cache_dir_path, 0755 ) && wp_is_writable( $cache_dir_path ) ) {
175
+ $cache_dir_exists = true;
176
+ }
177
+ } else {
178
+ if ( wp_is_writable( $cache_dir_path ) ) {
179
+ $cache_dir_exists = true;
180
+ }
181
+ }
182
+
183
+ $concat_files = [];
184
+ foreach ( $scripts as $script_to_load ) {
185
+ $script_to_load = sanitize_text_field( $script_to_load );
186
+ if ( $cache_enable && $cache_dir_exists ) {
187
+ $fname = FACTORY_BOOTSTRAP_425_DIR . "/assets/$type-min/$script_to_load.min." . $type;
188
+ if ( file_exists( $fname ) ) {
189
+ $f = @fopen( $fname, 'r' );
190
+ $concat_files[] = @fread( $f, filesize( $fname ) );
191
+ @fclose( $f );
192
  }
193
  } else {
194
+ if ( $type == 'js' ) {
195
+ wp_enqueue_script( md5( $script_to_load ), FACTORY_BOOTSTRAP_425_URL . "/assets/$type-min/$script_to_load.min." . $type, $is_first ? $dependencies : false, $this->plugin->getPluginVersion() );
 
 
 
196
  } else {
197
+ wp_enqueue_style( md5( $script_to_load ), FACTORY_BOOTSTRAP_425_URL . "/assets/$type-min/$script_to_load.min." . $type, [], $this->plugin->getPluginVersion() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  }
199
+ $is_first = false;
200
+ }
201
+ }
202
 
203
+ if ( $cache_enable && $cache_dir_exists && ! empty( $concat_files ) ) {
204
 
205
+ $cf = @fopen( $cache_filepath, 'w' );
206
+ $write_content = implode( PHP_EOL, $concat_files );
207
+ @fwrite( $cf, $write_content );
208
+ @fclose( $cf );
209
+ chmod( $cache_filepath, 0755 );
210
 
211
+ if ( file_exists( $cache_filepath ) ) {
212
+ if ( $type == 'js' ) {
213
+ wp_enqueue_script( 'wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, $dependencies, $this->plugin->getPluginVersion() );
214
+ } else {
215
+ wp_enqueue_style( 'wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, [], $this->plugin->getPluginVersion() );
 
 
216
  }
217
  }
218
  }
219
+ }
220
+ }
221
 
222
+ /**
223
+ * Adds the body classes: 'factory-flat or 'factory-volumetric'.
224
+ *
225
+ * @since 3.2.0
226
+ *
227
+ * @param string $classes
228
+ *
229
+ * @return string
230
+ */
231
+ public function adminBodyClass( $classes ) {
232
+ $classes .= FACTORY_FLAT_ADMIN ? ' factory-flat ' : ' factory-volumetric ';
 
233
 
234
+ return $classes;
235
+ }
236
+ }
 
libs/factory/bootstrap/includes/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/bootstrap/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/clearfy/assets/css/clearfy-base.css CHANGED
@@ -5,18 +5,18 @@
5
  * @copyright Webcraftic 06.10.2018
6
  * @sicne 2.0.5
7
  */
8
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-clearfy-208-multisite-suggetion {
9
  padding: 30px 80px;
10
  }
11
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-clearfy-208-multisite-suggetion h3 {
12
  margin: 0 0 20px;
13
  }
14
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-clearfy-208-multisite-suggetion .wbcr-factory-inner-contanier {
15
  border: 2px dashed #8bc34a;
16
  background: #fff;
17
  padding: 20px;
18
  }
19
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-clearfy-208-multisite-suggetion .wbcr-factory-activate-premium {
20
  display: inline-block;
21
  cursor: pointer;
22
  line-height: 16px;
@@ -35,16 +35,16 @@
35
  -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
36
  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
37
  }
38
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-clearfy-208-multisite-suggetion .wbcr-factory-activate-premium:active {
39
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
40
  -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
41
  -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
42
  }
43
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-clearfy-208-multisite-suggetion .wbcr-factory-activate-premium:focus {
44
  outline: none;
45
  border: 0;
46
  }
47
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-clearfy-208-multisite-suggetion .wbcr-factory-purchase-premium {
48
  display: inline-block;
49
  cursor: pointer;
50
  line-height: 16px;
@@ -63,22 +63,22 @@
63
  -moz-box-shadow: 0 1px 0 rgba(60, 45, 2, 0.31);
64
  -webkit-box-shadow: 0 1px 0 rgba(60, 45, 2, 0.31);
65
  }
66
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-clearfy-208-multisite-suggetion .wbcr-factory-purchase-premium:active {
67
  box-shadow: inset 0 1px 0 rgba(60, 45, 2, 0.31);
68
  -moz-box-shadow: inset 0 1px 0 rgba(60, 45, 2, 0.31);
69
  -webkit-box-shadow: inset 0 1px 0 rgba(60, 45, 2, 0.31);
70
  }
71
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-clearfy-208-multisite-suggetion .wbcr-factory-purchase-premium:focus {
72
  outline: none;
73
  border: 0;
74
  }
75
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion {
76
  background: #fff;
77
  color: #353535;
78
  font-weight: 600;
79
  border: 2px dashed #8bc34a;
80
  }
81
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion h3 {
82
  margin: 0 0 20px;
83
  padding: 10px 0;
84
  text-align: center;
@@ -89,16 +89,16 @@
89
  vertical-align: middle;
90
  text-transform: uppercase;
91
  }
92
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion ul {
93
  position: relative;
94
  margin-bottom: 20px;
95
  }
96
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion ul li {
97
  font-size: 15px;
98
  padding: 7px;
99
  padding-left: 20px;
100
  }
101
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion ul li:before {
102
  content: " ";
103
  display: inline-block;
104
  width: 0.4em;
@@ -112,7 +112,7 @@
112
  -o-transform: rotate(45deg);
113
  transform: rotate(45deg);
114
  }
115
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion .wbcr-factory-purchase-premium {
116
  display: block;
117
  cursor: pointer;
118
  line-height: 16px;
@@ -131,44 +131,44 @@
131
  -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
132
  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
133
  }
134
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion .wbcr-factory-purchase-premium:active {
135
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
136
  -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
137
  -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
138
  }
139
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion .wbcr-factory-purchase-premium:focus {
140
  outline: none;
141
  border: 0;
142
  }
143
  @media screen and (max-width: 1550px) {
144
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-clearfy-208-multisite-pro-suggetion {
145
  padding: 10px 80px;
146
  }
147
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion {
148
  padding: 10px;
149
  }
150
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion h3 {
151
  margin: 0 0 20px;
152
  padding: 10px 0;
153
  font-size: 13px;
154
  font-weight: 600;
155
  }
156
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion ul {
157
  margin-bottom: 20px;
158
  }
159
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion ul li {
160
  font-size: 13px;
161
  padding: 2px;
162
  padding-left: 10px;
163
  }
164
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion ul li:before {
165
  width: 0.4em;
166
  height: 0.7em;
167
  border-width: 0 0.2em 0.2em 0;
168
  left: 0;
169
  margin-right: 10px;
170
  }
171
- #WBCR .wbcr-factory-pages-412-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-208-pro-suggettion .wbcr-factory-purchase-premium {
172
  font-weight: 700;
173
  line-height: 16px;
174
  font-size: 12px;
5
  * @copyright Webcraftic 06.10.2018
6
  * @sicne 2.0.5
7
  */
8
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-clearfy-216-multisite-suggetion {
9
  padding: 30px 80px;
10
  }
11
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-clearfy-216-multisite-suggetion h3 {
12
  margin: 0 0 20px;
13
  }
14
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-clearfy-216-multisite-suggetion .wbcr-factory-inner-contanier {
15
  border: 2px dashed #8bc34a;
16
  background: #fff;
17
  padding: 20px;
18
  }
19
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-clearfy-216-multisite-suggetion .wbcr-factory-activate-premium {
20
  display: inline-block;
21
  cursor: pointer;
22
  line-height: 16px;
35
  -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
36
  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
37
  }
38
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-clearfy-216-multisite-suggetion .wbcr-factory-activate-premium:active {
39
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
40
  -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
41
  -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
42
  }
43
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-clearfy-216-multisite-suggetion .wbcr-factory-activate-premium:focus {
44
  outline: none;
45
  border: 0;
46
  }
47
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-clearfy-216-multisite-suggetion .wbcr-factory-purchase-premium {
48
  display: inline-block;
49
  cursor: pointer;
50
  line-height: 16px;
63
  -moz-box-shadow: 0 1px 0 rgba(60, 45, 2, 0.31);
64
  -webkit-box-shadow: 0 1px 0 rgba(60, 45, 2, 0.31);
65
  }
66
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-clearfy-216-multisite-suggetion .wbcr-factory-purchase-premium:active {
67
  box-shadow: inset 0 1px 0 rgba(60, 45, 2, 0.31);
68
  -moz-box-shadow: inset 0 1px 0 rgba(60, 45, 2, 0.31);
69
  -webkit-box-shadow: inset 0 1px 0 rgba(60, 45, 2, 0.31);
70
  }
71
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-clearfy-216-multisite-suggetion .wbcr-factory-purchase-premium:focus {
72
  outline: none;
73
  border: 0;
74
  }
75
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion {
76
  background: #fff;
77
  color: #353535;
78
  font-weight: 600;
79
  border: 2px dashed #8bc34a;
80
  }
81
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion h3 {
82
  margin: 0 0 20px;
83
  padding: 10px 0;
84
  text-align: center;
89
  vertical-align: middle;
90
  text-transform: uppercase;
91
  }
92
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion ul {
93
  position: relative;
94
  margin-bottom: 20px;
95
  }
96
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion ul li {
97
  font-size: 15px;
98
  padding: 7px;
99
  padding-left: 20px;
100
  }
101
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion ul li:before {
102
  content: " ";
103
  display: inline-block;
104
  width: 0.4em;
112
  -o-transform: rotate(45deg);
113
  transform: rotate(45deg);
114
  }
115
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion .wbcr-factory-purchase-premium {
116
  display: block;
117
  cursor: pointer;
118
  line-height: 16px;
131
  -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
132
  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
133
  }
134
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion .wbcr-factory-purchase-premium:active {
135
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
136
  -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
137
  -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
138
  }
139
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion .wbcr-factory-purchase-premium:focus {
140
  outline: none;
141
  border: 0;
142
  }
143
  @media screen and (max-width: 1550px) {
144
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-clearfy-216-multisite-pro-suggetion {
145
  padding: 10px 80px;
146
  }
147
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion {
148
  padding: 10px;
149
  }
150
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion h3 {
151
  margin: 0 0 20px;
152
  padding: 10px 0;
153
  font-size: 13px;
154
  font-weight: 600;
155
  }
156
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion ul {
157
  margin-bottom: 20px;
158
  }
159
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion ul li {
160
  font-size: 13px;
161
  padding: 2px;
162
  padding-left: 10px;
163
  }
164
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion ul li:before {
165
  width: 0.4em;
166
  height: 0.7em;
167
  border-width: 0 0.2em 0.2em 0;
168
  left: 0;
169
  margin-right: 10px;
170
  }
171
+ #WBCR .wbcr-factory-pages-424-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-216-pro-suggettion .wbcr-factory-purchase-premium {
172
  font-weight: 700;
173
  line-height: 16px;
174
  font-size: 12px;
libs/factory/clearfy/assets/css/clearfy-base.css.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":["clearfy-base.less"],"names":[],"mappings":";;;;;;;AAoCA,KAEE,iDACE;EACE,kBAAA;;AAJN,KAEE,iDACE,8CAGE;EACE,gBAAA;;AAPR,KAEE,iDACE,8CAOE;EACE,0BAAA;EACA,gBAAA;EACA,aAAA;;AAbR,KAEE,iDACE,8CAaE;EACE,qBAAA;EA5CN,eAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,kBAAA;EACA,kBAAA;EACA,qBAAA;EACA,yBAAA;EACA,kBAAA;EACA,uBAAA;EACA,0BAAA;EACA,cAAA;EACA,mBAAA;EACA,sCAAA;EACA,2CAAA;EACA,8CAAA;;AACA,KAaA,iDACE,8CAaE,+BA3BH;EACC,4CAAA;EACA,iDAAA;EACA,oDAAA;;AAEF,KAQA,iDACE,8CAaE,+BAtBH;EACC,aAAA;EACA,SAAA;;AAIJ,KAEE,iDACE,8CAiBE;EACE,qBAAA;EAhDN,eAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,kBAAA;EACA,kBAAA;EACA,qBAAA;EACA,yBAAA;EACA,kBAAA;EACA,uBAAA;EACA,0BAAA;EACA,cAAA;EACA,mBAAA;EACA,yCAAA;EACA,8CAAA;EACA,iDAAA;;AACA,KAaA,iDACE,8CAiBE,+BA/BH;EACC,+CAAA;EACA,oDAAA;EACA,uDAAA;;AAEF,KAQA,iDACE,8CAiBE,+BA1BH;EACC,aAAA;EACA,SAAA;;AAIJ,KAEE,iDAwBE,oCACE;EACE,gBAAA;EACA,cAAA;EACA,gBAAA;EACA,0BAAA;;AA/BR,KAEE,iDAwBE,oCACE,yCAME;EACE,gBAAA;EACA,eAAA;EACA,kBAAA;EACA,gCAAA;EACA,cAAA;EACA,eAAA;EACA,gBAAA;EACA,sBAAA;EACA,yBAAA;;AA1CV,KAEE,iDAwBE,oCACE,yCAkBE;EAEE,kBAAA;EACA,mBAAA;;AAhDV,KAEE,iDAwBE,oCACE,yCAkBE,GAKE;EACE,eAAA;EACA,YAAA;EACA,kBAAA;;AAIA,KAvDV,iDAwBE,oCACE,yCAkBE,GAKE,GAOG;EACC,SAAS,GAAT;EACA,qBAAA;EACA,YAAA;EACA,aAAA;EACA,qBAAA;EACA,6BAAA;EACA,OAAA;EACA,kBAAA;EACA,mBAAmB,aAAnB;EACA,gBAAgB,aAAhB;EACA,cAAc,aAAd;EACA,WAAW,aAAX;;AArEd,KAEE,iDAwBE,oCACE,yCAgDE;EACE,cAAA;EAvGR,eAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,kBAAA;EACA,kBAAA;EACA,qBAAA;EACA,yBAAA;EACA,kBAAA;EACA,uBAAA;EACA,0BAAA;EACA,cAAA;EACA,mBAAA;EACA,sCAAA;EACA,2CAAA;EACA,8CAAA;;AACA,KAaA,iDAwBE,oCACE,yCAgDE,+BAtFL;EACC,4CAAA;EACA,iDAAA;EACA,oDAAA;;AAEF,KAQA,iDAwBE,oCACE,yCAgDE,+BAjFL;EACC,aAAA;EACA,SAAA;;AAwFJ,mBAAsC;EACpC,KACE,iDACE;IACE,kBAAA;;EAHN,KACE,iDAKE,oCACE;IACE,aAAA;;EARR,KACE,iDAKE,oCACE,yCAGE;IACE,gBAAA;IACA,eAAA;IACA,eAAA;IACA,gBAAA;;EAdV,KACE,iDAKE,oCACE,yCAUE;IACE,mBAAA;;EAlBV,KACE,iDAKE,oCACE,yCAUE,GAGE;IACE,eAAA;IACA,YAAA;IACA,kBAAA;;EAEA,KAxBV,iDAKE,oCACE,yCAUE,GAGE,GAKG;IACC,YAAA;IACA,aAAA;IACA,6BAAA;IACA,OAAA;IACA,kBAAA;;EA9Bd,KACE,iDAKE,oCACE,yCA4BE;IACE,gBAAA;IACA,iBAAA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;IACA,uBAAA;IACA,0BAAA","file":"clearfy-base.css"}
libs/factory/clearfy/assets/css/index.php DELETED
File without changes
libs/factory/clearfy/assets/index.php DELETED
File without changes
libs/factory/clearfy/assets/js/globals.js CHANGED
@@ -2,8 +2,8 @@
2
  * Глобальный JS файл, который регистрирует глобальные переменные с общими методами для всех компонентов Clearfy
3
  * и самого Clearfy.
4
  *
5
- * $.wbcr_factory_clearfy_208.app - методы для работы с приложением. Скрыть, показать уведомления.
6
- * $.wbcr_factory_clearfy_208.hooks - это иммитация хуков и фильтров аналогично тем, что используются в Wordpress
7
  *
8
  * Copyright 2018, Webcraftic, http://webcraftic.com
9
  *
@@ -13,11 +13,11 @@
13
  (function($) {
14
  'use strict';
15
 
16
- if( !$.wbcr_factory_clearfy_208 ) {
17
- $.wbcr_factory_clearfy_208 = {};
18
  }
19
 
20
- $.wbcr_factory_clearfy_208.app = $.wbcr_factory_clearfy_208.app || {
21
  /**
22
  * Создает и показывает уведомление внутри интерфейса Clearfy
23
  *
@@ -63,12 +63,12 @@
63
  /**
64
  * Хук выполняет проивольную функцию, после того как уведомление отображено
65
  * Реализация системы фильтров и хуков в файле libs/clearfy/admin/assests/js/global.js
66
- * Пример регистрации хука $.wbcr_factory_clearfy_208.hooks.add('wbcr/factory_clearfy_208/updated',
67
  * function(noticeId) {});
68
  * @param {string} noticeId - id уведомления
69
  */
70
- $.wbcr_factory_clearfy_208.hooks.run('wbcr/factory_clearfy_208/showed_notice', [noticeId]);
71
- $.wbcr_factory_clearfy_208.hooks.run('wbcr/clearfy/showed_notice', [noticeId]);
72
  });
73
 
74
  return noticeId;
@@ -93,13 +93,13 @@
93
  /**
94
  * Хук выполняет проивольную функцию, после того как уведомление скрыто
95
  * Реализация системы фильтров и хуков в файле libs/clearfy/admin/assests/js/global.js
96
- * Пример регистрации хука $.wbcr_factory_clearfy_208.hooks.add('wbcr/factory_clearfy_208/updated',
97
  * function(noticeId)
98
  * {});
99
  * @param {string} noticeId - id уведомления
100
  */
101
- $.wbcr_factory_clearfy_208.hooks.run('wbcr/factory_clearfy_208/hidded_notice', [noticeId]);
102
- $.wbcr_factory_clearfy_208.hooks.run('wbcr/clearfy/hidded_notice', [noticeId]);
103
  });
104
  },
105
 
@@ -116,7 +116,7 @@
116
 
117
  };
118
 
119
- $.wbcr_factory_clearfy_208.filters = $.wbcr_factory_clearfy_208.filters || {
120
 
121
  /**
122
  * A set of registered filters.
@@ -183,20 +183,20 @@
183
  }
184
  };
185
 
186
- $.wbcr_factory_clearfy_208.hooks = $.wbcr_factory_clearfy_208.hooks || {
187
 
188
  /**
189
  * Applies filters to a given input value.
190
  */
191
  run: function(filterName, args) {
192
- $.wbcr_factory_clearfy_208.filters.run(filterName, args);
193
  },
194
 
195
  /**
196
  * Registers a new filter.
197
  */
198
  add: function(filterName, callback, priority) {
199
- $.wbcr_factory_clearfy_208.filters.add(filterName, callback, priority);
200
  }
201
  };
202
 
2
  * Глобальный JS файл, который регистрирует глобальные переменные с общими методами для всех компонентов Clearfy
3
  * и самого Clearfy.
4
  *
5
+ * $.wbcr_factory_clearfy_216.app - методы для работы с приложением. Скрыть, показать уведомления.
6
+ * $.wbcr_factory_clearfy_216.hooks - это иммитация хуков и фильтров аналогично тем, что используются в Wordpress
7
  *
8
  * Copyright 2018, Webcraftic, http://webcraftic.com
9
  *
13
  (function($) {
14
  'use strict';
15
 
16
+ if( !$.wbcr_factory_clearfy_216 ) {
17
+ $.wbcr_factory_clearfy_216 = {};
18
  }
19
 
20
+ $.wbcr_factory_clearfy_216.app = $.wbcr_factory_clearfy_216.app || {
21
  /**
22
  * Создает и показывает уведомление внутри интерфейса Clearfy
23
  *
63
  /**
64
  * Хук выполняет проивольную функцию, после того как уведомление отображено
65
  * Реализация системы фильтров и хуков в файле libs/clearfy/admin/assests/js/global.js
66
+ * Пример регистрации хука $.wbcr_factory_clearfy_216.hooks.add('wbcr/factory_clearfy_216/updated',
67
  * function(noticeId) {});
68
  * @param {string} noticeId - id уведомления
69
  */
70
+ $.wbcr_factory_clearfy_216.hooks.run('wbcr/factory_clearfy_216/showed_notice', [noticeId]);
71
+ $.wbcr_factory_clearfy_216.hooks.run('wbcr/clearfy/showed_notice', [noticeId]);
72
  });
73
 
74
  return noticeId;
93
  /**
94
  * Хук выполняет проивольную функцию, после того как уведомление скрыто
95
  * Реализация системы фильтров и хуков в файле libs/clearfy/admin/assests/js/global.js
96
+ * Пример регистрации хука $.wbcr_factory_clearfy_216.hooks.add('wbcr/factory_clearfy_216/updated',
97
  * function(noticeId)
98
  * {});
99
  * @param {string} noticeId - id уведомления
100
  */
101
+ $.wbcr_factory_clearfy_216.hooks.run('wbcr/factory_clearfy_216/hidded_notice', [noticeId]);
102
+ $.wbcr_factory_clearfy_216.hooks.run('wbcr/clearfy/hidded_notice', [noticeId]);
103
  });
104
  },
105
 
116
 
117
  };
118
 
119
+ $.wbcr_factory_clearfy_216.filters = $.wbcr_factory_clearfy_216.filters || {
120
 
121
  /**
122
  * A set of registered filters.
183
  }
184
  };
185
 
186
+ $.wbcr_factory_clearfy_216.hooks = $.wbcr_factory_clearfy_216.hooks || {
187
 
188
  /**
189
  * Applies filters to a given input value.
190
  */
191
  run: function(filterName, args) {
192
+ $.wbcr_factory_clearfy_216.filters.run(filterName, args);
193
  },
194
 
195
  /**
196
  * Registers a new filter.
197
  */
198
  add: function(filterName, callback, priority) {
199
+ $.wbcr_factory_clearfy_216.filters.add(filterName, callback, priority);
200
  }
201
  };
202
 
libs/factory/clearfy/assets/js/index.php DELETED
File without changes
libs/factory/clearfy/assets/js/license-manager.js CHANGED
@@ -3,44 +3,40 @@
3
  * Его основная роль отправка ajax запросов на проверку, активацию, деактивацию лицензии
4
  * и вывод уведомлений об ошибка или успешно выполнении проверок.
5
  *
6
- * @author Webcraftic <wordpress.webraftic@gmail.com>
7
  * @copyright (c) 05.10.2018, Webcraftic
8
  * @version 1.1
9
  * @since 1.4.0
10
  */
11
-
12
-
13
  jQuery(function($) {
14
 
15
  var allNotices = [];
16
 
17
  $(document).on('click', '.wcl-control-btn', function() {
18
-
19
- // Скрываем все открытые этим событием уведомления
20
- // Глобальные уведомления не трогаем
 
 
21
 
22
  for( i = 0; i < allNotices.length; i++ ) {
23
- $.wbcr_factory_clearfy_208.app.hideNotice(allNotices[i]);
24
  }
25
 
26
  $('.wcl-control-btn').hide();
27
 
28
- var wrapper = $('#wcl-license-wrapper'),
29
- loader = wrapper.data('loader'),
30
- pluginClass = wrapper.data('plugin');
31
-
32
  $(this).after('<img class="wcl-loader" src="' + loader + '">');
33
 
34
  var data = {
35
- action: 'wbcr-clearfy-activate-license',
36
- _wpnonce: $('#_wpnonce').val(),
37
- license_action: $(this).data('action'),
 
38
  licensekey: ''
39
  };
40
 
41
  if( $(this).data('action').trim() === 'activate' ) {
42
  data.licensekey = $('#license-key').val().trim();
43
- data.plugin_class = pluginClass;
44
  }
45
 
46
  $.ajax(ajaxurl, {
@@ -57,7 +53,7 @@ jQuery(function($) {
57
 
58
  if( response.data ) {
59
  console.log(response.data.error_message);
60
- noticeId = $.wbcr_factory_clearfy_208.app.showNotice('Error: [' + response.data.error_message + ']', 'danger');
61
  allNotices.push(noticeId);
62
  } else {
63
  console.log(response);
@@ -67,7 +63,7 @@ jQuery(function($) {
67
  }
68
 
69
  if( response.data && response.data.message ) {
70
- noticeId = $.wbcr_factory_clearfy_208.app.showNotice(response.data.message, 'success');
71
  allNotices.push(noticeId);
72
 
73
  // todo: доработать генерацию формы, вместо перезагрузки страницы
@@ -84,7 +80,7 @@ jQuery(function($) {
84
  console.log(xhr.responseText);
85
  console.log(thrownError);
86
 
87
- var noticeId = $.wbcr_factory_clearfy_208.app.showNotice('Error: [' + thrownError + '] Status: [' + xhr.status + '] Error massage: [' + xhr.responseText + ']', 'danger');
88
 
89
  allNotices.push(noticeId);
90
  }
3
  * Его основная роль отправка ajax запросов на проверку, активацию, деактивацию лицензии
4
  * и вывод уведомлений об ошибка или успешно выполнении проверок.
5
  *
6
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
7
  * @copyright (c) 05.10.2018, Webcraftic
8
  * @version 1.1
9
  * @since 1.4.0
10
  */
 
 
11
  jQuery(function($) {
12
 
13
  var allNotices = [];
14
 
15
  $(document).on('click', '.wcl-control-btn', function() {
16
+ var wrapper = $('#wcl-license-wrapper'),
17
+ loader = wrapper.data('loader'),
18
+ pluginName = wrapper.data('plugin-name'),
19
+ wpnonce = wrapper.data('nonce'),
20
+ licenseAction = $(this).data('action');
21
 
22
  for( i = 0; i < allNotices.length; i++ ) {
23
+ $.wbcr_factory_clearfy_216.app.hideNotice(allNotices[i]);
24
  }
25
 
26
  $('.wcl-control-btn').hide();
27
 
 
 
 
 
28
  $(this).after('<img class="wcl-loader" src="' + loader + '">');
29
 
30
  var data = {
31
+ action: 'wbcr-clearfy-activate-license-for-' + pluginName,
32
+ _wpnonce: wpnonce,
33
+ plugin_name: pluginName,
34
+ license_action: licenseAction,
35
  licensekey: ''
36
  };
37
 
38
  if( $(this).data('action').trim() === 'activate' ) {
39
  data.licensekey = $('#license-key').val().trim();
 
40
  }
41
 
42
  $.ajax(ajaxurl, {
53
 
54
  if( response.data ) {
55
  console.log(response.data.error_message);
56
+ noticeId = $.wbcr_factory_clearfy_216.app.showNotice('Error: [' + response.data.error_message + ']', 'danger');
57
  allNotices.push(noticeId);
58
  } else {
59
  console.log(response);
63
  }
64
 
65
  if( response.data && response.data.message ) {
66
+ noticeId = $.wbcr_factory_clearfy_216.app.showNotice(response.data.message, 'success');
67
  allNotices.push(noticeId);
68
 
69
  // todo: доработать генерацию формы, вместо перезагрузки страницы
80
  console.log(xhr.responseText);
81
  console.log(thrownError);
82
 
83
+ var noticeId = $.wbcr_factory_clearfy_216.app.showNotice('Error: [' + thrownError + '] Status: [' + xhr.status + '] Error massage: [' + xhr.responseText + ']', 'danger');
84
 
85
  allNotices.push(noticeId);
86
  }
libs/factory/clearfy/boot.php CHANGED
@@ -2,11 +2,11 @@
2
  /**
3
  * Factory clearfy
4
  *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
 
 
6
  * @copyright (c) 2018, Webcraftic Ltd
7
  *
8
- * @package clearfy
9
- * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
@@ -14,35 +14,36 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  exit;
15
  }
16
 
17
- if ( defined( 'FACTORY_CLEARFY_208_LOADED' ) ) {
18
  return;
19
  }
20
 
21
- define( 'FACTORY_CLEARFY_208_LOADED', true );
22
 
23
- define( 'FACTORY_CLEARFY_208', '2.0.7' );
24
 
25
- define( 'FACTORY_CLEARFY_208_DIR', dirname( __FILE__ ) );
26
- define( 'FACTORY_CLEARFY_208_URL', plugins_url( null, __FILE__ ) );
27
 
28
- load_plugin_textdomain( 'wbcr_factory_clearfy_208', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
29
 
30
- require( FACTORY_CLEARFY_208_DIR . '/includes/ajax-handlers.php' );
31
- require( FACTORY_CLEARFY_208_DIR . '/includes/class-clearfy-helpers.php' );
32
- require( FACTORY_CLEARFY_208_DIR . '/includes/class-clearfy-configurate.php' );
33
 
34
  // module provides function only for the admin area
35
  if ( is_admin() ) {
36
  /**
37
  * Подключаем скрипты для установки компонентов Clearfy
38
- * на все страницы админпанели
39
  */
40
  add_action( 'admin_enqueue_scripts', function () {
41
- wp_enqueue_script( 'wbcr-factory-clearfy-208-global', FACTORY_CLEARFY_208_URL . '/assets/js/globals.js', array( 'jquery' ), FACTORY_CLEARFY_208 );
42
  } );
43
-
44
- // TODO: Предполагается, что загрузка модуля pages будет раньше этого модуля.
45
- require( FACTORY_CLEARFY_208_DIR . '/pages/class-clearfy-more-features.php' );
46
- require( FACTORY_CLEARFY_208_DIR . '/pages/class-clearfy-pages.php' );
47
- require( FACTORY_CLEARFY_208_DIR . '/pages/class-clearfy-license.php' );
 
48
  }
2
  /**
3
  * Factory clearfy
4
  *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
6
+ * @since 1.0.0
7
+ * @package clearfy
8
  * @copyright (c) 2018, Webcraftic Ltd
9
  *
 
 
10
  */
11
 
12
  // Exit if accessed directly
14
  exit;
15
  }
16
 
17
+ if ( defined( 'FACTORY_CLEARFY_216_LOADED' ) ) {
18
  return;
19
  }
20
 
21
+ define( 'FACTORY_CLEARFY_216_LOADED', true );
22
 
23
+ define( 'FACTORY_CLEARFY_216', '2.1.6' );
24
 
25
+ define( 'FACTORY_CLEARFY_216_DIR', dirname( __FILE__ ) );
26
+ define( 'FACTORY_CLEARFY_216_URL', plugins_url( null, __FILE__ ) );
27
 
28
+ load_plugin_textdomain( 'wbcr_factory_clearfy_216', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
29
 
30
+ require( FACTORY_CLEARFY_216_DIR . '/includes/ajax-handlers.php' );
31
+ require( FACTORY_CLEARFY_216_DIR . '/includes/class-helpers.php' );
32
+ require( FACTORY_CLEARFY_216_DIR . '/includes/class-configurate.php' );
33
 
34
  // module provides function only for the admin area
35
  if ( is_admin() ) {
36
  /**
37
  * Подключаем скрипты для установки компонентов Clearfy
38
+ * на все страницы админпанели.
39
  */
40
  add_action( 'admin_enqueue_scripts', function () {
41
+ wp_enqueue_script( 'wbcr-factory-clearfy-216-global', FACTORY_CLEARFY_216_URL . '/assets/js/globals.js', [ 'jquery' ], FACTORY_CLEARFY_216 );
42
  } );
43
+
44
+ if ( defined( 'FACTORY_PAGES_424_LOADED' ) ) {
45
+ require( FACTORY_CLEARFY_216_DIR . '/pages/class-pages.php' );
46
+ require( FACTORY_CLEARFY_216_DIR . '/pages/class-page-more-features.php' );
47
+ require( FACTORY_CLEARFY_216_DIR . '/pages/class-page-license.php' );
48
+ }
49
  }
libs/factory/clearfy/includes/ajax-handlers.php CHANGED
@@ -1,9 +1,10 @@
1
  <?php
2
  /**
3
  * Ajax handlers
4
- * @author Webcraftic <wordpress.webraftic@gmail.com>
 
5
  * @copyright (c) 2017 Webraftic Ltd
6
- * @version 1.0
7
  */
8
 
9
  // Exit if accessed directly
@@ -14,76 +15,87 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  /**
15
  * Обработчик ajax запросов для проверки, активации, деактивации лицензионного ключа
16
  *
17
- * @param Wbcr_Factory412_Plugin $plugin_instance
18
  *
19
- * @since 2.0.7
20
  *
21
  */
22
- function wbcr_factory_clearfy_208_check_license( $plugin_instance ) {
23
- check_admin_referer( 'license' );
24
-
 
 
 
 
 
25
  $action = $plugin_instance->request->post( 'license_action', false, true );
26
  $license_key = $plugin_instance->request->post( 'licensekey', null );
27
-
28
- if ( empty( $action ) || ! in_array( $action, array( 'activate', 'deactivate', 'sync', 'unsubscribe' ) ) ) {
29
- wp_send_json_error( array( 'error_message' => __( 'Licensing action not passed or this action is prohibited!', 'wbcr_factory_clearfy_208' ) ) );
 
 
30
  die();
31
  }
32
-
33
  $result = null;
34
  $success_message = '';
35
-
36
  try {
37
  switch ( $action ) {
38
  case 'activate':
39
  if ( empty( $license_key ) || strlen( $license_key ) > 32 ) {
40
- wp_send_json_error( array( 'error_message' => __( 'License key is empty or license key too long (license key is 32 characters long)', 'wbcr_factory_clearfy_208' ) ) );
41
  } else {
42
  $plugin_instance->premium->activate( $license_key );
43
- $success_message = __( 'Your license has been successfully activated', 'wbcr_factory_clearfy_208' );
44
  }
45
  break;
46
  case 'deactivate':
47
  $plugin_instance->premium->deactivate();
48
- $success_message = __( 'The license is deactivated', 'wbcr_factory_clearfy_208' );
49
  break;
50
  case 'sync':
51
  $plugin_instance->premium->sync();
52
- $success_message = __( 'The license has been updated', 'wbcr_factory_clearfy_208' );
53
  break;
54
  case 'unsubscribe':
55
  $plugin_instance->premium->cancel_paid_subscription();
56
- $success_message = __( 'Subscription success cancelled', 'wbcr_factory_clearfy_208' );
57
  break;
58
  }
59
  } catch( Exception $e ) {
60
-
61
  /**
62
- * Экшен выполняетяс, когда проверка лицензии вернула ошибку
 
 
 
63
  *
64
- * @param string $action
65
  * @param string $license_key
66
  * @param string $error_message
67
  *
68
- * @since 2.0.7
69
  */
70
- do_action( 'wbcr/clearfy/check_license_error', $action, $license_key, $e->getMessage() );
71
-
72
- wp_send_json_error( array( 'error_message' => $e->getMessage() ) );
73
  die();
74
  }
75
-
76
  /**
77
- * Экшен выполняет, когда проверка лицензии успешно завершена
 
 
 
78
  *
79
- * @param string $action
80
  * @param string $license_key
81
  *
82
- * @since 2.0.7
83
  */
84
- do_action( 'wbcr/clearfy/check_license_success', $action, $license_key );
85
-
86
- wp_send_json_success( array( 'message' => $success_message ) );
87
-
88
  die();
89
  }
1
  <?php
2
  /**
3
  * Ajax handlers
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
6
  * @copyright (c) 2017 Webraftic Ltd
7
+ * @version 1.0
8
  */
9
 
10
  // Exit if accessed directly
15
  /**
16
  * Обработчик ajax запросов для проверки, активации, деактивации лицензионного ключа
17
  *
18
+ * @since 2.0.7
19
  *
20
+ * @param Wbcr_Factory424_Plugin $plugin_instance
21
  *
22
  */
23
+ function wbcr_factory_clearfy_216_check_license( $plugin_instance ) {
24
+
25
+ $plugin_name = $plugin_instance->request->post( 'plugin_name', null, true );
26
+
27
+ if ( ( $plugin_instance->getPluginName() !== $plugin_name ) || ! $plugin_instance->current_user_can() ) {
28
+ wp_die( - 1, 403 );
29
+ }
30
+
31
  $action = $plugin_instance->request->post( 'license_action', false, true );
32
  $license_key = $plugin_instance->request->post( 'licensekey', null );
33
+
34
+ check_admin_referer( "clearfy_activate_license_for_{$plugin_name}" );
35
+
36
+ if ( empty( $action ) || ! in_array( $action, [ 'activate', 'deactivate', 'sync', 'unsubscribe' ] ) ) {
37
+ wp_send_json_error( [ 'error_message' => __( 'Licensing action not passed or this action is prohibited!', 'wbcr_factory_clearfy_216' ) ] );
38
  die();
39
  }
40
+
41
  $result = null;
42
  $success_message = '';
43
+
44
  try {
45
  switch ( $action ) {
46
  case 'activate':
47
  if ( empty( $license_key ) || strlen( $license_key ) > 32 ) {
48
+ wp_send_json_error( [ 'error_message' => __( 'License key is empty or license key too long (license key is 32 characters long)', 'wbcr_factory_clearfy_216' ) ] );
49
  } else {
50
  $plugin_instance->premium->activate( $license_key );
51
+ $success_message = __( 'Your license has been successfully activated', 'wbcr_factory_clearfy_216' );
52
  }
53
  break;
54
  case 'deactivate':
55
  $plugin_instance->premium->deactivate();
56
+ $success_message = __( 'The license is deactivated', 'wbcr_factory_clearfy_216' );
57
  break;
58
  case 'sync':
59
  $plugin_instance->premium->sync();
60
+ $success_message = __( 'The license has been updated', 'wbcr_factory_clearfy_216' );
61
  break;
62
  case 'unsubscribe':
63
  $plugin_instance->premium->cancel_paid_subscription();
64
+ $success_message = __( 'Subscription success cancelled', 'wbcr_factory_clearfy_216' );
65
  break;
66
  }
67
  } catch( Exception $e ) {
68
+
69
  /**
70
+ * Экшен выполняется, когда проверка лицензии вернула ошибку
71
+ *
72
+ * @since 2.1.2 Переименован в {$plugin_name}/factory/clearfy/check_license_error
73
+ * @since 2.0.7
74
  *
 
75
  * @param string $license_key
76
  * @param string $error_message
77
  *
78
+ * @param string $action
79
  */
80
+ do_action( "{$plugin_name}/factory/clearfy/check_license_error", $action, $license_key, $e->getMessage() );
81
+
82
+ wp_send_json_error( [ 'error_message' => $e->getMessage() ] );
83
  die();
84
  }
85
+
86
  /**
87
+ * Экшен выполняется, когда проверка лицензии успешно завершена
88
+ *
89
+ * @since 2.1.2 Переименован в {$plugin_name}/factory/clearfy/check_license_success
90
+ * @since 2.0.7
91
  *
 
92
  * @param string $license_key
93
  *
94
+ * @param string $action
95
  */
96
+ do_action( "{$plugin_name}/factory/clearfy/check_license_success", $action, $license_key );
97
+
98
+ wp_send_json_success( [ 'message' => $success_message ] );
99
+
100
  die();
101
  }
libs/factory/clearfy/includes/check-clearfy-compatibility.php DELETED
@@ -1,306 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Класс позволяет получить информацию о плагине Clearfy и его совместимость с другими плагинами.
5
- * Наследует класс Wbcr_Factory_Compatibility, который отвечает за проверку базовой совместимости сайта.
6
- *
7
- * @author Webcraftic <wordpress.webraftic@gmail.com>
8
- * @copyright (c) 26.09.2018, Webcraftic
9
- * @version 1.0.0
10
- * @since 2.0.5
11
- */
12
- if( !class_exists('Wbcr_FactoryClearfy_Compatibility') ) {
13
-
14
- class Wbcr_FactoryClearfy_Compatibility extends Wbcr_Factory_Compatibility {
15
-
16
- protected $factory_version;
17
-
18
- /**
19
- * @var bool
20
- */
21
- protected $plugin_as_component;
22
-
23
- /**
24
- * @var bool
25
- */
26
- protected $plugin_already_activate;
27
-
28
- /**
29
- * @var bool
30
- */
31
- protected $plugin_dir;
32
-
33
- /**
34
- * @var bool
35
- */
36
- protected $plugin_base;
37
-
38
- /**
39
- * @var bool
40
- */
41
- protected $plugin_url;
42
-
43
- /**
44
- * С какой версией Clearfy может работать этот плагин
45
- *
46
- * @var string
47
- */
48
- protected $required_clearfy_version = '1.4.2';
49
-
50
- /**
51
- * Нужно ли требовать активацию Clearfy для работы этого плагина
52
- * Если true, то нужно
53
- *
54
- * @var bool по умолчанию false
55
- */
56
- protected $required_clearfy_active = false;
57
-
58
-
59
- /**
60
- * Нужно ли проверять активирован ли этот плагин, как компонент в плагине Clearfy
61
- * Если true, то нужно
62
- *
63
- * @var bool по умолчанию false
64
- */
65
- protected $required_clearfy_check_component = false;
66
-
67
- /**
68
- * Нужно ли проверять совместимость фреймворка для работы с плагином Clearfy
69
- * Если true, то нужно
70
- *
71
- * @var bool по умолчанию false
72
- */
73
- protected $required_clearfy_framework_compatibility = false;
74
-
75
-
76
- /**
77
- * Нужно ли проверять совместимость этого плагин с версией Clearfy
78
- * Если true, то нужно
79
- *
80
- * @var bool по умолчанию false
81
- */
82
- protected $required_clearfy_version_compatibility = false;
83
-
84
-
85
- function __construct(array $plugin_info)
86
- {
87
- parent::__construct($plugin_info);
88
- }
89
-
90
- /**
91
- * Это статистический метод. Вовзращает директорию плагина Clearfy
92
- *
93
- * @return string
94
- */
95
- public static function getClearfyDir()
96
- {
97
- $folder_name = 'clearfy';
98
-
99
- return WP_PLUGIN_DIR . '/' . $folder_name;
100
- }
101
-
102
- /**
103
- * Это статистический метод. Вовзращает базовый путь к плагину Clearfy
104
- * Пример: clearfy/clearfy.php
105
- *
106
- * @return string
107
- */
108
- public static function getClearfyBasePath()
109
- {
110
- return plugin_basename(self::getClearfyPluginFile());
111
- }
112
-
113
- /**
114
- * Это статистический метод. Вовзращает aбсолютный путь к основному файлу плагина Clearfy *
115
- * Пример: www/wp-content/plugins/clearfy/clearfy.php
116
- *
117
- * @return string
118
- */
119
- public static function getClearfyPluginFile()
120
- {
121
- return self::getClearfyDir() . '/clearfy.php';
122
- }
123
-
124
- /**
125
- * Это статистический метод. Возвращает версию плагина Clearfy *
126
- * Пример: 1.3.0
127
- *
128
- * @return string
129
- */
130
- public static function getClearfyVersion()
131
- {
132
- require_once ABSPATH . '/wp-admin/includes/plugin.php';
133
-
134
- $plugin_data = get_plugin_data(self::getClearfyPluginFile());
135
-
136
- return !empty($plugin_data['Version']) ? $plugin_data['Version'] : null;
137
- }
138
-
139
- public function registerNotices()
140
- {
141
- if( current_user_can('activate_plugins') && current_user_can('edit_plugins') && current_user_can('install_plugins') ) {
142
- if( is_plugin_active_for_network(self::getClearfyBasePath()) ) {
143
- add_action('network_admin_notices', array($this, 'showNotice'));
144
- } else {
145
- add_action('admin_notices', array($this, 'showNotice'));
146
- }
147
- }
148
- }
149
-
150
-
151
- /**
152
- * Проверяем, активирован ли плагин Clearfy
153
- *
154
- * @return bool
155
- */
156
- public static function isClearfyActivate()
157
- {
158
- require_once ABSPATH . '/wp-admin/includes/plugin.php';
159
-
160
- return is_plugin_active(self::getClearfyBasePath());
161
- }
162
-
163
- /**
164
- * Проверяем, активирован ли плагин, как компонент в Clearfy
165
- *
166
- * @return bool
167
- */
168
- public function isPluginActiveAsComponent()
169
- {
170
- return self::isClearfyActivate() && !$this->plugin_as_component;
171
- }
172
-
173
- /**
174
- * Проверяем совместимость с версией фреймворка, который использует плагина Clearfy
175
- *
176
- * @return bool
177
- */
178
- public function checkClearfyFrameworkCompatibility()
179
- {
180
- if( !defined('WBCR_CLEARFY_FRAMEWORK_VER') || empty($this->factory_version) ) {
181
- return false;
182
- }
183
-
184
- return WBCR_CLEARFY_FRAMEWORK_VER == $this->factory_version;
185
- }
186
-
187
- /**
188
- * Проверяем совместимость этого плагина с версией Clearfy
189
- *
190
- * @return bool
191
- */
192
- public function checkClearfyVersionCompatibility()
193
- {
194
- $plugin_version = self::getClearfyVersion();
195
-
196
- if( !empty($plugin_version) ) {
197
- if( !version_compare($plugin_version, $this->required_clearfy_version, '>=') ) {
198
- return false;
199
- }
200
- }
201
-
202
- return true;
203
- }
204
-
205
- /**
206
- * Совместимость с плагином Clearfy, проверяется только в премиум компонентах,
207
- * так как компоненты компилируются с Clearfy на одной версии фреймворка
208
- *
209
- * @return bool|mixed
210
- */
211
- public function check()
212
- {
213
- if( $this->plugin_already_activate ) {
214
- return false;
215
- }
216
-
217
- if( $this->required_clearfy_check_component && $this->isPluginActiveAsComponent() ) {
218
- return false;
219
- }
220
-
221
- if( !parent::check() ) {
222
- return false;
223
- }
224
-
225
- if( !self::checkClearfyFrameworkCompatibility() && $this->required_clearfy_framework_compatibility ) {
226
- return false;
227
- }
228
-
229
- if( $this->required_clearfy_active ) {
230
- if( self::isClearfyActivate() ) {
231
- if( $this->required_clearfy_version_compatibility ) {
232
- $plugin_version = self::getClearfyVersion();
233
-
234
- if( !empty($plugin_version) ) {
235
- if( !version_compare($plugin_version, $this->required_clearfy_version, '>=') ) {
236
- return false;
237
- }
238
- }
239
- }
240
- } else {
241
- return false;
242
- }
243
- }
244
-
245
- return true;
246
- }
247
-
248
- /**
249
- * Метод возвращает текст уведомления
250
- *
251
- * @return string
252
- */
253
- public function getNoticeText()
254
- {
255
- if( !self::isClearfyActivate() && !$this->required_clearfy_active ) {
256
- return parent::getNoticeText();
257
- }
258
-
259
- $notice_text = $notice_default_text = '';
260
-
261
- if( self::isClearfyActivate() ) {
262
- $notice_default_text .= '<b>' . __('Clearfy warning', 'wbcr_factory_clearfy_208') . ':</b>' . '<br>';
263
- $phrase = sprintf(__('The %s component', 'wbcr_factory_clearfy_208'), $this->plugin_title);
264
- } else {
265
- $notice_default_text .= '<b>' . $this->plugin_title . ' ' . __('warning', 'wbcr_factory_clearfy_208') . ':</b>' . '<br>';
266
- $phrase = sprintf(__('The %s plugin', 'wbcr_factory_clearfy_208'), $this->plugin_title);
267
- }
268
-
269
- $notice_default_text .= $phrase . ' ' . __('has stopped.', 'wbcr_factory_clearfy_208');
270
- $notice_default_text .= __('Possible reasons:', 'wbcr_factory_clearfy_208') . ' <br>';
271
-
272
- $has_one = false;
273
-
274
- if( !$this->isPhpCompatibility() ) {
275
- $has_one = true;
276
- $notice_text .= '- ' . sprintf(__('You need to update the PHP version to %s or higher!', 'wbcr_factory_clearfy_208'), $this->required_php_version) . '<br>';
277
- }
278
-
279
- if( !$this->isWpCompatibility() ) {
280
- $has_one = true;
281
- $notice_text .= '- ' . sprintf(__('You need to update WordPress to %s or higher!', 'wbcr_factory_clearfy_208'), $this->required_wp_version) . '<br>';
282
- }
283
-
284
- if( $this->required_clearfy_version_compatibility && !$this->checkClearfyVersionCompatibility() ) {
285
- $has_one = true;
286
- $notice_text .= '- ' . sprintf(__('You need to update the Clearfy plugin version to %s or higher!', 'wbcr_factory_clearfy_208'), $this->required_clearfy_version) . '<br>';
287
- }
288
-
289
- if( $this->plugin_already_activate ) {
290
- $has_one = true;
291
- $notice_text = '- ' . sprintf(__('This plugin is already activated, you are trying to activate it again.', 'wbcr_factory_clearfy_208'), $this->required_php_version) . '<br>';
292
- }
293
-
294
- if( $this->required_clearfy_check_component && $this->isPluginActiveAsComponent() ) {
295
- $has_one = true;
296
- $notice_text = '- ' . sprintf(__('Clearfy has the features of the %s plugin. Please, deactivate %s to avoid conflicts of plugins!', 'wbcr_factory_clearfy_208'), $this->plugin_title, $this->plugin_title) . '<br>';
297
- }
298
-
299
- if( $has_one ) {
300
- $notice_text = $notice_default_text . $notice_text;
301
- }
302
-
303
- return $notice_text;
304
- }
305
- }
306
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/factory/clearfy/includes/class-clearfy-configurate.php DELETED
@@ -1,120 +0,0 @@
1
- <?php
2
- /**
3
- * Configurate clearfy plugins
4
- *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
- * @copyright (c) 2018, Webcraftic Ltd
7
- *
8
- * @package clearfy
9
- * @since 1.0.0
10
- */
11
-
12
- // Exit if accessed directly
13
- if( !defined('ABSPATH') ) {
14
- exit;
15
- }
16
-
17
- if( !class_exists('Wbcr_FactoryClearfy208_Configurate') ) {
18
-
19
- abstract class Wbcr_FactoryClearfy208_Configurate {
20
-
21
- /**
22
- * @param Wbcr_Factory412_Plugin $plugin
23
- */
24
- public function __construct(Wbcr_Factory412_Plugin $plugin)
25
- {
26
- $this->plugin = $plugin;
27
- $this->registerActionsAndFilters();
28
- }
29
-
30
- /**
31
- * Registers filters and actions
32
- * @return mixed
33
- */
34
- abstract protected function registerActionsAndFilters();
35
-
36
- /**
37
- * Get options with namespace
38
- *
39
- * @param $option_name
40
- * @param bool $default
41
- * @return mixed|void
42
- */
43
- public function getPopulateOption($option_name, $default = false)
44
- {
45
- return $this->plugin->getPopulateOption($option_name, $default);
46
- }
47
-
48
- /**
49
- * Get options with namespace
50
- *
51
- * @param $option_name
52
- * @param bool $default
53
- * @return mixed|void
54
- */
55
- public function getOption($option_name, $default = false)
56
- {
57
- return $this->plugin->getOption($option_name, $default);
58
- }
59
-
60
- /**
61
- * Get network options with namespace
62
- *
63
- * @param $option_name
64
- * @param bool $default
65
- * @return mixed|void
66
- */
67
- public function getNetworkOption($option_name, $default = false)
68
- {
69
- return $this->plugin->getNetworkOption($option_name, $default);
70
- }
71
-
72
- /**
73
- * @param $option_name
74
- * @param $value
75
- * @return bool
76
- */
77
- public function updatePopulateOption($option_name, $value)
78
- {
79
- $this->plugin->updatePopulateOption($option_name, $value);
80
- }
81
-
82
- /**
83
- * @param $option_name
84
- * @param $value
85
- * @return bool
86
- */
87
- public function updateNetworkOption($option_name, $value)
88
- {
89
- $this->plugin->updateNetworkOption($option_name, $value);
90
- }
91
-
92
- /**
93
- * @param $option_name
94
- * @param $value
95
- * @return bool
96
- */
97
- public function updateOption($option_name, $value)
98
- {
99
- $this->plugin->updateOption($option_name, $value);
100
- }
101
-
102
- /**
103
- * @param $option_name
104
- * @return bool
105
- */
106
- public function deletePopulateOption($option_name)
107
- {
108
- $this->plugin->deletePopulateOption($option_name);
109
- }
110
-
111
- /**
112
- * @param $option_name
113
- * @return bool
114
- */
115
- public function deleteOption($option_name)
116
- {
117
- $this->plugin->deleteOption($option_name);
118
- }
119
- }
120
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/factory/clearfy/includes/class-clearfy-helpers.php DELETED
@@ -1,370 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Helpers functions
5
- *
6
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
7
- * @copyright (c) 2018, Webcraftic Ltd
8
- *
9
- * @package clearfy
10
- * @since 1.0.0
11
- */
12
-
13
- // Exit if accessed directly
14
- if( !defined('ABSPATH') ) {
15
- exit;
16
- }
17
-
18
- if( !class_exists('WbcrFactoryClearfy208_Helpers') ) {
19
- class WbcrFactoryClearfy208_Helpers {
20
-
21
- /**
22
- * Ссылка по умолчанию (анг)
23
- */
24
- const WEBCRAFTIC_SITE_URL = 'https://clearfy.pro';
25
-
26
- /**
27
- * Русская локализация сайта
28
- */
29
- const WEBCRAFTIC_RU_SITE_URL = 'https://ru.clearfy.pro';
30
- /**
31
- * Украинская локализация сайта
32
- */
33
- const WEBCRAFTIC_UA_SITE_URL = 'https://ua.clearfy.pro';
34
- /**
35
- * Испанская
36
- */
37
- const WEBCRAFTIC_ES_SITE_URL = 'https://es.clearfy.pro';
38
- /**
39
- * Французкая
40
- */
41
- const WEBCRAFTIC_DE_SITE_URL = 'https://de.clearfy.pro';
42
-
43
- /**
44
- * @since 2.0.5
45
- * @param int $price
46
- * @return int
47
- */
48
- public static function getClearfyBusinessPrice($price = 19)
49
- {
50
- return (int)apply_filters('wbcr/clearfy/business_price', $price);
51
- }
52
-
53
- /**
54
- * @since 2.0.5
55
- * @param int $price
56
- * @return int
57
- */
58
- public static function getClearfyBusinessRevPrice($price = 69)
59
- {
60
- return (int)apply_filters('wbcr/clearfy/business_rev_price', $price);
61
- }
62
-
63
- /**
64
- * Get a link to the official website of the developer
65
- *
66
- * @return string|null
67
- */
68
- public static function getWebcrafticSiteUrl()
69
- {
70
- if( get_locale() == 'ru_RU' ) {
71
- return self::WEBCRAFTIC_RU_SITE_URL;
72
- }
73
-
74
- return self::WEBCRAFTIC_SITE_URL;
75
- }
76
-
77
- /**
78
- * /**
79
- * Get a link to the official website of the developer
80
- *
81
- * @since 2.0.5
82
- * @param string $plugin_name
83
- * @param string $page - page address
84
- * @param string $utm_content - from which page or part of the plugin user moved to the site
85
- * @param string $urm_source
86
- * @return string
87
- */
88
- public static function getWebcrafticSitePageUrl($plugin_name, $page, $utm_content = null, $urm_source = 'wordpress.org')
89
- {
90
- $args = array('utm_source' => $urm_source);
91
-
92
- if( !empty($plugin_name) ) {
93
- $args['utm_campaign'] = $plugin_name;
94
- }
95
-
96
- if( !empty($utm_content) ) {
97
- $args['utm_content'] = $utm_content;
98
- }
99
-
100
- $raw_url = add_query_arg($args, self::getWebcrafticSiteUrl() . '/' . $page . '/');
101
- $url = esc_url($raw_url);
102
-
103
- /**
104
- * @param string $url
105
- * @param string $raw_url
106
- * @param string $plugin_name
107
- * @param string $page - page address
108
- * @param string $utm_content - from which page or part of the plugin user moved to the site
109
- * @param string $urm_source
110
- */
111
-
112
- return apply_filters('wbcr/clearfy/webcraftic_site_page_url', $url, $raw_url, $plugin_name, $page, $utm_content, $urm_source);
113
- }
114
-
115
- /**
116
- * Recursive sanitation for an array
117
- *
118
- * @param $array
119
- * @since 2.0.5
120
- * @return mixed
121
- */
122
- public static function recursiveSanitizeArray($array, $function)
123
- {
124
- foreach($array as $key => &$value) {
125
- if( is_array($value) ) {
126
- $value = self::recursiveSanitizeArray($value, $function);
127
- } else {
128
- if( function_exists($function) ) {
129
- $value = $function($value);
130
- }
131
- }
132
- }
133
-
134
- return $array;
135
- }
136
-
137
- /**
138
- * Is permalink enabled?
139
- * @global WP_Rewrite $wp_rewrite
140
- * @since 1.0.0
141
- * @return bool
142
- */
143
- public static function isPermalink()
144
- {
145
- global $wp_rewrite;
146
-
147
- if( !isset($wp_rewrite) || !is_object($wp_rewrite) || !$wp_rewrite->using_permalinks() ) {
148
- return false;
149
- }
150
-
151
- return true;
152
- }
153
-
154
- /**
155
- * Display 404 page to bump bots and bad guys
156
- *
157
- * @param bool $simple If true force displaying basic 404 page
158
- */
159
- public static function setError404()
160
- {
161
- global $wp_query;
162
-
163
- if( function_exists('status_header') ) {
164
- status_header('404');
165
- nocache_headers();
166
- }
167
-
168
- if( $wp_query && is_object($wp_query) ) {
169
- $wp_query->set_404();
170
- get_template_part(404);
171
- } else {
172
- global $pagenow;
173
-
174
- $pagenow = 'index.php';
175
-
176
- if( !defined('WP_USE_THEMES') ) {
177
- define('WP_USE_THEMES', true);
178
- }
179
-
180
- wp();
181
-
182
- $_SERVER['REQUEST_URI'] = self::userTrailingslashit('/hmwp_404');
183
-
184
- require_once(ABSPATH . WPINC . '/template-loader.php');
185
- }
186
-
187
- exit();
188
- }
189
-
190
- public static function useTrailingSlashes()
191
- {
192
- return ('/' === substr(get_option('permalink_structure'), -1, 1));
193
- }
194
-
195
- public static function userTrailingslashit($string)
196
- {
197
- return self::useTrailingSlashes() ? trailingslashit($string) : untrailingslashit($string);
198
- }
199
-
200
- /**
201
- * Returns true if a needle can be found in a haystack
202
- *
203
- * @param string $string
204
- * @param string $find
205
- * @param bool $case_sensitive
206
- * @return bool
207
- */
208
- public static function strContains($string, $find, $case_sensitive = true)
209
- {
210
- if( empty($string) || empty($find) ) {
211
- return false;
212
- }
213
-
214
- $pos = $case_sensitive ? strpos($string, $find) : stripos($string, $find);
215
-
216
- return !($pos === false);
217
- }
218
-
219
- /**
220
- * Tests if a text starts with an given string.
221
- *
222
- * @param string $string
223
- * @param string $find
224
- * @param bool $case_sensitive
225
- * @return bool
226
- */
227
- public static function strStartsWith($string, $find, $case_sensitive = true)
228
- {
229
- if( $case_sensitive ) {
230
- return strpos($string, $find) === 0;
231
- }
232
-
233
- return stripos($string, $find) === 0;
234
- }
235
-
236
- /**
237
- * Tests if a text ends with an given string.
238
- *
239
- * @param $string
240
- * @param $find
241
- * @param bool $case_sensitive
242
- * @return bool
243
- */
244
- public static function strEndsWith($string, $find, $case_sensitive = true)
245
- {
246
- $expected_position = strlen($string) - strlen($find);
247
-
248
- if( $case_sensitive ) {
249
- return strrpos($string, $find, 0) === $expected_position;
250
- }
251
-
252
- return strripos($string, $find, 0) === $expected_position;
253
- }
254
-
255
- public static function arrayMergeInsert(array $arr, array $inserted, $position = 'bottom', $key = null)
256
- {
257
- if( $position == 'top' ) {
258
- return array_merge($inserted, $arr);
259
- }
260
- $key_position = ($key === null) ? false : array_search($key, array_keys($arr));
261
- if( $key_position === false OR ($position != 'before' AND $position != 'after') ) {
262
- return array_merge($arr, $inserted);
263
- }
264
- if( $position == 'after' ) {
265
- $key_position++;
266
- }
267
-
268
- return array_merge(array_slice($arr, 0, $key_position, true), $inserted, array_slice($arr, $key_position, null, true));
269
- }
270
-
271
- public static function maybeGetPostJson($name)
272
- {
273
- if( isset($_POST[$name]) AND is_string($_POST[$name]) ) {
274
- $result = json_decode(stripslashes($_POST[$name]), true);
275
- if( !is_array($result) ) {
276
- $result = array();
277
- }
278
-
279
- return $result;
280
- } else {
281
- return array();
282
- }
283
- }
284
-
285
- public static function getEscapeJson(array $data)
286
- {
287
- return htmlspecialchars(json_encode($data), ENT_QUOTES, 'UTF-8');
288
- }
289
-
290
- /**
291
- * Replace url for multisite
292
- *
293
- * @param $string
294
- *
295
- * @return string
296
- */
297
- public static function replaceMsUrl($string)
298
- {
299
- if( is_multisite() && BLOG_ID_CURRENT_SITE != get_current_blog_id() ) {
300
- return str_replace(get_site_url(BLOG_ID_CURRENT_SITE), get_site_url(get_current_blog_id()), $string);
301
- }
302
-
303
- return $string;
304
- }
305
-
306
- /*
307
- * Flushes as many page cache plugin's caches as possible.
308
- *
309
- * @return void
310
- */
311
- public static function flushPageCache()
312
- {
313
- if( function_exists('wp_cache_clear_cache') ) {
314
- if( is_multisite() ) {
315
- $blog_id = get_current_blog_id();
316
- wp_cache_clear_cache($blog_id);
317
- } else {
318
- wp_cache_clear_cache();
319
- }
320
- } elseif( has_action('cachify_flush_cache') ) {
321
- do_action('cachify_flush_cache');
322
- } elseif( function_exists('w3tc_pgcache_flush') ) {
323
- w3tc_pgcache_flush();
324
- } elseif( function_exists('wp_fast_cache_bulk_delete_all') ) {
325
- wp_fast_cache_bulk_delete_all();
326
- } elseif( class_exists('WpFastestCache') ) {
327
- $wpfc = new WpFastestCache();
328
- $wpfc->deleteCache();
329
- } elseif( class_exists('c_ws_plugin__qcache_purging_routines') ) {
330
- c_ws_plugin__qcache_purging_routines::purge_cache_dir(); // quick cache
331
- } elseif( class_exists('zencache') ) {
332
- zencache::clear();
333
- } elseif( class_exists('comet_cache') ) {
334
- comet_cache::clear();
335
- } elseif( class_exists('WpeCommon') ) {
336
- // WPEngine cache purge/flush methods to call by default
337
- $wpe_methods = array(
338
- 'purge_varnish_cache',
339
- );
340
-
341
- // More agressive clear/flush/purge behind a filter
342
- if( apply_filters('wbcr/factory/flush_wpengine_aggressive', false) ) {
343
- $wpe_methods = array_merge($wpe_methods, array('purge_memcached', 'clear_maxcdn_cache'));
344
- }
345
-
346
- // Filtering the entire list of WpeCommon methods to be called (for advanced usage + easier testing)
347
- $wpe_methods = apply_filters('wbcr/factory/wpengine_methods', $wpe_methods);
348
-
349
- foreach($wpe_methods as $wpe_method) {
350
- if( method_exists('WpeCommon', $wpe_method) ) {
351
- WpeCommon::$wpe_method();
352
- }
353
- }
354
- } elseif( function_exists('sg_cachepress_purge_cache') ) {
355
- sg_cachepress_purge_cache();
356
- } elseif( file_exists(WP_CONTENT_DIR . '/wp-cache-config.php') && function_exists('prune_super_cache') ) {
357
- // fallback for WP-Super-Cache
358
- global $cache_path;
359
- if( is_multisite() ) {
360
- $blog_id = get_current_blog_id();
361
- prune_super_cache(get_supercache_dir($blog_id), true);
362
- prune_super_cache($cache_path . 'blogs/', true);
363
- } else {
364
- prune_super_cache($cache_path . 'supercache/', true);
365
- prune_super_cache($cache_path, true);
366
- }
367
- }
368
- }
369
- }
370
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/factory/clearfy/includes/class-configurate.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * Configurate clearfy plugins
9
+ *
10
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
11
+ * @since 1.0.0
12
+ * @package clearfy
13
+ * @copyright (c) 2018, Webcraftic Ltd
14
+ *
15
+ */
16
+ abstract class Wbcr_FactoryClearfy216_Configurate {
17
+
18
+ /**
19
+ * @param Wbcr_Factory424_Plugin $plugin
20
+ */
21
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
22
+ $this->plugin = $plugin;
23
+ $this->registerActionsAndFilters();
24
+ }
25
+
26
+ /**
27
+ * Registers filters and actions
28
+ *
29
+ * @return mixed
30
+ */
31
+ abstract protected function registerActionsAndFilters();
32
+
33
+ /**
34
+ * Get options with namespace
35
+ *
36
+ * @param $option_name
37
+ * @param bool $default
38
+ *
39
+ * @return mixed|void
40
+ */
41
+ public function getPopulateOption( $option_name, $default = false ) {
42
+ return $this->plugin->getPopulateOption( $option_name, $default );
43
+ }
44
+
45
+ /**
46
+ * Get options with namespace
47
+ *
48
+ * @param $option_name
49
+ * @param bool $default
50
+ *
51
+ * @return mixed|void
52
+ */
53
+ public function getOption( $option_name, $default = false ) {
54
+ return $this->plugin->getOption( $option_name, $default );
55
+ }
56
+
57
+ /**
58
+ * Get network options with namespace
59
+ *
60
+ * @param $option_name
61
+ * @param bool $default
62
+ *
63
+ * @return mixed|void
64
+ */
65
+ public function getNetworkOption( $option_name, $default = false ) {
66
+ return $this->plugin->getNetworkOption( $option_name, $default );
67
+ }
68
+
69
+ /**
70
+ * @param $option_name
71
+ * @param $value
72
+ *
73
+ * @return bool
74
+ */
75
+ public function updatePopulateOption( $option_name, $value ) {
76
+ $this->plugin->updatePopulateOption( $option_name, $value );
77
+ }
78
+
79
+ /**
80
+ * @param $option_name
81
+ * @param $value
82
+ *
83
+ * @return bool
84
+ */
85
+ public function updateNetworkOption( $option_name, $value ) {
86
+ $this->plugin->updateNetworkOption( $option_name, $value );
87
+ }
88
+
89
+ /**
90
+ * @param $option_name
91
+ * @param $value
92
+ *
93
+ * @return bool
94
+ */
95
+ public function updateOption( $option_name, $value ) {
96
+ $this->plugin->updateOption( $option_name, $value );
97
+ }
98
+
99
+ /**
100
+ * @param $option_name
101
+ *
102
+ * @return bool
103
+ */
104
+ public function deletePopulateOption( $option_name ) {
105
+ $this->plugin->deletePopulateOption( $option_name );
106
+ }
107
+
108
+ /**
109
+ * @param $option_name
110
+ *
111
+ * @return bool
112
+ */
113
+ public function deleteOption( $option_name ) {
114
+ $this->plugin->deleteOption( $option_name );
115
+ }
116
+ }
libs/factory/clearfy/includes/class-helpers.php ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+
8
+ /**
9
+ * Helpers functions
10
+ *
11
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
12
+ * @since 1.0.0
13
+ * @package clearfy
14
+ * @copyright (c) 2018, Webcraftic Ltd
15
+ *
16
+ */
17
+ class WbcrFactoryClearfy216_Helpers {
18
+
19
+ /**
20
+ * Recursive sanitation for an array
21
+ *
22
+ * @since 2.0.5
23
+ *
24
+ * @param $array
25
+ *
26
+ * @return mixed
27
+ */
28
+ public static function recursiveSanitizeArray( $array, $function ) {
29
+ foreach ( $array as $key => &$value ) {
30
+ if ( is_array( $value ) ) {
31
+ $value = self::recursiveSanitizeArray( $value, $function );
32
+ } else {
33
+ if ( function_exists( $function ) ) {
34
+ $value = $function( $value );
35
+ }
36
+ }
37
+ }
38
+
39
+ return $array;
40
+ }
41
+
42
+ /**
43
+ * Is permalink enabled?
44
+ *
45
+ * @since 1.0.0
46
+ * @return bool
47
+ * @global WP_Rewrite $wp_rewrite
48
+ */
49
+ public static function isPermalink() {
50
+ global $wp_rewrite;
51
+
52
+ if ( ! isset( $wp_rewrite ) || ! is_object( $wp_rewrite ) || ! $wp_rewrite->using_permalinks() ) {
53
+ return false;
54
+ }
55
+
56
+ return true;
57
+ }
58
+
59
+ /**
60
+ * Display 404 page to bump bots and bad guys
61
+ *
62
+ * @param bool $simple If true force displaying basic 404 page
63
+ */
64
+ public static function setError404() {
65
+ global $wp_query;
66
+
67
+ if ( function_exists( 'status_header' ) ) {
68
+ status_header( '404' );
69
+ nocache_headers();
70
+ }
71
+
72
+ if ( $wp_query && is_object( $wp_query ) ) {
73
+ $wp_query->set_404();
74
+ get_template_part( 404 );
75
+ } else {
76
+ global $pagenow;
77
+
78
+ $pagenow = 'index.php';
79
+
80
+ if ( ! defined( 'WP_USE_THEMES' ) ) {
81
+ define( 'WP_USE_THEMES', true );
82
+ }
83
+
84
+ wp();
85
+
86
+ $_SERVER['REQUEST_URI'] = self::userTrailingslashit( '/hmwp_404' );
87
+
88
+ require_once( ABSPATH . WPINC . '/template-loader.php' );
89
+ }
90
+
91
+ exit();
92
+ }
93
+
94
+ public static function useTrailingSlashes() {
95
+ return ( '/' === substr( get_option( 'permalink_structure' ), - 1, 1 ) );
96
+ }
97
+
98
+ public static function userTrailingslashit( $string ) {
99
+ return self::useTrailingSlashes() ? trailingslashit( $string ) : untrailingslashit( $string );
100
+ }
101
+
102
+ /**
103
+ * Returns true if a needle can be found in a haystack
104
+ *
105
+ * @param string $string
106
+ * @param string $find
107
+ * @param bool $case_sensitive
108
+ *
109
+ * @return bool
110
+ */
111
+ public static function strContains( $string, $find, $case_sensitive = true ) {
112
+ if ( empty( $string ) || empty( $find ) ) {
113
+ return false;
114
+ }
115
+
116
+ $pos = $case_sensitive ? strpos( $string, $find ) : stripos( $string, $find );
117
+
118
+ return ! ( $pos === false );
119
+ }
120
+
121
+ /**
122
+ * Tests if a text starts with an given string.
123
+ *
124
+ * @param string $string
125
+ * @param string $find
126
+ * @param bool $case_sensitive
127
+ *
128
+ * @return bool
129
+ */
130
+ public static function strStartsWith( $string, $find, $case_sensitive = true ) {
131
+ if ( $case_sensitive ) {
132
+ return strpos( $string, $find ) === 0;
133
+ }
134
+
135
+ return stripos( $string, $find ) === 0;
136
+ }
137
+
138
+ /**
139
+ * Tests if a text ends with an given string.
140
+ *
141
+ * @param $string
142
+ * @param $find
143
+ * @param bool $case_sensitive
144
+ *
145
+ * @return bool
146
+ */
147
+ public static function strEndsWith( $string, $find, $case_sensitive = true ) {
148
+ $expected_position = strlen( $string ) - strlen( $find );
149
+
150
+ if ( $case_sensitive ) {
151
+ return strrpos( $string, $find, 0 ) === $expected_position;
152
+ }
153
+
154
+ return strripos( $string, $find, 0 ) === $expected_position;
155
+ }
156
+
157
+ public static function arrayMergeInsert( array $arr, array $inserted, $position = 'bottom', $key = null ) {
158
+ if ( $position == 'top' ) {
159
+ return array_merge( $inserted, $arr );
160
+ }
161
+ $key_position = ( $key === null ) ? false : array_search( $key, array_keys( $arr ) );
162
+ if ( $key_position === false OR ( $position != 'before' AND $position != 'after' ) ) {
163
+ return array_merge( $arr, $inserted );
164
+ }
165
+ if ( $position == 'after' ) {
166
+ $key_position ++;
167
+ }
168
+
169
+ return array_merge( array_slice( $arr, 0, $key_position, true ), $inserted, array_slice( $arr, $key_position, null, true ) );
170
+ }
171
+
172
+ public static function maybeGetPostJson( $name ) {
173
+ if ( isset( $_POST[ $name ] ) AND is_string( $_POST[ $name ] ) ) {
174
+ $result = json_decode( stripslashes( $_POST[ $name ] ), true );
175
+ if ( ! is_array( $result ) ) {
176
+ $result = [];
177
+ }
178
+
179
+ return $result;
180
+ } else {
181
+ return [];
182
+ }
183
+ }
184
+
185
+ public static function getEscapeJson( array $data ) {
186
+ return htmlspecialchars( json_encode( $data ), ENT_QUOTES, 'UTF-8' );
187
+ }
188
+
189
+ /**
190
+ * Replace url for multisite
191
+ *
192
+ * @param $string
193
+ *
194
+ * @return string
195
+ */
196
+ public static function replaceMsUrl( $string ) {
197
+ if ( is_multisite() && BLOG_ID_CURRENT_SITE != get_current_blog_id() ) {
198
+ return str_replace( get_site_url( BLOG_ID_CURRENT_SITE ), get_site_url( get_current_blog_id() ), $string );
199
+ }
200
+
201
+ return $string;
202
+ }
203
+
204
+ /*
205
+ * Flushes as many page cache plugin's caches as possible.
206
+ *
207
+ * @return void
208
+ */
209
+ public static function flushPageCache() {
210
+ if ( function_exists( 'wp_cache_clear_cache' ) ) {
211
+ if ( is_multisite() ) {
212
+ $blog_id = get_current_blog_id();
213
+ wp_cache_clear_cache( $blog_id );
214
+ } else {
215
+ wp_cache_clear_cache();
216
+ }
217
+ } else if ( has_action( 'cachify_flush_cache' ) ) {
218
+ do_action( 'cachify_flush_cache' );
219
+ } else if ( function_exists( 'w3tc_pgcache_flush' ) ) {
220
+ w3tc_pgcache_flush();
221
+ } else if ( function_exists( 'wp_fast_cache_bulk_delete_all' ) ) {
222
+ wp_fast_cache_bulk_delete_all();
223
+ } else if ( class_exists( 'WpFastestCache' ) ) {
224
+ $wpfc = new WpFastestCache();
225
+ $wpfc->deleteCache();
226
+ } else if ( class_exists( 'c_ws_plugin__qcache_purging_routines' ) ) {
227
+ c_ws_plugin__qcache_purging_routines::purge_cache_dir(); // quick cache
228
+ } else if ( class_exists( 'zencache' ) ) {
229
+ zencache::clear();
230
+ } else if ( class_exists( 'comet_cache' ) ) {
231
+ comet_cache::clear();
232
+ } else if ( class_exists( 'WpeCommon' ) ) {
233
+ // WPEngine cache purge/flush methods to call by default
234
+ $wpe_methods = [
235
+ 'purge_varnish_cache',
236
+ ];
237
+
238
+ // More agressive clear/flush/purge behind a filter
239
+ if ( apply_filters( 'wbcr/factory/flush_wpengine_aggressive', false ) ) {
240
+ $wpe_methods = array_merge( $wpe_methods, [ 'purge_memcached', 'clear_maxcdn_cache' ] );
241
+ }
242
+
243
+ // Filtering the entire list of WpeCommon methods to be called (for advanced usage + easier testing)
244
+ $wpe_methods = apply_filters( 'wbcr/factory/wpengine_methods', $wpe_methods );
245
+
246
+ foreach ( $wpe_methods as $wpe_method ) {
247
+ if ( method_exists( 'WpeCommon', $wpe_method ) ) {
248
+ WpeCommon::$wpe_method();
249
+ }
250
+ }
251
+ } else if ( function_exists( 'sg_cachepress_purge_cache' ) ) {
252
+ sg_cachepress_purge_cache();
253
+ } else if ( file_exists( WP_CONTENT_DIR . '/wp-cache-config.php' ) && function_exists( 'prune_super_cache' ) ) {
254
+ // fallback for WP-Super-Cache
255
+ global $cache_path;
256
+ if ( is_multisite() ) {
257
+ $blog_id = get_current_blog_id();
258
+ prune_super_cache( get_supercache_dir( $blog_id ), true );
259
+ prune_super_cache( $cache_path . 'blogs/', true );
260
+ } else {
261
+ prune_super_cache( $cache_path . 'supercache/', true );
262
+ prune_super_cache( $cache_path, true );
263
+ }
264
+ }
265
+ }
266
+ }
libs/factory/clearfy/langs/index.php DELETED
File without changes
libs/factory/clearfy/langs/{wbcr_factory_clearfy_208-ru_RU.mo → wbcr_factory_clearfy_216-ru_RU.mo} RENAMED
File without changes
libs/factory/clearfy/langs/{wbcr_factory_clearfy_208-ru_RU.po → wbcr_factory_clearfy_216-ru_RU.po} RENAMED
File without changes
libs/factory/clearfy/pages/class-clearfy-more-features.php DELETED
@@ -1,148 +0,0 @@
1
- <?php
2
- /**
3
- * The page Settings.
4
- *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
- * @copyright (c) 2018, Webcraftic Ltd
7
- *
8
- * @package clearfy
9
- * @since 1.0.1
10
- */
11
-
12
- // Exit if accessed directly
13
- if( !defined('ABSPATH') ) {
14
- exit;
15
- }
16
-
17
- if( !class_exists('Wbcr_FactoryClearfy208_MoreFeaturesPage') && class_exists('Wbcr_FactoryPages412_ImpressiveThemplate') ) {
18
-
19
- class Wbcr_FactoryClearfy208_MoreFeaturesPage extends Wbcr_FactoryPages412_ImpressiveThemplate {
20
-
21
- public $id = "more_features";
22
-
23
- public $page_menu_dashicon = 'dashicons-star-filled wbcr-factory-orange-color';
24
-
25
- public $page_menu_position = 5;
26
-
27
- public $type = 'page';
28
-
29
- public function __construct(Wbcr_Factory412_Plugin $plugin)
30
- {
31
- $this->menu_title = __('More features (<b>free</b>)', 'wbcr_factory_clearfy_208');
32
-
33
- parent::__construct($plugin);
34
-
35
- $this->plugin = $plugin;
36
- }
37
-
38
- public function getPageTitle()
39
- {
40
- return __('More features', 'wbcr_factory_clearfy_208');
41
- }
42
-
43
- public function showPageContent()
44
- {
45
- ?>
46
- <div class="row">
47
- <div class="col-sm-4">
48
- <div class="wbcr-factory-feature-box">
49
- <span class="dashicons dashicons-yes"></span>
50
-
51
- <h3><?php _e('Code cleaning', 'wbcr_factory_clearfy_208')?></h3>
52
-
53
- <p><?php _e('Clears the source code of the page from unused code.', 'wbcr_factory_clearfy_208')?></p>
54
- </div>
55
- </div>
56
- <div class="col-sm-4">
57
- <div class="wbcr-factory-feature-box">
58
- <span class="dashicons dashicons-chart-bar"></span>
59
-
60
- <h3><?php _e('Improve SEO', 'wbcr_factory_clearfy_208')?></h3>
61
-
62
- <p><?php _e('Removes duplicate pages, closes external links, changes the headers of the server.', 'wbcr_factory_clearfy_208')?></p>
63
- </div>
64
- </div>
65
- <div class="col-sm-4">
66
- <div class="wbcr-factory-feature-box">
67
- <span class="dashicons dashicons-shield-alt"></span>
68
-
69
- <h3><?php _e('Site protection', 'wbcr_factory_clearfy_208')?></h3>
70
-
71
- <p><?php _e('Enables and disables features that improve the protection of your site.', 'wbcr_factory_clearfy_208')?></p>
72
- </div>
73
- </div>
74
- <div class="col-sm-4">
75
- <div class="wbcr-factory-feature-box">
76
- <span class="dashicons dashicons-welcome-comments"></span>
77
-
78
- <h3><?php _e('Disable comments', 'wbcr_factory_clearfy_208')?></h3>
79
-
80
- <p><?php _e('Disables comments on the entire site or on specific pages.', 'wbcr_factory_clearfy_208')?></p>
81
- </div>
82
- </div>
83
- <div class="col-sm-4">
84
- <div class="wbcr-factory-feature-box">
85
- <span class="dashicons dashicons-update"></span>
86
-
87
- <h3><?php _e('Manage updates', 'wbcr_factory_clearfy_208')?></h3>
88
-
89
- <p><?php _e('Enables or disables automatically updates for plugins, themes and core. It is also possible
90
- to disable all updates.', 'wbcr_factory_clearfy_208')?></p>
91
- </div>
92
- </div>
93
- <div class="col-sm-4">
94
- <div class="wbcr-factory-feature-box">
95
- <span class="dashicons dashicons-admin-plugins"></span>
96
-
97
- <h3><?php _e('Manage widgets', 'wbcr_factory_clearfy_208')?></h3>
98
-
99
- <p><?php _e('Allows you to remove unused widgets.', 'wbcr_factory_clearfy_208')?></p>
100
- </div>
101
- </div>
102
- <div class="col-sm-4">
103
- <div class="wbcr-factory-feature-box">
104
- <span class="dashicons dashicons-dashboard"></span>
105
-
106
- <h3><?php _e('Speed Optimization', 'wbcr_factory_clearfy_208')?></h3>
107
-
108
- <p><?php _e('Increases performance by disabling unused functions and reducing the number of requests.', 'wbcr_factory_clearfy_208')?></p>
109
- </div>
110
- </div>
111
- <div class="col-sm-4">
112
- <div class="wbcr-factory-feature-box">
113
- <span class="dashicons dashicons-visibility"></span>
114
-
115
- <h3><?php _e('Site privacy', 'wbcr_factory_clearfy_208')?></h3>
116
-
117
- <p><?php _e('Allows you to hide the version of the site and plugins. Allows you to hide your
118
- WordPress.', 'wbcr_factory_clearfy_208')?></p>
119
- </div>
120
- </div>
121
- <div class="col-sm-4">
122
- <div class="wbcr-factory-feature-box">
123
- <span class="dashicons dashicons-admin-settings"></span>
124
-
125
- <h3><?php _e('Easy setup', 'wbcr_factory_clearfy_208')?></h3>
126
-
127
- <p><?php _e('In quick mode, you can easily configure the plugin according to your needs.', 'wbcr_factory_clearfy_208')?></p>
128
- </div>
129
- </div>
130
- </div>
131
-
132
- <div class="wbcr-factory-buttons-wrap">
133
- <?php
134
- $url = 'https://clearfy.pro';
135
-
136
- if( get_locale() == 'ru_RU' ) {
137
- $url = 'https://ru.clearfy.pro';
138
- }
139
- $url .= '?utm_source=wordpress.org&utm_campaign=' . $this->plugin->getPluginName();
140
- ?>
141
- <a href="<?= $url ?>" class="wbcr-factory-premium-button" target="_blank">
142
- <?php _e('Get the ultimate plugin 100% FREE', 'wbcr_factory_clearfy_208')?>
143
- </a>
144
- </div>
145
- <?php
146
- }
147
- }
148
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/factory/clearfy/pages/class-clearfy-pages.php DELETED
@@ -1,385 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Общий класс прослойка для страниц Clearfy и его компоннетов.
5
- * В этом классе добавляются общие ресурсы и элементы, необходимые для всех связанных плагинов.
6
- *
7
- * Author: Webcraftic <wordpress.webraftic@gmail.com>
8
- * Version: 1.1.0
9
- * @since 2.0.5
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- /**
18
- * Class Wbcr_FactoryPages412_ImpressiveThemplate
19
- *
20
- * @method string getInfoWidget() - get widget content information
21
- * @method string getRatingWidget( array $args = array() ) - get widget content rating
22
- * @method string getDonateWidget() - get widget content donate
23
- * @method string getBusinessSuggetionWidget()
24
- */
25
-
26
- if ( ! class_exists( 'Wbcr_FactoryClearfy208_PageBase' ) && class_exists( 'Wbcr_FactoryPages412_ImpressiveThemplate' ) ) {
27
-
28
- class Wbcr_FactoryClearfy208_PageBase extends Wbcr_FactoryPages412_ImpressiveThemplate {
29
-
30
- /**
31
- * Показывать правый сайдбар?
32
- * Сайдбар будет показан на внутренних страницах шаблона.
33
- *
34
- * @var bool
35
- */
36
- public $show_right_sidebar_in_options = true;
37
-
38
- /**
39
- * Страница доступна в меню суперадмнистратора (режим мультисайтов)
40
- *
41
- * @var bool
42
- */
43
- public $available_for_multisite = true;
44
-
45
- /**
46
- * Показывать нижний сайдбар?
47
- * Сайдбар будет показан на внутренних страницах шаблона.
48
- *
49
- * @var bool
50
- */
51
- //public $show_bottom_sidebar = false;
52
-
53
- /**
54
- * @param Wbcr_Factory412_Plugin $plugin
55
- */
56
- public function __construct( Wbcr_Factory412_Plugin $plugin ) {
57
- parent::__construct( $plugin );
58
- }
59
-
60
- /**
61
- * @param $name
62
- * @param $arguments
63
- *
64
- * @return null|string
65
- */
66
- public function __call( $name, $arguments ) {
67
- if ( substr( $name, 0, 3 ) == 'get' ) {
68
- $called_method_name = 'show' . substr( $name, 3 );
69
- if ( method_exists( $this, $called_method_name ) ) {
70
- ob_start();
71
-
72
- $this->$called_method_name( $arguments );
73
- $content = ob_get_contents();
74
- ob_end_clean();
75
-
76
- return $content;
77
- }
78
- }
79
-
80
- return null;
81
- }
82
-
83
- /**
84
- * Requests assets (js and css) for the page.
85
- *
86
- * @see Wbcr_FactoryPages412_AdminPage
87
- *
88
- * @param Wbcr_Factory412_ScriptList $scripts
89
- * @param Wbcr_Factory412_StyleList $styles
90
- *
91
- * @return void
92
- */
93
- public function assets( $scripts, $styles ) {
94
- parent::assets( $scripts, $styles );
95
-
96
- $this->styles->add( FACTORY_CLEARFY_208_URL . '/assets/css/clearfy-base.css' );
97
-
98
- // todo: вынести все общие скрипты и стили фреймворка, продумать совместимость с другими плагинами
99
- if ( defined( 'WCL_PLUGIN_URL' ) ) {
100
- $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
101
- }
102
-
103
- wbcr_factory_412_do_action_deprecated( 'wbcr_clearfy_page_enqueue_scripts', array(
104
- $this->getResultId(),
105
- $scripts,
106
- $styles
107
- ), '1.4.0', 'wbcr/clearfy/page_assets' );
108
-
109
- /**
110
- * Allows you to enqueue scripts to the internal pages of the plugin.
111
- * $this->getResultId() - page id + plugin name = quick_start-wbcr_clearfy
112
- * @since 2.0.5
113
- */
114
- do_action( 'wbcr/clearfy/page_assets', $this->getResultId(), $scripts, $styles );
115
- }
116
-
117
- /**
118
- * @return Wbcr_Factory412_Request
119
- */
120
- public function request() {
121
- return $this->plugin->request;
122
- }
123
-
124
- /**
125
- * @since 2.0.5
126
- *
127
- * @param $option_name
128
- * @param bool $default *
129
- *
130
- * @return mixed|void
131
- */
132
- public function getPopulateOption( $option_name, $default = false ) {
133
- return $this->plugin->getPopulateOption( $option_name, $default );
134
- }
135
-
136
- /**
137
- * @param $option_name
138
- * @param bool $default
139
- *
140
- * @return mixed|void
141
- */
142
- public function getOption( $option_name, $default = false ) {
143
- return $this->plugin->getOption( $option_name, $default );
144
- }
145
-
146
- /**
147
- * @param $option_name
148
- * @param $value
149
- *
150
- * @return void
151
- */
152
- public function updatePopulateOption( $option_name, $value ) {
153
- $this->plugin->updatePopulateOption( $option_name, $value );
154
- }
155
-
156
- /**
157
- * @param $option_name
158
- * @param $value
159
- *
160
- * @return void
161
- */
162
- public function updateOption( $option_name, $value ) {
163
- $this->plugin->updateOption( $option_name, $value );
164
- }
165
-
166
- /**
167
- * @param $option_name
168
- *
169
- * @return void
170
- */
171
- public function deletePopulateOption( $option_name ) {
172
- $this->plugin->deletePopulateOption( $option_name );
173
- }
174
-
175
- /**
176
- * @param $option_name
177
- *
178
- * @return void
179
- */
180
- public function deleteOption( $option_name ) {
181
- $this->plugin->deleteOption( $option_name );
182
- }
183
-
184
-
185
- /**
186
- * Действие выполняется для всех страниц Clearfy и его компонентах.
187
- * Это простое предложение перейти на PRO версию.
188
- */
189
- public function multisiteProAction() {
190
- if ( is_multisite() && $this->plugin->isNetworkActive() ) {
191
-
192
- $license_page_url = $this->getBaseUrl( 'license' );
193
- $upgrade_url = WbcrFactoryClearfy208_Helpers::getWebcrafticSitePageUrl( $this->plugin->getPluginName(), 'pricing', 'multisite_save_settings' );
194
- $upgrade_price = WbcrFactoryClearfy208_Helpers::getClearfyBusinessPrice();
195
-
196
- $html = '<div class="wbcr-factory-clearfy-208-multisite-suggetion">';
197
- $html .= '<div class="wbcr-factory-inner-contanier">';
198
- $html .= '<h3>' . __( 'Upgrade to Clearfy Business', 'wbcr_factory_clearfy_208' ) . '</h3>';
199
- $html .= '<p>' . __( 'Oops... Sorry for the inconvenience caused!', 'wbcr_factory_clearfy_208' ) . '</p>';
200
- $html .= '<p>' . __( 'Complete multisite support is available in Clearfy Business and Clearfy Business Revolution packages only!', 'wbcr_factory_clearfy_208' ) . '</p>';
201
- $html .= '<p>' . __( 'You can activate the plugin on each website and use it with zero limitations. But you can’t save the plugin’s settings under the Super Administrator role!', 'wbcr_factory_clearfy_208' ) . '</p>';
202
- $html .= '<p style="margin-top:20px">';
203
- $html .= '<a href="' . $license_page_url . '" class="wbcr-factory-activate-premium" rel="noopener">' . __( 'Activate license ', 'wbcr_factory_clearfy_208' ) . '</a> ';
204
- $html .= '<a href="' . $upgrade_url . '" class="wbcr-factory-purchase-premium" target="_blank" rel="noopener">' . sprintf( __( 'Upgrade to Clearfy Business for $%d', 'wbcr_factory_clearfy_208' ), $upgrade_price ) . '</a>';
205
- $html .= '</p>';
206
- $html .= '</div>';
207
- $html .= '</div>';
208
-
209
- $this->showPage( $html );
210
-
211
- return;
212
- }
213
-
214
- $this->redirectToAction( 'index' );
215
- }
216
-
217
- /**
218
- * @param string $position
219
- *
220
- * @return mixed|void
221
- */
222
- protected function getPageWidgets( $position = 'bottom' ) {
223
- $widgets = array();
224
-
225
- if ( $position == 'bottom' ) {
226
- $widgets['info_widget'] = $this->getInfoWidget();
227
- $widgets['rating_widget'] = $this->getRatingWidget();
228
- $widgets['donate_widget'] = $this->getDonateWidget();
229
- } else if ( $position == 'right' ) {
230
- $widgets['businnes_suggetion'] = $this->getBusinessSuggetionWidget();
231
- $widgets['info_widget'] = $this->getInfoWidget();
232
- $widgets['rating_widget'] = $this->getRatingWidget();
233
- }
234
-
235
- /**
236
- * @since 4.0.9 - является устаревшим
237
- */
238
- $widgets = wbcr_factory_412_apply_filters_deprecated( 'wbcr_factory_pages_412_imppage_get_widgets', array(
239
- $widgets,
240
- $position,
241
- $this->plugin,
242
- $this
243
- ), '4.0.9', 'wbcr/factory/pages/impressive/widgets' );
244
-
245
- /**
246
- * @since 4.0.1 - добавлен
247
- * @since 4.0.9 - изменено имя
248
- */
249
- $widgets = apply_filters( 'wbcr/factory/pages/impressive/widgets', $widgets, $position, $this->plugin, $this );
250
-
251
- return $widgets;
252
- }
253
-
254
- public function showBusinessSuggetionWidget() {
255
- $plugin_name = $this->plugin->getPluginName();
256
- $upgrade_price = $this->plugin->has_premium() ? $this->plugin->premium->get_price() : 0;
257
- $purchase_url = $this->plugin->get_support()->get_pricing_url( true, 'right_sidebar_ads' );
258
-
259
- $default_features = array(
260
- '4_premium' => __( '4 premium components now;', 'wbcr_factory_clearfy_208' ),
261
- '40_premium' => __( '40 new premium components within a year for the single price;', 'wbcr_factory_clearfy_208' ),
262
- 'multisite_support' => __( 'Multisite support;', 'wbcr_factory_clearfy_208' ),
263
- 'advance_settings' => __( 'Advanced settings;', 'wbcr_factory_clearfy_208' ),
264
- 'no_ads' => __( 'No ads;', 'wbcr_factory_clearfy_208' ),
265
- 'perfect_support' => __( 'Perfect support.', 'wbcr_factory_clearfy_208' )
266
- );
267
-
268
- /**
269
- * @since 2.0.8 - added
270
- */
271
- $suggetion_title = __( 'MORE IN CLEARFY <span>BUSINESS</span>', 'wbcr_factory_clearfy_208' );
272
- $suggetion_title = apply_filters( 'wbcr/clearfy/pages/suggetion_title', $suggetion_title, $plugin_name, $this->id );
273
-
274
- /**
275
- * @since 2.0.8 - deprecated
276
- */
277
- $suggetion_features = wbcr_factory_412_apply_filters_deprecated( 'wbcr/clearfy/page_bussines_suggetion_features', array(
278
- $default_features,
279
- $this->plugin->getPluginName(),
280
- $this->id
281
- ), '2.0.8', 'wbcr/clearfy/pages/suggetion_features' );
282
-
283
- /**
284
- * @since 2.0.8 - renamed
285
- * @since 2.0.6
286
- */
287
- $suggetion_features = apply_filters( 'wbcr/clearfy/pages/suggetion_features', $suggetion_features, $plugin_name, $this->id );
288
-
289
- if ( empty( $suggetion_features ) ) {
290
- $suggetion_features = $default_features;
291
- }
292
- ?>
293
- <div class="wbcr-factory-sidebar-widget wbcr-factory-clearfy-208-pro-suggettion">
294
- <h3><?php echo $suggetion_title; ?></h3>
295
- <ul>
296
- <?php if ( ! empty( $suggetion_features ) ): ?>
297
- <?php foreach ( $suggetion_features as $feature ): ?>
298
- <li><?= $feature ?></li>
299
- <?php endforeach; ?>
300
- <?php endif; ?>
301
- </ul>
302
- <a href="<?php echo $purchase_url ?>" class="wbcr-factory-purchase-premium" target="_blank" rel="noopener">
303
- <?php printf( __( 'Upgrade for $%s', 'wbcr_factory_clearfy_208' ), $upgrade_price ) ?>
304
- </a>
305
- </div>
306
- <?php
307
- }
308
-
309
- public function showInfoWidget() {
310
- ?>
311
- <div class="wbcr-factory-sidebar-widget">
312
- <ul>
313
- <li>
314
- <span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-red">
315
- <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt=""/>
316
- </span>
317
- - <?php _e( 'A neutral setting that can not harm your site, but you must be sure that you need to use it.', 'wbcr_factory_clearfy_208' ); ?>
318
- </li>
319
- <li>
320
- <span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-grey">
321
- <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt=""/>
322
- </span>
323
- - <?php _e( 'When set this option, you must be careful. Plugins and themes may depend on this function. You must be sure that you can disable this feature for the site.', 'wbcr_factory_clearfy_208' ); ?>
324
- </li>
325
- <li>
326
- <span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-green">
327
- <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt=""/>
328
- </span>
329
- - <?php _e( 'Absolutely safe setting, We recommend to use.', 'wbcr_factory_clearfy_208' ); ?>
330
- </li>
331
- </ul>
332
- ----------<br>
333
- <p><?php _e( 'Hover to the icon to get help for the feature you selected.', 'wbcr_factory_clearfy_208' ); ?></p>
334
- </div>
335
- <?php
336
- }
337
-
338
- public function showRatingWidget( array $args ) {
339
- if ( ! isset( $args[0] ) || empty( $args[0] ) ) {
340
- $page_url = "https://goo.gl/tETE2X";
341
- } else {
342
- $page_url = $args[0];
343
- }
344
-
345
- $page_url = apply_filters( 'wbcr_factory_pages_412_imppage_rating_widget_url', $page_url, $this->plugin->getPluginName(), $this->getResultId() );
346
-
347
- ?>
348
- <div class="wbcr-factory-sidebar-widget">
349
- <p>
350
- <strong><?php _e( 'Do you want the plugin to improved and update?', 'wbcr_factory_clearfy_208' ); ?></strong>
351
- </p>
352
- <p><?php _e( 'Help the author, leave a review on wordpress.org. Thanks to feedback, I will know that the plugin is really useful to you and is needed.', 'wbcr_factory_clearfy_208' ); ?></p>
353
- <p><?php _e( 'And also write your ideas on how to extend or improve the plugin.', 'wbcr_factory_clearfy_208' ); ?></p>
354
- <p>
355
- <i class="wbcr-factory-icon-5stars"></i>
356
- <a href="<?= $page_url ?>" title="Go rate us" target="_blank">
357
- <strong><?php _e( 'Go rate us and push ideas', 'wbcr_factory_clearfy_208' ); ?></strong>
358
- </a>
359
- </p>
360
- </div>
361
- <?php
362
- }
363
-
364
- public function showDonateWidget() {
365
- ?>
366
- <div class="wbcr-factory-sidebar-widget">
367
- <p>
368
- <strong><?php _e( 'Donation for plugin development', 'wbcr_factory_clearfy_208' ); ?></strong>
369
- </p>
370
- <?php if ( get_locale() !== 'ru_RU' ): ?>
371
- <form id="wbcr-factory-paypal-donation-form" action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
372
- <input type="hidden" name="cmd" value="_s-xclick">
373
- <input type="hidden" name="hosted_button_id" value="VDX7JNTQPNPFW">
374
- <div class="wbcr-factory-donation-price">5$</div>
375
- <input type="image" src="<?= FACTORY_PAGES_412_URL ?>/templates/assets/img/paypal-donate.png" border="0" name="submit" alt="PayPal – The safer, easier way to pay online!">
376
- </form>
377
- <?php else: ?>
378
- <iframe frameborder="0" allowtransparency="true" scrolling="no" src="https://money.yandex.ru/embed/donate.xml?account=410011242846510&quickpay=donate&payment-type-choice=on&mobile-payment-type-choice=on&default-sum=300&targets=%D0%9D%D0%B0+%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D1%83+%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%B0+%D0%B8+%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D1%83+%D0%BD%D0%BE%D0%B2%D1%8B%D1%85+%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9.+&target-visibility=on&project-name=Webcraftic&project-site=&button-text=05&comment=on&hint=%D0%9A%D0%B0%D0%BA%D1%83%D1%8E+%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8E+%D0%BD%D1%83%D0%B6%D0%BD%D0%BE+%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C+%D0%B2+%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%3F&mail=on&successURL=" width="508" height="187"></iframe>
379
- <?php endif; ?>
380
- </div>
381
- <?php
382
- }
383
- }
384
- }
385
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/factory/clearfy/pages/{class-clearfy-license.php → class-page-license.php} RENAMED
@@ -8,40 +8,68 @@ if ( ! defined( 'ABSPATH' ) ) {
8
  /**
9
  * Class Wbcr_FactoryLicense000_LicensePage is used as template to display form to active premium functionality.
10
  *
11
- * @since 2.0.7
 
12
  */
13
- class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase {
14
-
15
  /**
16
  * {@inheritdoc}
 
 
 
 
17
  */
18
  public $type = "page";
19
-
20
  /**
21
  * {@inheritdoc}
 
 
 
 
22
  */
23
  public $page_menu_dashicon = 'dashicons-admin-network';
24
-
25
  /**
26
  * {@inheritdoc}
 
 
 
 
27
  */
28
  public $show_right_sidebar_in_options = false;
29
-
30
  /**
31
  * {@inheritdoc}
 
 
 
 
32
  */
33
  public $page_menu_position = 0;
34
-
35
  /**
36
  * {@inheritdoc}
 
 
 
 
37
  */
38
  public $available_for_multisite = true;
39
-
 
 
 
 
 
 
 
40
  /**
41
  * @var string Name of the paid plan.
42
  */
43
  public $plan_name;
44
-
45
  // PREMIUM SECTION
46
  // ------------------------------------------------------------------
47
  /**
@@ -49,87 +77,90 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
49
  * @var bool
50
  */
51
  protected $is_premium;
52
-
53
  /**
54
  * @since 2.0.7
55
- * @var \WBCR\Factory_412\Premium\Provider
56
  */
57
  protected $premium;
58
-
59
  /**
60
  * @since 2.0.7
61
  * @var bool
62
  */
63
  protected $is_premium_active;
64
-
65
  /**
66
  * @since 2.0.7
67
  * @var bool
68
  */
69
  protected $premium_has_subscription;
70
-
71
  /**
72
  * @since 2.0.7
73
- * @var \WBCR\Factory_412\Premium\Interfaces\License
74
  */
75
  protected $premium_license;
76
-
77
  // END PREMIUM SECTION
78
  // ------------------------------------------------------------------
79
-
80
  /**
81
  * {@inheritdoc}
82
- * @param Wbcr_Factory412_Plugin $plugin
83
  */
84
- public function __construct( Wbcr_Factory412_Plugin $plugin ) {
85
  $this->plugin = $plugin;
86
-
87
  parent::__construct( $plugin );
88
-
89
  if ( ! $this->id ) {
90
  $this->id = $this->plugin->getPrefix() . 'license';
91
  }
92
- $this->premium = WRIO_Plugin::app()->premium;
 
 
93
  $this->is_premium = $this->premium->is_activate();
94
  $this->is_premium_active = $this->premium->is_active();
95
  $this->premium_has_subscription = $this->premium->has_paid_subscription();
96
  $this->premium_license = $this->premium->get_license();
97
-
98
- add_action( 'wp_ajax_wbcr-clearfy-activate-license', array( $this, 'ajax_handler' ) );
99
  }
100
-
101
  /**
102
  * [MAGIC] Magic method that configures assets for a page.
103
  */
104
  public function assets( $scripts, $styles ) {
105
  parent::assets( $scripts, $styles );
106
-
107
- $this->styles->add( FACTORY_CLEARFY_208_URL . '/assets/css/license-manager.css' );
108
- $this->scripts->add( FACTORY_CLEARFY_208_URL . '/assets/js/license-manager.js' );
109
  }
110
-
111
  /**
112
  * Регистрируем ajax обработчик для текущей страницы
 
113
  * @since 2.0.7
114
  */
115
  public function ajax_handler() {
116
- wbcr_factory_clearfy_208_check_license( $this->plugin );
117
  }
118
-
119
  /**
120
  * {@inheritdoc}
121
  */
122
  public function showPageContent() {
123
  ?>
124
- <?php wp_nonce_field( 'license' ); ?>
125
  <div id="wcl-license-wrapper"
126
- data-loader="<?php echo FACTORY_CLEARFY_208_URL . '/assets/img/loader.gif'; ?>"
127
- data-plugin="<?php echo get_class( $this->plugin ) ?>">
 
128
  <?php $this->show_license_form(); ?>
129
  </div>
130
  <?php
131
  }
132
-
133
  /**
134
  * Get before content.
135
  *
@@ -138,7 +169,7 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
138
  protected function get_plan_description() {
139
  return '';
140
  }
141
-
142
  /**
143
  * @return string
144
  */
@@ -146,10 +177,10 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
146
  if ( ! $this->is_premium ) {
147
  return '';
148
  }
149
-
150
  return $this->premium_license->get_hidden_key();
151
  }
152
-
153
  /**
154
  * @return string
155
  */
@@ -157,17 +188,17 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
157
  if ( ! $this->is_premium ) {
158
  return 'free';
159
  }
160
-
161
  return $this->premium->get_plan();
162
  }
163
-
164
  /**
165
  * @return mixed
166
  */
167
  protected function get_expiration_days() {
168
  return $this->premium_license->get_expiration_time( 'days' );
169
  }
170
-
171
  /**
172
  * @return string
173
  */
@@ -175,19 +206,19 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
175
  if ( ! $this->is_premium ) {
176
  return '';
177
  }
178
-
179
  $billing_cycle = $this->premium->get_billing_cycle();
180
  $billing = 'lifetime';
181
-
182
  if ( 1 == $billing_cycle ) {
183
  $billing = 'month';
184
  } else if ( 12 == $billing_cycle ) {
185
  $billing = 'year';
186
  }
187
-
188
  return $billing;
189
  }
190
-
191
  /**
192
  * Тип лицензии, цветовое оформление для формы лицензирования
193
  * free - бесплатная
@@ -201,34 +232,34 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
201
  if ( ! $this->is_premium ) {
202
  return 'free';
203
  }
204
-
205
  $license = $this->premium_license;
206
-
207
  if ( $license->is_lifetime() ) {
208
  return 'gift';
209
  } else if ( $license->get_expiration_time( 'days' ) < 1 ) {
210
  return 'trial';
211
  }
212
-
213
  return 'paid';
214
  }
215
-
216
  /**
217
  * @param bool|WP_Error $notice
218
  */
219
  public function show_license_form( $notice = false ) {
220
  ?>
221
- <div class="factory-bootstrap-412 onp-page-wrap <?= $this->get_license_type() ?>-license-manager-content"
222
- id="license-manager">
223
  <div>
224
- <h3><?php printf( __( 'Activate %s', 'wbcr_factory_clearfy_208' ), $this->plan_name ) ?></h3>
225
  <?php echo $this->get_plan_description() ?>
226
  </div>
227
  <br>
228
  <?php if ( is_wp_error( $notice ) ) : ?>
229
  <div class="license-message <?= $this->get_license_type() ?>-license-message">
230
  <div class="alert <?php echo esc_attr( $notice->get_error_code() ); ?>">
231
- <h4 class="alert-heading"><?php _e( $notice->get_error_message(), 'wbcr_factory_clearfy_208' ) ?></h4>
232
  </div>
233
  </div>
234
  <?php endif; ?>
@@ -238,25 +269,25 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
238
  <a href="<?php echo $this->plugin->get_support()->get_pricing_url( true, 'license_page' ); ?>"
239
  class="purchase-premium" target="_blank" rel="noopener">
240
  <span class="btn btn-gold btn-inner-wrap">
241
- <?php printf( __( 'Upgrade to Premium for $%s', 'wbcr_factory_clearfy_208' ), $this->premium->get_price() ) ?>
242
  </span>
243
  </a>
244
- <p><?php printf( __( 'Your current license for %1$s:', 'wbcr_factory_clearfy_208' ), $this->plugin->getPluginTitle() ) ?></p>
245
  <?php endif; ?>
246
  <div class="license-details-block <?= $this->get_license_type() ?>-details-block">
247
  <?php if ( $this->is_premium ): ?>
248
  <a data-action="deactivate" href="#"
249
  class="btn btn-default btn-small license-delete-button wcl-control-btn">
250
- <?php _e( 'Delete Key', 'wbcr_factory_clearfy_208' ) ?>
251
  </a>
252
  <a data-action="sync" href="#"
253
  class="btn btn-default btn-small license-synchronization-button wcl-control-btn">
254
- <?php _e( 'Synchronization', 'wbcr_factory_clearfy_208' ) ?>
255
  </a>
256
  <?php endif; ?>
257
  <h3>
258
  <?php echo ucfirst( $this->get_plan() ); ?>
259
-
260
  <?php if ( $this->is_premium && $this->premium_has_subscription ): ?>
261
  <span style="font-size: 15px;">
262
  (<?php printf( __( 'Automatic renewal, every %s', '' ), esc_attr( $this->get_billing_cycle_readable() ) ); ?>)
@@ -269,17 +300,17 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
269
  </div>
270
  <?php endif; ?>
271
  <div class="license-key-description">
272
- <p><?php _e( 'Public License is a GPLv2 compatible license allowing you to change and use this version of the plugin for free. Please keep in mind this license covers only free edition of the plugin. Premium versions are distributed with other type of a license.', 'wbcr_factory_clearfy_208' ) ?>
273
  </p>
274
  <?php if ( $this->is_premium && $this->premium_has_subscription ): ?>
275
  <p class="activate-trial-hint">
276
- <?php _e( 'You use a paid subscription for the plugin updates. In case you don’t want to receive paid updates, please, click <a data-action="unsubscribe" class="wcl-control-btn" href="#">cancel subscription</a>', 'wbcr_factory_clearfy_208' ) ?>
277
  </p>
278
  <?php endif; ?>
279
-
280
  <?php if ( $this->get_license_type() == 'trial' ): ?>
281
  <p class="activate-error-hint">
282
- <?php printf( __( 'Your license has expired, please extend the license to get updates and support.', 'wbcr_factory_clearfy_208' ), '' ) ?>
283
  </p>
284
  <?php endif; ?>
285
  </div>
@@ -287,19 +318,19 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
287
  <tr>
288
  <!--<td class="license-param license-param-domain">
289
  <span class="license-value"><?php echo esc_attr( $_SERVER['SERVER_NAME'] ); ?></span>
290
- <span class="license-value-name"><?php _e( 'domain', 'wbcr_factory_clearfy_208' ) ?></span>
291
  </td>-->
292
  <td class="license-param license-param-days">
293
  <span class="license-value"><?= $this->get_plan() ?></span>
294
- <span class="license-value-name"><?php _e( 'plan', 'wbcr_factory_clearfy_208' ) ?></span>
295
  </td>
296
  <?php if ( $this->is_premium ) : ?>
297
  <td class="license-param license-param-sites">
298
  <span class="license-value">
299
  <?php echo esc_attr( $this->premium_license->get_count_active_sites() ); ?>
300
- <?php _e( 'of', 'wbcr_factory_clearfy_208' ) ?>
301
  <?php echo esc_attr( $this->premium_license->get_sites_quota() ); ?></span>
302
- <span class="license-value-name"><?php _e( 'active sites', 'wbcr_factory_clearfy_208' ) ?></span>
303
  </td>
304
  <?php endif; ?>
305
  <td class="license-param license-param-version">
@@ -309,8 +340,8 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
309
  <?php if ( $this->is_premium ): ?>
310
  <td class="license-param license-param-days">
311
  <?php if ( $this->get_license_type() == 'trial' ): ?>
312
- <span class="license-value"><?php _e( 'EXPIRED!', 'wbcr_factory_clearfy_208' ) ?></span>
313
- <span class="license-value-name"><?php _e( 'please update the key', 'wbcr_factory_clearfy_208' ) ?></span>
314
  <?php else: ?>
315
  <span class="license-value">
316
  <?php
@@ -320,9 +351,9 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
320
  echo $this->get_expiration_days();
321
  }
322
  ?>
323
- <small> <?php _e( 'day(s)', 'wbcr_factory_clearfy_208' ) ?></small>
324
  </span>
325
- <span class="license-value-name"><?php _e( 'remained', 'wbcr_factory_clearfy_208' ) ?></span>
326
  <?php endif; ?>
327
  </td>
328
  <?php endif; ?>
@@ -333,25 +364,24 @@ class Wbcr_FactoryClearfy208_LicensePage extends Wbcr_FactoryClearfy208_PageBase
333
  <div class="license-input">
334
  <form action="" method="post">
335
  <?php if ( $this->is_premium ): ?>
336
- <p><?php _e( 'Have a key to activate the premium version? Paste it here:', 'wbcr_factory_clearfy_208' ) ?><p>
337
  <?php else: ?>
338
- <p><?php _e( 'Have a key to activate the plugin? Paste it here:', 'wbcr_factory_clearfy_208' ) ?>
339
  <p>
340
  <?php endif; ?>
341
- <button data-action="activate" class="btn btn-default wcl-control-btn" type="button"
342
- id="license-submit">
343
- <?php _e( 'Submit Key', 'wbcr_factory_clearfy_208' ) ?>
344
  </button>
345
  <div class="license-key-wrap">
346
  <input type="text" id="license-key" name="licensekey" value="" class="form-control"/>
347
  </div>
348
  <?php if ( $this->is_premium ): ?>
349
  <p style="margin-top: 10px;">
350
- <?php printf( __( '<a href="%s" target="_blank" rel="noopener">Lean more</a> about the premium version and get the license key to activate it now!', 'wbcr_factory_clearfy_208' ), $this->plugin->get_support()->get_pricing_url( true, 'license_page' ) ); ?>
351
  </p>
352
  <?php else: ?>
353
  <p style="margin-top: 10px;">
354
- <?php printf( __( 'Can’t find your key? Go to <a href="%s" target="_blank" rel="noopener">this page</a> and login using the e-mail address associated with your purchase.', 'wbcr_factory_clearfy_208' ), $this->plugin->get_support()->get_contacts_url( true, 'license_page' ) ) ?>
355
  </p>
356
  <?php endif; ?>
357
  </form>
8
  /**
9
  * Class Wbcr_FactoryLicense000_LicensePage is used as template to display form to active premium functionality.
10
  *
11
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
12
+ * @since 2.0.7
13
  */
14
+ class Wbcr_FactoryClearfy216_LicensePage extends Wbcr_FactoryClearfy216_PageBase {
15
+
16
  /**
17
  * {@inheritdoc}
18
+ *
19
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
20
+ * @since 2.1.2
21
+ * @var string
22
  */
23
  public $type = "page";
24
+
25
  /**
26
  * {@inheritdoc}
27
+ *
28
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
29
+ * @since 2.1.2
30
+ * @var string
31
  */
32
  public $page_menu_dashicon = 'dashicons-admin-network';
33
+
34
  /**
35
  * {@inheritdoc}
36
+ *
37
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
38
+ * @since 2.1.2
39
+ * @var bool
40
  */
41
  public $show_right_sidebar_in_options = false;
42
+
43
  /**
44
  * {@inheritdoc}
45
+ *
46
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
47
+ * @since 2.1.2
48
+ * @var int
49
  */
50
  public $page_menu_position = 0;
51
+
52
  /**
53
  * {@inheritdoc}
54
+ *
55
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
56
+ * @since 2.1.2
57
+ * @var bool
58
  */
59
  public $available_for_multisite = true;
60
+
61
+ /**
62
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
63
+ * @since 2.1.2
64
+ * @var string
65
+ */
66
+ public $plugin_name;
67
+
68
  /**
69
  * @var string Name of the paid plan.
70
  */
71
  public $plan_name;
72
+
73
  // PREMIUM SECTION
74
  // ------------------------------------------------------------------
75
  /**
77
  * @var bool
78
  */
79
  protected $is_premium;
80
+
81
  /**
82
  * @since 2.0.7
83
+ * @var \WBCR\Factory_424\Premium\Provider
84
  */
85
  protected $premium;
86
+
87
  /**
88
  * @since 2.0.7
89
  * @var bool
90
  */
91
  protected $is_premium_active;
92
+
93
  /**
94
  * @since 2.0.7
95
  * @var bool
96
  */
97
  protected $premium_has_subscription;
98
+
99
  /**
100
  * @since 2.0.7
101
+ * @var \WBCR\Factory_424\Premium\Interfaces\License
102
  */
103
  protected $premium_license;
104
+
105
  // END PREMIUM SECTION
106
  // ------------------------------------------------------------------
107
+
108
  /**
109
  * {@inheritdoc}
110
+ * @param Wbcr_Factory424_Plugin $plugin
111
  */
112
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
113
  $this->plugin = $plugin;
114
+
115
  parent::__construct( $plugin );
116
+
117
  if ( ! $this->id ) {
118
  $this->id = $this->plugin->getPrefix() . 'license';
119
  }
120
+
121
+ $this->plugin_name = $this->plugin->getPluginName();
122
+ $this->premium = $plugin->premium;
123
  $this->is_premium = $this->premium->is_activate();
124
  $this->is_premium_active = $this->premium->is_active();
125
  $this->premium_has_subscription = $this->premium->has_paid_subscription();
126
  $this->premium_license = $this->premium->get_license();
127
+
128
+ add_action( "wp_ajax_wbcr-clearfy-activate-license-for-{$this->plugin_name}", [ $this, 'ajax_handler' ] );
129
  }
130
+
131
  /**
132
  * [MAGIC] Magic method that configures assets for a page.
133
  */
134
  public function assets( $scripts, $styles ) {
135
  parent::assets( $scripts, $styles );
136
+
137
+ $this->styles->add( FACTORY_CLEARFY_216_URL . '/assets/css/license-manager.css' );
138
+ $this->scripts->add( FACTORY_CLEARFY_216_URL . '/assets/js/license-manager.js' );
139
  }
140
+
141
  /**
142
  * Регистрируем ajax обработчик для текущей страницы
143
+ *
144
  * @since 2.0.7
145
  */
146
  public function ajax_handler() {
147
+ wbcr_factory_clearfy_216_check_license( $this->plugin );
148
  }
149
+
150
  /**
151
  * {@inheritdoc}
152
  */
153
  public function showPageContent() {
154
  ?>
 
155
  <div id="wcl-license-wrapper"
156
+ data-loader="<?php echo FACTORY_CLEARFY_216_URL . '/assets/img/loader.gif'; ?>"
157
+ data-plugin-name="<?php echo esc_attr( $this->plugin_name ); ?>"
158
+ data-nonce="<?php echo wp_create_nonce( "clearfy_activate_license_for_{$this->plugin_name}" ) ?>">
159
  <?php $this->show_license_form(); ?>
160
  </div>
161
  <?php
162
  }
163
+
164
  /**
165
  * Get before content.
166
  *
169
  protected function get_plan_description() {
170
  return '';
171
  }
172
+
173
  /**
174
  * @return string
175
  */
177
  if ( ! $this->is_premium ) {
178
  return '';
179
  }
180
+
181
  return $this->premium_license->get_hidden_key();
182
  }
183
+
184
  /**
185
  * @return string
186
  */
188
  if ( ! $this->is_premium ) {
189
  return 'free';
190
  }
191
+
192
  return $this->premium->get_plan();
193
  }
194
+
195
  /**
196
  * @return mixed
197
  */
198
  protected function get_expiration_days() {
199
  return $this->premium_license->get_expiration_time( 'days' );
200
  }
201
+
202
  /**
203
  * @return string
204
  */
206
  if ( ! $this->is_premium ) {
207
  return '';
208
  }
209
+
210
  $billing_cycle = $this->premium->get_billing_cycle();
211
  $billing = 'lifetime';
212
+
213
  if ( 1 == $billing_cycle ) {
214
  $billing = 'month';
215
  } else if ( 12 == $billing_cycle ) {
216
  $billing = 'year';
217
  }
218
+
219
  return $billing;
220
  }
221
+
222
  /**
223
  * Тип лицензии, цветовое оформление для формы лицензирования
224
  * free - бесплатная
232
  if ( ! $this->is_premium ) {
233
  return 'free';
234
  }
235
+
236
  $license = $this->premium_license;
237
+
238
  if ( $license->is_lifetime() ) {
239
  return 'gift';
240
  } else if ( $license->get_expiration_time( 'days' ) < 1 ) {
241
  return 'trial';
242
  }
243
+
244
  return 'paid';
245
  }
246
+
247
  /**
248
  * @param bool|WP_Error $notice
249
  */
250
  public function show_license_form( $notice = false ) {
251
  ?>
252
+ <div id="license-manager"
253
+ class="factory-bootstrap-425 onp-page-wrap <?= $this->get_license_type() ?>-license-manager-content">
254
  <div>
255
+ <h3><?php printf( __( 'Activate %s', 'wbcr_factory_clearfy_216' ), $this->plan_name ) ?></h3>
256
  <?php echo $this->get_plan_description() ?>
257
  </div>
258
  <br>
259
  <?php if ( is_wp_error( $notice ) ) : ?>
260
  <div class="license-message <?= $this->get_license_type() ?>-license-message">
261
  <div class="alert <?php echo esc_attr( $notice->get_error_code() ); ?>">
262
+ <h4 class="alert-heading"><?php _e( $notice->get_error_message(), 'wbcr_factory_clearfy_216' ) ?></h4>
263
  </div>
264
  </div>
265
  <?php endif; ?>
269
  <a href="<?php echo $this->plugin->get_support()->get_pricing_url( true, 'license_page' ); ?>"
270
  class="purchase-premium" target="_blank" rel="noopener">
271
  <span class="btn btn-gold btn-inner-wrap">
272
+ <?php _e( 'Upgrade to Premium', 'wbcr_factory_clearfy_216' ) ?>
273
  </span>
274
  </a>
275
+ <p><?php printf( __( 'Your current license for %1$s:', 'wbcr_factory_clearfy_216' ), $this->plugin->getPluginTitle() ) ?></p>
276
  <?php endif; ?>
277
  <div class="license-details-block <?= $this->get_license_type() ?>-details-block">
278
  <?php if ( $this->is_premium ): ?>
279
  <a data-action="deactivate" href="#"
280
  class="btn btn-default btn-small license-delete-button wcl-control-btn">
281
+ <?php _e( 'Delete Key', 'wbcr_factory_clearfy_216' ) ?>
282
  </a>
283
  <a data-action="sync" href="#"
284
  class="btn btn-default btn-small license-synchronization-button wcl-control-btn">
285
+ <?php _e( 'Synchronization', 'wbcr_factory_clearfy_216' ) ?>
286
  </a>
287
  <?php endif; ?>
288
  <h3>
289
  <?php echo ucfirst( $this->get_plan() ); ?>
290
+
291
  <?php if ( $this->is_premium && $this->premium_has_subscription ): ?>
292
  <span style="font-size: 15px;">
293
  (<?php printf( __( 'Automatic renewal, every %s', '' ), esc_attr( $this->get_billing_cycle_readable() ) ); ?>)
300
  </div>
301
  <?php endif; ?>
302
  <div class="license-key-description">
303
+ <p><?php _e( 'Public License is a GPLv2 compatible license allowing you to change and use this version of the plugin for free. Please keep in mind this license covers only free edition of the plugin. Premium versions are distributed with other type of a license.', 'wbcr_factory_clearfy_216' ) ?>
304
  </p>
305
  <?php if ( $this->is_premium && $this->premium_has_subscription ): ?>
306
  <p class="activate-trial-hint">
307
+ <?php _e( 'You use a paid subscription for the plugin updates. In case you don’t want to receive paid updates, please, click <a data-action="unsubscribe" class="wcl-control-btn" href="#">cancel subscription</a>', 'wbcr_factory_clearfy_216' ) ?>
308
  </p>
309
  <?php endif; ?>
310
+
311
  <?php if ( $this->get_license_type() == 'trial' ): ?>
312
  <p class="activate-error-hint">
313
+ <?php printf( __( 'Your license has expired, please extend the license to get updates and support.', 'wbcr_factory_clearfy_216' ), '' ) ?>
314
  </p>
315
  <?php endif; ?>
316
  </div>
318
  <tr>
319
  <!--<td class="license-param license-param-domain">
320
  <span class="license-value"><?php echo esc_attr( $_SERVER['SERVER_NAME'] ); ?></span>
321
+ <span class="license-value-name"><?php _e( 'domain', 'wbcr_factory_clearfy_216' ) ?></span>
322
  </td>-->
323
  <td class="license-param license-param-days">
324
  <span class="license-value"><?= $this->get_plan() ?></span>
325
+ <span class="license-value-name"><?php _e( 'plan', 'wbcr_factory_clearfy_216' ) ?></span>
326
  </td>
327
  <?php if ( $this->is_premium ) : ?>
328
  <td class="license-param license-param-sites">
329
  <span class="license-value">
330
  <?php echo esc_attr( $this->premium_license->get_count_active_sites() ); ?>
331
+ <?php _e( 'of', 'wbcr_factory_clearfy_216' ) ?>
332
  <?php echo esc_attr( $this->premium_license->get_sites_quota() ); ?></span>
333
+ <span class="license-value-name"><?php _e( 'active sites', 'wbcr_factory_clearfy_216' ) ?></span>
334
  </td>
335
  <?php endif; ?>
336
  <td class="license-param license-param-version">
340
  <?php if ( $this->is_premium ): ?>
341
  <td class="license-param license-param-days">
342
  <?php if ( $this->get_license_type() == 'trial' ): ?>
343
+ <span class="license-value"><?php _e( 'EXPIRED!', 'wbcr_factory_clearfy_216' ) ?></span>
344
+ <span class="license-value-name"><?php _e( 'please update the key', 'wbcr_factory_clearfy_216' ) ?></span>
345
  <?php else: ?>
346
  <span class="license-value">
347
  <?php
351
  echo $this->get_expiration_days();
352
  }
353
  ?>
354
+ <small> <?php _e( 'day(s)', 'wbcr_factory_clearfy_216' ) ?></small>
355
  </span>
356
+ <span class="license-value-name"><?php _e( 'remained', 'wbcr_factory_clearfy_216' ) ?></span>
357
  <?php endif; ?>
358
  </td>
359
  <?php endif; ?>
364
  <div class="license-input">
365
  <form action="" method="post">
366
  <?php if ( $this->is_premium ): ?>
367
+ <p><?php _e( 'Have a key to activate the premium version? Paste it here:', 'wbcr_factory_clearfy_216' ) ?><p>
368
  <?php else: ?>
369
+ <p><?php _e( 'Have a key to activate the plugin? Paste it here:', 'wbcr_factory_clearfy_216' ) ?>
370
  <p>
371
  <?php endif; ?>
372
+ <button data-action="activate" class="btn btn-default wcl-control-btn" type="button" id="license-submit">
373
+ <?php _e( 'Submit Key', 'wbcr_factory_clearfy_216' ) ?>
 
374
  </button>
375
  <div class="license-key-wrap">
376
  <input type="text" id="license-key" name="licensekey" value="" class="form-control"/>
377
  </div>
378
  <?php if ( $this->is_premium ): ?>
379
  <p style="margin-top: 10px;">
380
+ <?php printf( __( '<a href="%s" target="_blank" rel="noopener">Lean more</a> about the premium version and get the license key to activate it now!', 'wbcr_factory_clearfy_216' ), $this->plugin->get_support()->get_pricing_url( true, 'license_page' ) ); ?>
381
  </p>
382
  <?php else: ?>
383
  <p style="margin-top: 10px;">
384
+ <?php printf( __( 'Can’t find your key? Go to <a href="%s" target="_blank" rel="noopener">this page</a> and login using the e-mail address associated with your purchase.', 'wbcr_factory_clearfy_216' ), $this->plugin->get_support()->get_contacts_url( true, 'license_page' ) ) ?>
385
  </p>
386
  <?php endif; ?>
387
  </form>
libs/factory/clearfy/pages/class-page-more-features.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The page Settings.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
6
+ * @since 1.0.1
7
+ * @package clearfy
8
+ * @copyright (c) 2018, Webcraftic Ltd
9
+ *
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+
18
+ class Wbcr_FactoryClearfy216_MoreFeaturesPage extends Wbcr_FactoryPages424_ImpressiveThemplate {
19
+
20
+ /**
21
+ * {@inheritDoc}
22
+ *
23
+ * @var string
24
+ */
25
+ public $id = "more_features";
26
+
27
+ /**
28
+ * {@inheritDoc}
29
+ *
30
+ * @var string
31
+ */
32
+ public $page_menu_dashicon = 'dashicons-star-filled wbcr-factory-orange-color';
33
+
34
+ /**
35
+ * {@inheritDoc}
36
+ *
37
+ * @var string
38
+ */
39
+ public $page_menu_position = 5;
40
+
41
+ /**
42
+ * {@inheritDoc}
43
+ *
44
+ * @var string
45
+ */
46
+ public $type = 'page';
47
+
48
+ /**
49
+ * {@inheritDoc}
50
+ *
51
+ * @var bool
52
+ */
53
+ public $available_for_multisite = true;
54
+
55
+ /**
56
+ * {@inheritDoc}
57
+ *
58
+ * @since 2.0.6 - добавлен
59
+ * @var bool
60
+ */
61
+ public $internal = true;
62
+
63
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
64
+ $this->menu_title = __( 'More features (<b>free</b>)', 'wbcr_factory_clearfy_216' );
65
+
66
+ parent::__construct( $plugin );
67
+
68
+ $this->plugin = $plugin;
69
+ }
70
+
71
+ /**
72
+ * {@inheritDoc}
73
+ *
74
+ * @return string
75
+ */
76
+ public function getPageTitle() {
77
+ return __( 'More features', 'wbcr_factory_clearfy_216' );
78
+ }
79
+
80
+ /**
81
+ * {@inheritDoc}
82
+ *
83
+ * @return void
84
+ */
85
+ public function showPageContent() {
86
+ ?>
87
+ <div class="row">
88
+ <div class="col-sm-4">
89
+ <div class="wbcr-factory-feature-box">
90
+ <span class="dashicons dashicons-yes"></span>
91
+ <h3><?php _e( 'Code cleaning', 'wbcr_factory_clearfy_216' ) ?></h3>
92
+ <p><?php _e( 'Clears the source code of the page from unused code.', 'wbcr_factory_clearfy_216' ) ?></p>
93
+ </div>
94
+ </div>
95
+ <div class="col-sm-4">
96
+ <div class="wbcr-factory-feature-box">
97
+ <span class="dashicons dashicons-chart-bar"></span>
98
+ <h3><?php _e( 'Improve SEO', 'wbcr_factory_clearfy_216' ) ?></h3>
99
+ <p><?php _e( 'Removes duplicate pages, closes external links, changes the headers of the server.', 'wbcr_factory_clearfy_216' ) ?></p>
100
+ </div>
101
+ </div>
102
+ <div class="col-sm-4">
103
+ <div class="wbcr-factory-feature-box">
104
+ <span class="dashicons dashicons-shield-alt"></span>
105
+ <h3><?php _e( 'Site protection', 'wbcr_factory_clearfy_216' ) ?></h3>
106
+ <p><?php _e( 'Enables and disables features that improve the protection of your site.', 'wbcr_factory_clearfy_216' ) ?></p>
107
+ </div>
108
+ </div>
109
+ <div class="col-sm-4">
110
+ <div class="wbcr-factory-feature-box">
111
+ <span class="dashicons dashicons-welcome-comments"></span>
112
+ <h3><?php _e( 'Disable comments', 'wbcr_factory_clearfy_216' ) ?></h3>
113
+ <p><?php _e( 'Disables comments on the entire site or on specific pages.', 'wbcr_factory_clearfy_216' ) ?></p>
114
+ </div>
115
+ </div>
116
+ <div class="col-sm-4">
117
+ <div class="wbcr-factory-feature-box">
118
+ <span class="dashicons dashicons-update"></span>
119
+ <h3><?php _e( 'Manage updates', 'wbcr_factory_clearfy_216' ) ?></h3>
120
+ <p><?php _e( 'Enables or disables automatically updates for plugins, themes and core. It is also possible
121
+ to disable all updates.', 'wbcr_factory_clearfy_216' ) ?></p>
122
+ </div>
123
+ </div>
124
+ <div class="col-sm-4">
125
+ <div class="wbcr-factory-feature-box">
126
+ <span class="dashicons dashicons-admin-plugins"></span>
127
+ <h3><?php _e( 'Manage widgets', 'wbcr_factory_clearfy_216' ) ?></h3>
128
+ <p><?php _e( 'Allows you to remove unused widgets.', 'wbcr_factory_clearfy_216' ) ?></p>
129
+ </div>
130
+ </div>
131
+ <div class="col-sm-4">
132
+ <div class="wbcr-factory-feature-box">
133
+ <span class="dashicons dashicons-dashboard"></span>
134
+ <h3><?php _e( 'Speed Optimization', 'wbcr_factory_clearfy_216' ) ?></h3>
135
+ <p><?php _e( 'Increases performance by disabling unused functions and reducing the number of requests.', 'wbcr_factory_clearfy_216' ) ?></p>
136
+ </div>
137
+ </div>
138
+ <div class="col-sm-4">
139
+ <div class="wbcr-factory-feature-box">
140
+ <span class="dashicons dashicons-visibility"></span>
141
+ <h3><?php _e( 'Site privacy', 'wbcr_factory_clearfy_216' ) ?></h3>
142
+ <p><?php _e( 'Allows you to hide the version of the site and plugins. Allows you to hide your
143
+ WordPress.', 'wbcr_factory_clearfy_216' ) ?></p>
144
+ </div>
145
+ </div>
146
+ <div class="col-sm-4">
147
+ <div class="wbcr-factory-feature-box">
148
+ <span class="dashicons dashicons-admin-settings"></span>
149
+ <h3><?php _e( 'Easy setup', 'wbcr_factory_clearfy_216' ) ?></h3>
150
+ <p><?php _e( 'In quick mode, you can easily configure the plugin according to your needs.', 'wbcr_factory_clearfy_216' ) ?></p>
151
+ </div>
152
+ </div>
153
+ </div>
154
+ <div class="wbcr-factory-buttons-wrap">
155
+ <?php
156
+ $url = 'https://clearfy.pro';
157
+
158
+ if ( get_locale() == 'ru_RU' ) {
159
+ $url = 'https://ru.clearfy.pro';
160
+ }
161
+ $url .= '?utm_source=wordpress.org&utm_campaign=' . $this->plugin->getPluginName();
162
+ ?>
163
+ <a href="<?= $url ?>" class="wbcr-factory-premium-button" target="_blank">
164
+ <?php _e( 'Get the ultimate plugin 100% FREE', 'wbcr_factory_clearfy_216' ) ?>
165
+ </a>
166
+ </div>
167
+ <?php
168
+ }
169
+ }
170
+
libs/factory/clearfy/pages/class-pages.php ADDED
@@ -0,0 +1,439 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Общий класс прослойка для страниц Clearfy и его компоннетов.
5
+ * В этом классе добавляются общие ресурсы и элементы, необходимые для всех связанных плагинов.
6
+ *
7
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
8
+ * @since 2.0.5
9
+ */
10
+
11
+ // Exit if accessed directly
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
15
+
16
+ /**
17
+ * Class Wbcr_FactoryPages424_ImpressiveThemplate
18
+ *
19
+ * @method string getInfoWidget() - get widget content information
20
+ * @method string getRatingWidget( array $args = [] ) - get widget content rating
21
+ * @method string getDonateWidget() - get widget content donate
22
+ * @method string getBusinessSuggetionWidget()
23
+ * @method string getSupportWidget
24
+ */
25
+ class Wbcr_FactoryClearfy216_PageBase extends Wbcr_FactoryPages424_ImpressiveThemplate {
26
+
27
+ /**
28
+ * {@inheritDoc}
29
+ *
30
+ * @since 2.0.5 - добавлен
31
+ * @var bool
32
+ */
33
+ public $show_right_sidebar_in_options = true;
34
+
35
+ /**
36
+ * {@inheritDoc}
37
+ *
38
+ * @since 2.0.5 - добавлен
39
+ * @var bool
40
+ */
41
+ public $available_for_multisite = true;
42
+
43
+ /**
44
+ * {@inheritDoc}
45
+ *
46
+ * @since 2.0.6 - добавлен
47
+ * @var bool
48
+ */
49
+ public $internal = true;
50
+
51
+ /**
52
+ * @param Wbcr_Factory424_Plugin $plugin
53
+ */
54
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
55
+ parent::__construct( $plugin );
56
+ }
57
+
58
+ /**
59
+ * @param $name
60
+ * @param $arguments
61
+ *
62
+ * @return null|string
63
+ */
64
+ public function __call( $name, $arguments ) {
65
+ if ( substr( $name, 0, 3 ) == 'get' ) {
66
+ $called_method_name = 'show' . substr( $name, 3 );
67
+ if ( method_exists( $this, $called_method_name ) ) {
68
+ ob_start();
69
+
70
+ $this->$called_method_name( $arguments );
71
+ $content = ob_get_contents();
72
+ ob_end_clean();
73
+
74
+ return $content;
75
+ }
76
+ }
77
+
78
+ return null;
79
+ }
80
+
81
+ /**
82
+ * Requests assets (js and css) for the page.
83
+ *
84
+ * @param Wbcr_Factory424_ScriptList $scripts
85
+ * @param Wbcr_Factory424_StyleList $styles
86
+ *
87
+ * @return void
88
+ * @see Wbcr_FactoryPages424_AdminPage
89
+ *
90
+ */
91
+ public function assets( $scripts, $styles ) {
92
+ parent::assets( $scripts, $styles );
93
+
94
+ $this->styles->add( FACTORY_CLEARFY_216_URL . '/assets/css/clearfy-base.css' );
95
+
96
+ // todo: вынести все общие скрипты и стили фреймворка, продумать совместимость с другими плагинами
97
+ if ( defined( 'WCL_PLUGIN_URL' ) ) {
98
+ $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
99
+ }
100
+
101
+ wbcr_factory_424_do_action_deprecated( 'wbcr_clearfy_page_enqueue_scripts', [
102
+ $this->getResultId(),
103
+ $scripts,
104
+ $styles
105
+ ], '1.4.0', 'wbcr/clearfy/page_assets' );
106
+
107
+ /**
108
+ * Allows you to enqueue scripts to the internal pages of the plugin.
109
+ * $this->getResultId() - page id + plugin name = quick_start-wbcr_clearfy
110
+ *
111
+ * @since 2.0.5
112
+ */
113
+ do_action( 'wbcr/clearfy/page_assets', $this->getResultId(), $scripts, $styles );
114
+ }
115
+
116
+ /**
117
+ * @return Wbcr_Factory424_Request
118
+ */
119
+ public function request() {
120
+ return $this->plugin->request;
121
+ }
122
+
123
+ /**
124
+ * @since 2.0.5
125
+ *
126
+ * @param $option_name
127
+ * @param bool $default *
128
+ *
129
+ * @return mixed|void
130
+ */
131
+ public function getPopulateOption( $option_name, $default = false ) {
132
+ return $this->plugin->getPopulateOption( $option_name, $default );
133
+ }
134
+
135
+ /**
136
+ * @param $option_name
137
+ * @param bool $default
138
+ *
139
+ * @return mixed|void
140
+ */
141
+ public function getOption( $option_name, $default = false ) {
142
+ return $this->plugin->getOption( $option_name, $default );
143
+ }
144
+
145
+ /**
146
+ * @param $option_name
147
+ * @param $value
148
+ *
149
+ * @return void
150
+ */
151
+ public function updatePopulateOption( $option_name, $value ) {
152
+ $this->plugin->updatePopulateOption( $option_name, $value );
153
+ }
154
+
155
+ /**
156
+ * @param $option_name
157
+ * @param $value
158
+ *
159
+ * @return void
160
+ */
161
+ public function updateOption( $option_name, $value ) {
162
+ $this->plugin->updateOption( $option_name, $value );
163
+ }
164
+
165
+ /**
166
+ * @param $option_name
167
+ *
168
+ * @return void
169
+ */
170
+ public function deletePopulateOption( $option_name ) {
171
+ $this->plugin->deletePopulateOption( $option_name );
172
+ }
173
+
174
+ /**
175
+ * @param $option_name
176
+ *
177
+ * @return void
178
+ */
179
+ public function deleteOption( $option_name ) {
180
+ $this->plugin->deleteOption( $option_name );
181
+ }
182
+
183
+
184
+ /**
185
+ * Действие выполняется для всех страниц Clearfy и его компонентах.
186
+ * Это простое предложение перейти на PRO версию.
187
+ */
188
+ public function multisiteProAction() {
189
+ if ( is_multisite() && $this->plugin->isNetworkActive() ) {
190
+
191
+ $license_page_url = $this->getBaseUrl( 'license' );
192
+ $upgrade_url = WbcrFactoryClearfy216_Helpers::getWebcrafticSitePageUrl( $this->plugin->getPluginName(), 'pricing', 'multisite_save_settings' );
193
+
194
+ $html = '<div class="wbcr-factory-clearfy-216-multisite-suggetion">';
195
+ $html .= '<div class="wbcr-factory-inner-contanier">';
196
+ $html .= '<h3>' . __( 'Upgrade to Clearfy Business', 'wbcr_factory_clearfy_216' ) . '</h3>';
197
+ $html .= '<p>' . __( 'Oops... Sorry for the inconvenience caused!', 'wbcr_factory_clearfy_216' ) . '</p>';
198
+ $html .= '<p>' . __( 'Complete multisite support is available in Clearfy Business and Clearfy Business Revolution packages only!', 'wbcr_factory_clearfy_216' ) . '</p>';
199
+ $html .= '<p>' . __( 'You can activate the plugin on each website and use it with zero limitations. But you can’t save the plugin’s settings under the Super Administrator role!', 'wbcr_factory_clearfy_216' ) . '</p>';
200
+ $html .= '<p style="margin-top:20px">';
201
+ $html .= '<a href="' . $license_page_url . '" class="wbcr-factory-activate-premium" rel="noopener">' . __( 'Activate license ', 'wbcr_factory_clearfy_216' ) . '</a> ';
202
+ $html .= '<a href="' . $upgrade_url . '" class="wbcr-factory-purchase-premium" target="_blank" rel="noopener">' . __( 'Upgrade to Clearfy Business', 'wbcr_factory_clearfy_216' ) . '</a>';
203
+ $html .= '</p>';
204
+ $html .= '</div>';
205
+ $html .= '</div>';
206
+
207
+ $this->showPage( $html );
208
+
209
+ return;
210
+ }
211
+
212
+ $this->redirectToAction( 'index' );
213
+ }
214
+
215
+ /**
216
+ * @param string $position
217
+ *
218
+ * @return mixed|void
219
+ */
220
+ protected function getPageWidgets( $position = 'bottom' ) {
221
+ $widgets = [];
222
+
223
+ if ( $position == 'bottom' ) {
224
+ $widgets['info_widget'] = $this->getInfoWidget();
225
+ $widgets['rating_widget'] = $this->getRatingWidget();
226
+ $widgets['support_widget'] = $this->getSupportWidget();
227
+ //$widgets['donate_widget'] = $this->getDonateWidget();
228
+ } else if ( $position == 'right' ) {
229
+ $widgets['business_suggetion'] = $this->getBusinessSuggetionWidget();
230
+ $widgets['info_widget'] = $this->getInfoWidget();
231
+ $widgets['rating_widget'] = $this->getRatingWidget();
232
+ }
233
+
234
+ /**
235
+ * @since 4.0.9 - является устаревшим
236
+ */
237
+ $widgets = wbcr_factory_424_apply_filters_deprecated( 'wbcr_factory_pages_424_imppage_get_widgets', [
238
+ $widgets,
239
+ $position,
240
+ $this->plugin,
241
+ $this
242
+ ], '4.0.9', 'wbcr/factory/pages/impressive/widgets' );
243
+
244
+ /**
245
+ * @since 4.0.1 - добавлен
246
+ * @since 4.0.9 - изменено имя
247
+ */
248
+ $widgets = apply_filters( 'wbcr/factory/pages/impressive/widgets', $widgets, $position, $this->plugin, $this );
249
+
250
+ return $widgets;
251
+ }
252
+
253
+ /**
254
+ * Создает Html разметку виджета для рекламы премиум версии
255
+ *
256
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
257
+ * @since 2.0.2
258
+ */
259
+ public function showBusinessSuggetionWidget() {
260
+ $plugin_name = $this->plugin->getPluginName();
261
+ $upgrade_price = $this->plugin->has_premium() ? $this->plugin->premium->get_price() : 0;
262
+ $purchase_url = $this->plugin->get_support()->get_pricing_url( true, 'right_sidebar_ads' );
263
+
264
+ $default_features = [
265
+ '4_premium' => __( '4 premium components now;', 'wbcr_factory_clearfy_216' ),
266
+ '40_premium' => __( '40 new premium components within a year for the single price;', 'wbcr_factory_clearfy_216' ),
267
+ 'multisite_support' => __( 'Multisite support;', 'wbcr_factory_clearfy_216' ),
268
+ 'advance_settings' => __( 'Advanced settings;', 'wbcr_factory_clearfy_216' ),
269
+ 'no_ads' => __( 'No ads;', 'wbcr_factory_clearfy_216' ),
270
+ 'perfect_support' => __( 'Perfect support.', 'wbcr_factory_clearfy_216' )
271
+ ];
272
+
273
+ /**
274
+ * @since 2.0.8 - added
275
+ */
276
+ $suggetion_title = __( 'MORE IN CLEARFY <span>BUSINESS</span>', 'wbcr_factory_clearfy_216' );
277
+ $suggetion_title = apply_filters( 'wbcr/clearfy/pages/suggetion_title', $suggetion_title, $plugin_name, $this->id );
278
+
279
+ /**
280
+ * @since 2.0.8 - deprecated
281
+ */
282
+ $suggetion_features = wbcr_factory_424_apply_filters_deprecated( 'wbcr/clearfy/page_bussines_suggetion_features', [
283
+ $default_features,
284
+ $this->plugin->getPluginName(),
285
+ $this->id
286
+ ], '2.0.8', 'wbcr/clearfy/pages/suggetion_features' );
287
+
288
+ /**
289
+ * @since 2.0.8 - renamed
290
+ * @since 2.0.6
291
+ */
292
+ $suggetion_features = apply_filters( 'wbcr/clearfy/pages/suggetion_features', $suggetion_features, $plugin_name, $this->id );
293
+
294
+ if ( empty( $suggetion_features ) ) {
295
+ $suggetion_features = $default_features;
296
+ }
297
+ ?>
298
+ <div class="wbcr-factory-sidebar-widget wbcr-factory-clearfy-216-pro-suggettion">
299
+ <h3><?php echo $suggetion_title; ?></h3>
300
+ <ul>
301
+ <?php if ( ! empty( $suggetion_features ) ): ?>
302
+ <?php foreach ( $suggetion_features as $feature ): ?>
303
+ <li><?= $feature ?></li>
304
+ <?php endforeach; ?>
305
+ <?php endif; ?>
306
+ </ul>
307
+ <a href="<?php echo $purchase_url ?>" class="wbcr-factory-purchase-premium" target="_blank" rel="noopener">
308
+ <?php printf( __( 'Upgrade for $%s', 'wbcr_factory_clearfy_216' ), $upgrade_price ) ?>
309
+ </a>
310
+ </div>
311
+ <?php
312
+ }
313
+
314
+ /**
315
+ * Создает html разметку виджета с информационными маркерами
316
+ *
317
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
318
+ * @since 2.0.0
319
+ */
320
+ public function showInfoWidget() {
321
+ ?>
322
+ <div class="wbcr-factory-sidebar-widget">
323
+ <ul>
324
+ <li>
325
+ <span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-red">
326
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt=""/>
327
+ </span>
328
+ - <?php _e( 'A neutral setting that can not harm your site, but you must be sure that you need to use it.', 'wbcr_factory_clearfy_216' ); ?>
329
+ </li>
330
+ <li>
331
+ <span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-grey">
332
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt=""/>
333
+ </span>
334
+ - <?php _e( 'When set this option, you must be careful. Plugins and themes may depend on this function. You must be sure that you can disable this feature for the site.', 'wbcr_factory_clearfy_216' ); ?>
335
+ </li>
336
+ <li>
337
+ <span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-green">
338
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt=""/>
339
+ </span>
340
+ - <?php _e( 'Absolutely safe setting, We recommend to use.', 'wbcr_factory_clearfy_216' ); ?>
341
+ </li>
342
+ </ul>
343
+ ----------<br>
344
+ <p><?php _e( 'Hover to the icon to get help for the feature you selected.', 'wbcr_factory_clearfy_216' ); ?></p>
345
+ </div>
346
+ <?php
347
+ }
348
+
349
+ /**
350
+ * Создает html разметку виджета рейтинга
351
+ *
352
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
353
+ * @since 2.0.0
354
+ *
355
+ * @param array $args
356
+ */
357
+ public function showRatingWidget( array $args ) {
358
+ if ( ! isset( $args[0] ) || empty( $args[0] ) ) {
359
+ $page_url = "https://goo.gl/tETE2X";
360
+ } else {
361
+ $page_url = $args[0];
362
+ }
363
+
364
+ $page_url = apply_filters( 'wbcr_factory_pages_424_imppage_rating_widget_url', $page_url, $this->plugin->getPluginName(), $this->getResultId() );
365
+
366
+ ?>
367
+ <div class="wbcr-factory-sidebar-widget">
368
+ <p>
369
+ <strong><?php _e( 'Do you want the plugin to improved and update?', 'wbcr_factory_clearfy_216' ); ?></strong>
370
+ </p>
371
+ <p><?php _e( 'Help the author, leave a review on wordpress.org. Thanks to feedback, I will know that the plugin is really useful to you and is needed.', 'wbcr_factory_clearfy_216' ); ?></p>
372
+ <p><?php _e( 'And also write your ideas on how to extend or improve the plugin.', 'wbcr_factory_clearfy_216' ); ?></p>
373
+ <p>
374
+ <i class="wbcr-factory-icon-5stars"></i>
375
+ <a href="<?= $page_url ?>" title="Go rate us" target="_blank">
376
+ <strong><?php _e( 'Go rate us and push ideas', 'wbcr_factory_clearfy_216' ); ?></strong>
377
+ </a>
378
+ </p>
379
+ </div>
380
+ <?php
381
+ }
382
+
383
+ /**
384
+ * Создает html размету виджета доната
385
+ *
386
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
387
+ * @since 2.0.0
388
+ */
389
+ public function showDonateWidget() {
390
+ ?>
391
+ <div class="wbcr-factory-sidebar-widget">
392
+ <p>
393
+ <strong><?php _e( 'Donation for plugin development', 'wbcr_factory_clearfy_216' ); ?></strong>
394
+ </p>
395
+ <?php if ( get_locale() !== 'ru_RU' ): ?>
396
+ <form id="wbcr-factory-paypal-donation-form" action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
397
+ <input type="hidden" name="cmd" value="_s-xclick">
398
+ <input type="hidden" name="hosted_button_id" value="VDX7JNTQPNPFW">
399
+ <div class="wbcr-factory-donation-price">5$</div>
400
+ <input type="image" src="<?= FACTORY_PAGES_424_URL ?>/templates/assets/img/paypal-donate.png" border="0" name="submit" alt="PayPal – The safer, easier way to pay online!">
401
+ </form>
402
+ <?php else: ?>
403
+ <iframe frameborder="0" allowtransparency="true" scrolling="no" src="https://money.yandex.ru/embed/donate.xml?account=410011242846510&quickpay=donate&payment-type-choice=on&mobile-payment-type-choice=on&default-sum=300&targets=%D0%9D%D0%B0+%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D1%83+%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%B0+%D0%B8+%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D1%83+%D0%BD%D0%BE%D0%B2%D1%8B%D1%85+%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9.+&target-visibility=on&project-name=Webcraftic&project-site=&button-text=05&comment=on&hint=%D0%9A%D0%B0%D0%BA%D1%83%D1%8E+%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8E+%D0%BD%D1%83%D0%B6%D0%BD%D0%BE+%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C+%D0%B2+%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%3F&mail=on&successURL=" width="508" height="187"></iframe>
404
+ <?php endif; ?>
405
+ </div>
406
+ <?php
407
+ }
408
+
409
+ /**
410
+ * Создает html разметку виджета поддержки
411
+ *
412
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
413
+ * @since 2.0.8
414
+ */
415
+ public function showSupportWidget() {
416
+ $free_support_url = $this->plugin->get_support()->get_contacts_url();
417
+ $hot_support_url = 'https://webcraftic.com/other-questions-support/';
418
+ ?>
419
+ <div id="wbcr-clr-support-widget" class="wbcr-factory-sidebar-widget">
420
+ <p><strong><?php _e( 'Having Issues?', 'clearfy' ); ?></strong></p>
421
+ <div class="wbcr-clr-support-widget-body">
422
+ <p>
423
+ <?php _e( 'We provide free support for this plugin. If you are pushed with a problem, just create a new ticket. We will definitely help you!', 'clearfy' ); ?>
424
+ </p>
425
+ <ul>
426
+ <li><span class="dashicons dashicons-sos"></span>
427
+ <a href="<?= $free_support_url ?>" target="_blank" rel="noopener"><?php _e( 'Get starting free support', 'clearfy' ); ?></a>
428
+ </li>
429
+ <li style="margin-top: 15px;background: #fff4f1;padding: 10px;color: #a58074;">
430
+ <span class="dashicons dashicons-warning"></span>
431
+ <?php printf( __( 'If you find a php error or a vulnerability in plugin, you can <a href="%s" target="_blank" rel="noopener">create ticket</a> in hot support that we responded instantly.', 'clearfy' ), $hot_support_url ); ?>
432
+ </li>
433
+ </ul>
434
+ </div>
435
+ </div>
436
+ <?php
437
+ }
438
+ }
439
+
libs/factory/core/README.md ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ # Core Factory Framework
2
+
3
+ It performs the connection of system modules of the framework, is responsible for migrations, plugin updates, admin notifications, initialization of the plugin.
libs/factory/core/boot.php CHANGED
@@ -2,11 +2,11 @@
2
  /**
3
  * Factory Plugin
4
  *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
 
 
6
  * @copyright (c) 2018, Webcraftic Ltd
7
  *
8
- * @package core
9
- * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
@@ -14,49 +14,49 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  exit;
15
  }
16
 
17
- if ( defined( 'FACTORY_412_LOADED' ) ) {
18
  return;
19
  }
20
 
21
- define( 'FACTORY_412_LOADED', true );
22
 
23
- define( 'FACTORY_412_VERSION', '4.1.1' );
24
 
25
- define( 'FACTORY_412_DIR', dirname( __FILE__ ) );
26
- define( 'FACTORY_412_URL', plugins_url( null, __FILE__ ) );
27
 
28
- load_plugin_textdomain( 'wbcr_factory_412', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
29
 
30
  #comp merge
31
- require_once( FACTORY_412_DIR . '/includes/functions.php' );
32
 
33
- require_once( FACTORY_412_DIR . '/includes/entities/class-factory-paths.php' );
34
- require_once( FACTORY_412_DIR . '/includes/entities/class-factory-support.php' );
35
 
36
- require_once( FACTORY_412_DIR . '/includes/class-factory-requests.php' );
37
- require_once( FACTORY_412_DIR . '/includes/class-factory-options.php' );
38
- require_once( FACTORY_412_DIR . '/includes/class-factory-plugin-base.php' );
39
- require_once( FACTORY_412_DIR . '/includes/class-factory-migrations.php' );
40
- require_once( FACTORY_412_DIR . '/includes/class-factory-notices.php' );
41
 
42
  // ASSETS
43
- require_once( FACTORY_412_DIR . '/includes/assets-managment/class-factory-assets-list.php' );
44
- require_once( FACTORY_412_DIR . '/includes/assets-managment/class-factory-script-list.php' );
45
- require_once( FACTORY_412_DIR . '/includes/assets-managment/class-factory-style-list.php' );
46
 
47
  // PREMIUM
48
- require_once( FACTORY_412_DIR . '/includes/premium/class-factory-license-interface.php' );
49
- require_once( FACTORY_412_DIR . '/includes/premium/class-factory-provider-abstract.php' );
50
- require_once( FACTORY_412_DIR . '/includes/premium/class-factory-manager.php' );
51
 
52
  // UPDATES
53
- require_once( FACTORY_412_DIR . '/includes/updates/repositories/class-factory-repository-abstract.php' );
54
- require_once( FACTORY_412_DIR . '/includes/updates/repositories/class-factory-wordpress.php' );
55
- require_once( FACTORY_412_DIR . '/includes/updates/class-factory-upgrader.php' );
56
- require_once( FACTORY_412_DIR . '/includes/updates/class-factory-premium-upgrader.php' );
57
 
58
- require_once( FACTORY_412_DIR . '/includes/class-factory-plugin-abstract.php' );
59
 
60
- require_once( FACTORY_412_DIR . '/includes/activation/class-factory-activator.php' );
61
- require_once( FACTORY_412_DIR . '/includes/activation/class-factory-update.php' );
62
  #endcomp
2
  /**
3
  * Factory Plugin
4
  *
5
+ * @author @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
6
+ * @since 1.0.0
7
+ * @package core
8
  * @copyright (c) 2018, Webcraftic Ltd
9
  *
 
 
10
  */
11
 
12
  // Exit if accessed directly
14
  exit;
15
  }
16
 
17
+ if ( defined( 'FACTORY_424_LOADED' ) ) {
18
  return;
19
  }
20
 
21
+ define( 'FACTORY_424_LOADED', true );
22
 
23
+ define( 'FACTORY_424_VERSION', '4.2.4' );
24
 
25
+ define( 'FACTORY_424_DIR', dirname( __FILE__ ) );
26
+ define( 'FACTORY_424_URL', plugins_url( null, __FILE__ ) );
27
 
28
+ load_plugin_textdomain( 'wbcr_factory_424', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
29
 
30
  #comp merge
31
+ require_once( FACTORY_424_DIR . '/includes/functions.php' );
32
 
33
+ require_once( FACTORY_424_DIR . '/includes/entities/class-factory-paths.php' );
34
+ require_once( FACTORY_424_DIR . '/includes/entities/class-factory-support.php' );
35
 
36
+ require_once( FACTORY_424_DIR . '/includes/class-factory-requests.php' );
37
+ require_once( FACTORY_424_DIR . '/includes/class-factory-options.php' );
38
+ require_once( FACTORY_424_DIR . '/includes/class-factory-plugin-base.php' );
39
+ require_once( FACTORY_424_DIR . '/includes/class-factory-migrations.php' );
40
+ require_once( FACTORY_424_DIR . '/includes/class-factory-notices.php' );
41
 
42
  // ASSETS
43
+ require_once( FACTORY_424_DIR . '/includes/assets-managment/class-factory-assets-list.php' );
44
+ require_once( FACTORY_424_DIR . '/includes/assets-managment/class-factory-script-list.php' );
45
+ require_once( FACTORY_424_DIR . '/includes/assets-managment/class-factory-style-list.php' );
46
 
47
  // PREMIUM
48
+ require_once( FACTORY_424_DIR . '/includes/premium/class-factory-license-interface.php' );
49
+ require_once( FACTORY_424_DIR . '/includes/premium/class-factory-provider-abstract.php' );
50
+ require_once( FACTORY_424_DIR . '/includes/premium/class-factory-manager.php' );
51
 
52
  // UPDATES
53
+ require_once( FACTORY_424_DIR . '/includes/updates/repositories/class-factory-repository-abstract.php' );
54
+ require_once( FACTORY_424_DIR . '/includes/updates/repositories/class-factory-wordpress.php' );
55
+ require_once( FACTORY_424_DIR . '/includes/updates/class-factory-upgrader.php' );
56
+ require_once( FACTORY_424_DIR . '/includes/updates/class-factory-premium-upgrader.php' );
57
 
58
+ require_once( FACTORY_424_DIR . '/includes/class-factory-plugin-abstract.php' );
59
 
60
+ require_once( FACTORY_424_DIR . '/includes/activation/class-factory-activator.php' );
61
+ require_once( FACTORY_424_DIR . '/includes/activation/class-factory-update.php' );
62
  #endcomp
libs/factory/core/includes/activation/class-factory-activator.php CHANGED
@@ -2,11 +2,11 @@
2
  /**
3
  * The file contains a base class for plugin activators.
4
  *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
- * @copyright (c) 2018, Webcraftic Ltd
7
  *
8
- * @package factory-core
9
- * @since 1.0.0
10
  */
11
  // Exit if accessed directly
12
  if ( ! defined( 'ABSPATH' ) ) {
@@ -19,24 +19,25 @@ if ( ! defined( 'ABSPATH' ) ) {
19
  *
20
  * @since 1.0.0
21
  */
22
- abstract class Wbcr_Factory412_Activator {
23
-
24
  /**
25
  * Curent plugin.
26
- * @var Wbcr_Factory412_Plugin
 
27
  */
28
  public $plugin;
29
-
30
- public function __construct( Wbcr_Factory412_Plugin $plugin ) {
31
  $this->plugin = $plugin;
32
  }
33
-
34
  public function activate() {
35
  }
36
-
37
  public function deactivate() {
38
  }
39
-
40
  public function update() {
41
  }
42
  }
2
  /**
3
  * The file contains a base class for plugin activators.
4
  *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
6
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
7
  *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
  */
11
  // Exit if accessed directly
12
  if ( ! defined( 'ABSPATH' ) ) {
19
  *
20
  * @since 1.0.0
21
  */
22
+ abstract class Wbcr_Factory424_Activator {
23
+
24
  /**
25
  * Curent plugin.
26
+ *
27
+ * @var Wbcr_Factory424_Plugin
28
  */
29
  public $plugin;
30
+
31
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
32
  $this->plugin = $plugin;
33
  }
34
+
35
  public function activate() {
36
  }
37
+
38
  public function deactivate() {
39
  }
40
+
41
  public function update() {
42
  }
43
  }
libs/factory/core/includes/activation/class-factory-update.php CHANGED
@@ -2,11 +2,11 @@
2
  /**
3
  * The file contains a base class for update items of plugins.
4
  *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
- * @copyright (c) 2018, Webcraftic Ltd
7
  *
8
- * @package factory-core
9
- * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
@@ -20,19 +20,20 @@ if ( ! defined( 'ABSPATH' ) ) {
20
  *
21
  * @since 1.0.0
22
  */
23
- abstract class Wbcr_Factory412_Update {
24
-
25
  /**
26
  * Current plugin
27
- * @var Wbcr_Factory412_Plugin
 
28
  */
29
  var $plugin;
30
-
31
- public function __construct( Wbcr_Factory412_Plugin $plugin ) {
32
  $this->plugin = $plugin;
33
  }
34
-
35
  abstract function install();
36
-
37
  //abstract function rollback();
38
  }
2
  /**
3
  * The file contains a base class for update items of plugins.
4
  *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
6
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
7
  *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
20
  *
21
  * @since 1.0.0
22
  */
23
+ abstract class Wbcr_Factory424_Update {
24
+
25
  /**
26
  * Current plugin
27
+ *
28
+ * @var Wbcr_Factory424_Plugin
29
  */
30
  var $plugin;
31
+
32
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
33
  $this->plugin = $plugin;
34
  }
35
+
36
  abstract function install();
37
+
38
  //abstract function rollback();
39
  }
libs/factory/core/includes/activation/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/core/includes/assets-managment/class-factory-assets-list.php CHANGED
@@ -2,11 +2,11 @@
2
  /**
3
  * The class contains a base class for all lists of assets.
4
  *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
- * @copyright (c) 2018, Webcraftic Ltd
7
  *
8
- * @package factory-core
9
- * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
@@ -19,27 +19,27 @@ if ( ! defined( 'ABSPATH' ) ) {
19
  *
20
  * @since 1.0.0
21
  */
22
- class Wbcr_Factory412_AssetsList {
23
-
24
- protected $all = array();
25
- public $header_place = array();
26
- public $footer_place = array();
27
- public $required = array();
28
-
29
  protected $default_place;
30
-
31
  /**
32
- * @var Wbcr_Factory412_Plugin
33
  */
34
  protected $plugin;
35
-
36
  /**
37
- * @param Wbcr_Factory412_Plugin $plugin
38
- * @param bool $defaultIsFooter
39
  */
40
- public function __construct( Wbcr_Factory412_Plugin $plugin, $defaultIsFooter = true ) {
41
  $this->plugin = $plugin;
42
-
43
  if ( $defaultIsFooter ) {
44
  $this->default_place = &$this->footer_place;
45
  }
@@ -47,23 +47,24 @@ class Wbcr_Factory412_AssetsList {
47
  $this->default_place = &$this->header_place;
48
  }
49
  }
50
-
51
  /**
52
  * Remove items from the collection
 
53
  * @return $this
54
  */
55
  public function deregister() {
56
  foreach ( func_get_args() as $item ) {
57
-
58
  if ( ! is_string( $item ) ) {
59
  return $this;
60
  }
61
-
62
  $key_in_all = array_search( $item, $this->all );
63
  $key_in_default_place = array_search( $item, $this->default_place );
64
  $key_in_header_place = array_search( $item, $this->header_place );
65
  $key_inFooterPlace = array_search( $item, $this->footer_place );
66
-
67
  if ( $key_in_all ) {
68
  unset( $this->all[ $key_in_all ] );
69
  }
@@ -77,14 +78,14 @@ class Wbcr_Factory412_AssetsList {
77
  unset( $this->footer_place[ $key_inFooterPlace ] );
78
  }
79
  }
80
-
81
  return $this;
82
  }
83
-
84
  /**
85
  * Checks whether the collection is empty.
86
  *
87
- * @param string $source if the 'bootstrap' specified, checks only whether the bootstrap assets were required.
88
  *
89
  * @return boolean
90
  */
@@ -92,25 +93,25 @@ class Wbcr_Factory412_AssetsList {
92
  if ( 'bootstrap' === $source ) {
93
  return empty( $this->required[ $source ] );
94
  }
95
-
96
  return empty( $this->all ) && empty( $this->required );
97
  }
98
-
99
  public function IsHeaderEmpty() {
100
  return empty( $this->header_place );
101
  }
102
-
103
  public function IsFooterEmpty() {
104
  return empty( $this->footer_place );
105
  }
106
-
107
  /**
108
  * Adds new items to the requried collection.
109
  *
110
  * @param mixed
111
  */
112
  public function request( $items, $source = 'wordpress' ) {
113
-
114
  if ( is_array( $items ) ) {
115
  foreach ( $items as $item ) {
116
  $this->required[ $source ][] = $item;
@@ -118,7 +119,7 @@ class Wbcr_Factory412_AssetsList {
118
  } else {
119
  $this->required[ $source ][] = $items;
120
  }
121
-
122
  return $this;
123
  }
124
  }
2
  /**
3
  * The class contains a base class for all lists of assets.
4
  *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
6
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
7
  *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
19
  *
20
  * @since 1.0.0
21
  */
22
+ class Wbcr_Factory424_AssetsList {
23
+
24
+ protected $all = [];
25
+ public $header_place = [];
26
+ public $footer_place = [];
27
+ public $required = [];
28
+
29
  protected $default_place;
30
+
31
  /**
32
+ * @var Wbcr_Factory424_Plugin
33
  */
34
  protected $plugin;
35
+
36
  /**
37
+ * @param Wbcr_Factory424_Plugin $plugin
38
+ * @param bool $defaultIsFooter
39
  */
40
+ public function __construct( Wbcr_Factory424_Plugin $plugin, $defaultIsFooter = true ) {
41
  $this->plugin = $plugin;
42
+
43
  if ( $defaultIsFooter ) {
44
  $this->default_place = &$this->footer_place;
45
  }
47
  $this->default_place = &$this->header_place;
48
  }
49
  }
50
+
51
  /**
52
  * Remove items from the collection
53
+ *
54
  * @return $this
55
  */
56
  public function deregister() {
57
  foreach ( func_get_args() as $item ) {
58
+
59
  if ( ! is_string( $item ) ) {
60
  return $this;
61
  }
62
+
63
  $key_in_all = array_search( $item, $this->all );
64
  $key_in_default_place = array_search( $item, $this->default_place );
65
  $key_in_header_place = array_search( $item, $this->header_place );
66
  $key_inFooterPlace = array_search( $item, $this->footer_place );
67
+
68
  if ( $key_in_all ) {
69
  unset( $this->all[ $key_in_all ] );
70
  }
78
  unset( $this->footer_place[ $key_inFooterPlace ] );
79
  }
80
  }
81
+
82
  return $this;
83
  }
84
+
85
  /**
86
  * Checks whether the collection is empty.
87
  *
88
+ * @param string $source if the 'bootstrap' specified, checks only whether the bootstrap assets were required.
89
  *
90
  * @return boolean
91
  */
93
  if ( 'bootstrap' === $source ) {
94
  return empty( $this->required[ $source ] );
95
  }
96
+
97
  return empty( $this->all ) && empty( $this->required );
98
  }
99
+
100
  public function IsHeaderEmpty() {
101
  return empty( $this->header_place );
102
  }
103
+
104
  public function IsFooterEmpty() {
105
  return empty( $this->footer_place );
106
  }
107
+
108
  /**
109
  * Adds new items to the requried collection.
110
  *
111
  * @param mixed
112
  */
113
  public function request( $items, $source = 'wordpress' ) {
114
+
115
  if ( is_array( $items ) ) {
116
  foreach ( $items as $item ) {
117
  $this->required[ $source ][] = $item;
119
  } else {
120
  $this->required[ $source ][] = $items;
121
  }
122
+
123
  return $this;
124
  }
125
  }
libs/factory/core/includes/assets-managment/class-factory-script-list.php CHANGED
@@ -2,11 +2,11 @@
2
  /**
3
  * The file contains a class to manage script assets.
4
  *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
- * @copyright (c) 2018, Webcraftic Ltd
7
  *
8
- * @package factory-core
9
- * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
@@ -20,11 +20,11 @@ if ( ! defined( 'ABSPATH' ) ) {
20
  *
21
  * @since 1.0.0
22
  */
23
- class Wbcr_Factory412_ScriptList extends Wbcr_Factory412_AssetsList {
24
-
25
- public $localize_data = array();
26
  public $use_ajax = false;
27
-
28
  /**
29
  * Adds new items to the collection (default place).
30
  *
@@ -32,20 +32,20 @@ class Wbcr_Factory412_ScriptList extends Wbcr_Factory412_AssetsList {
32
  *
33
  * @version 2.0
34
  */
35
- public function add( $file_url, $deps = array( 'jquery' ), $handle = null, $version = false, $place = 'default' ) {
36
-
37
  if ( empty( $file_url ) ) {
38
  return $this;
39
  }
40
-
41
- $resource = array();
42
  $resource['file_url'] = $file_url;
43
  $resource['deps'] = $deps;
44
  $resource['handle'] = $handle;
45
  $resource['version'] = $version;
46
-
47
  $this->all[] = $resource;
48
-
49
  switch ( $place ) {
50
  case 'header':
51
  $this->header_place[] = $resource;
@@ -57,84 +57,84 @@ class Wbcr_Factory412_ScriptList extends Wbcr_Factory412_AssetsList {
57
  $this->default_place[] = $resource;
58
  break;
59
  }
60
-
61
  return $this;
62
  }
63
-
64
  /**
65
  * Adds new items to the collection (header).
66
  *
67
  * @param mixed
68
  */
69
- public function addToHeader( $file_url, $deps = array( 'jquery' ), $handle = null ) {
70
  return $this->add( $file_url, $deps, $handle, 'header' );
71
  }
72
-
73
  /**
74
  * Adds new items to the collection (footer).
75
  *
76
  * @param mixed
77
  */
78
- public function addToFooter( $file_url, $deps = array( 'jquery' ), $handle = null ) {
79
  return $this->add( $file_url, $deps, $handle, 'footer' );
80
  }
81
-
82
  /**
83
  * Осуществляет подключение всех зарегистрированных скриптов
84
  *
85
  * @param string $source
86
  */
87
  public function connect( $source = 'wordpress' ) {
88
-
89
  // register all global required scripts
90
  if ( ! empty( $this->required[ $source ] ) ) {
91
  foreach ( $this->required[ $source ] as $script ) {
92
  if ( 'wordpress' === $source ) {
93
  wp_enqueue_script( $script );
94
- } elseif ( 'bootstrap' === $source ) {
95
  $this->plugin->bootstrap->enqueueScript( $script );
96
  }
97
  }
98
  }
99
-
100
  if ( $source == 'bootstrap' ) {
101
  return;
102
  }
103
-
104
  $is_first_script = true;
105
  $is_footer = false;
106
-
107
  // register all other scripts
108
- foreach ( array( $this->header_place, $this->footer_place ) as $script_place ) {
109
  foreach ( $script_place as $script ) {
110
-
111
  if ( empty( $script['file_url'] ) ) {
112
  continue;
113
  }
114
-
115
  $handle = ! empty( $script['handle'] ) ? $script['handle'] : $script['file_url'];
116
- $deps = ! is_array( $script['deps'] ) ? array() : $script['deps'];
117
  $version = ! empty( $script['version'] ) ? $script['version'] : $this->plugin->getPluginVersion();
118
-
119
  wp_register_script( $handle, $script['file_url'], $deps, $version, $is_footer );
120
-
121
  if ( $is_first_script && $this->use_ajax ) {
122
- wp_localize_script( $handle, 'factory', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
123
  }
124
-
125
  if ( ! empty( $this->localize_data[ $handle ] ) ) {
126
  wp_localize_script( $handle, $this->localize_data[ $handle ][0], $this->localize_data[ $handle ][1] );
127
  }
128
-
129
  wp_enqueue_script( $handle );
130
-
131
  $is_first_script = false;
132
  }
133
-
134
  $is_footer = true;
135
  }
136
  }
137
-
138
  /**
139
  * Если вызвать этот метод, на странице будет обязательно добавлена
140
  * глобальная JS переменная с ссылкой на ajax обработчик
@@ -142,24 +142,24 @@ class Wbcr_Factory412_ScriptList extends Wbcr_Factory412_AssetsList {
142
  public function useAjax() {
143
  $this->use_ajax = true;
144
  }
145
-
146
  /**
147
  * Регистрирует глобальную JS переменную с пользовательскими данными
148
  *
149
  * @param string $varname
150
  * @param string $data
151
  *
152
- * @return Wbcr_Factory412_ScriptList $this
153
  */
154
  public function localize( $varname, $data ) {
155
  $bindTo = count( $this->all ) == 0 ? null : end( $this->all );
156
-
157
  if ( ! $bindTo ) {
158
  return $this;
159
  }
160
-
161
- $this->localize_data[ $bindTo ] = array( $varname, $data );
162
-
163
  return $this;
164
  }
165
  }
2
  /**
3
  * The file contains a class to manage script assets.
4
  *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
6
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
7
  *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
20
  *
21
  * @since 1.0.0
22
  */
23
+ class Wbcr_Factory424_ScriptList extends Wbcr_Factory424_AssetsList {
24
+
25
+ public $localize_data = [];
26
  public $use_ajax = false;
27
+
28
  /**
29
  * Adds new items to the collection (default place).
30
  *
32
  *
33
  * @version 2.0
34
  */
35
+ public function add( $file_url, $deps = [ 'jquery' ], $handle = null, $version = false, $place = 'default' ) {
36
+
37
  if ( empty( $file_url ) ) {
38
  return $this;
39
  }
40
+
41
+ $resource = [];
42
  $resource['file_url'] = $file_url;
43
  $resource['deps'] = $deps;
44
  $resource['handle'] = $handle;
45
  $resource['version'] = $version;
46
+
47
  $this->all[] = $resource;
48
+
49
  switch ( $place ) {
50
  case 'header':
51
  $this->header_place[] = $resource;
57
  $this->default_place[] = $resource;
58
  break;
59
  }
60
+
61
  return $this;
62
  }
63
+
64
  /**
65
  * Adds new items to the collection (header).
66
  *
67
  * @param mixed
68
  */
69
+ public function addToHeader( $file_url, $deps = [ 'jquery' ], $handle = null ) {
70
  return $this->add( $file_url, $deps, $handle, 'header' );
71
  }
72
+
73
  /**
74
  * Adds new items to the collection (footer).
75
  *
76
  * @param mixed
77
  */
78
+ public function addToFooter( $file_url, $deps = [ 'jquery' ], $handle = null ) {
79
  return $this->add( $file_url, $deps, $handle, 'footer' );
80
  }
81
+
82
  /**
83
  * Осуществляет подключение всех зарегистрированных скриптов
84
  *
85
  * @param string $source
86
  */
87
  public function connect( $source = 'wordpress' ) {
88
+
89
  // register all global required scripts
90
  if ( ! empty( $this->required[ $source ] ) ) {
91
  foreach ( $this->required[ $source ] as $script ) {
92
  if ( 'wordpress' === $source ) {
93
  wp_enqueue_script( $script );
94
+ } else if ( 'bootstrap' === $source ) {
95
  $this->plugin->bootstrap->enqueueScript( $script );
96
  }
97
  }
98
  }
99
+
100
  if ( $source == 'bootstrap' ) {
101
  return;
102
  }
103
+
104
  $is_first_script = true;
105
  $is_footer = false;
106
+
107
  // register all other scripts
108
+ foreach ( [ $this->header_place, $this->footer_place ] as $script_place ) {
109
  foreach ( $script_place as $script ) {
110
+
111
  if ( empty( $script['file_url'] ) ) {
112
  continue;
113
  }
114
+
115
  $handle = ! empty( $script['handle'] ) ? $script['handle'] : $script['file_url'];
116
+ $deps = ! is_array( $script['deps'] ) ? [] : $script['deps'];
117
  $version = ! empty( $script['version'] ) ? $script['version'] : $this->plugin->getPluginVersion();
118
+
119
  wp_register_script( $handle, $script['file_url'], $deps, $version, $is_footer );
120
+
121
  if ( $is_first_script && $this->use_ajax ) {
122
+ wp_localize_script( $handle, 'factory', [ 'ajaxurl' => admin_url( 'admin-ajax.php' ) ] );
123
  }
124
+
125
  if ( ! empty( $this->localize_data[ $handle ] ) ) {
126
  wp_localize_script( $handle, $this->localize_data[ $handle ][0], $this->localize_data[ $handle ][1] );
127
  }
128
+
129
  wp_enqueue_script( $handle );
130
+
131
  $is_first_script = false;
132
  }
133
+
134
  $is_footer = true;
135
  }
136
  }
137
+
138
  /**
139
  * Если вызвать этот метод, на странице будет обязательно добавлена
140
  * глобальная JS переменная с ссылкой на ajax обработчик
142
  public function useAjax() {
143
  $this->use_ajax = true;
144
  }
145
+
146
  /**
147
  * Регистрирует глобальную JS переменную с пользовательскими данными
148
  *
149
  * @param string $varname
150
  * @param string $data
151
  *
152
+ * @return Wbcr_Factory424_ScriptList $this
153
  */
154
  public function localize( $varname, $data ) {
155
  $bindTo = count( $this->all ) == 0 ? null : end( $this->all );
156
+
157
  if ( ! $bindTo ) {
158
  return $this;
159
  }
160
+
161
+ $this->localize_data[ $bindTo ] = [ $varname, $data ];
162
+
163
  return $this;
164
  }
165
  }
libs/factory/core/includes/assets-managment/class-factory-style-list.php CHANGED
@@ -2,11 +2,11 @@
2
  /**
3
  * The file contains a class to manage style assets.
4
  *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
- * @copyright (c) 2018, Webcraftic Ltd
7
  *
8
- * @package factory-core
9
- * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
@@ -20,8 +20,8 @@ if ( ! defined( 'ABSPATH' ) ) {
20
  *
21
  * @since 1.0.0
22
  */
23
- class Wbcr_Factory412_StyleList extends Wbcr_Factory412_AssetsList {
24
-
25
  /**
26
  * Adds new items to the collection (default place).
27
  *
@@ -29,56 +29,56 @@ class Wbcr_Factory412_StyleList extends Wbcr_Factory412_AssetsList {
29
  *
30
  * @version 2.0
31
  */
32
- public function add( $file_url, $deps = array(), $handle = null, $version = false, $media = 'all' ) {
33
-
34
  if ( empty( $file_url ) ) {
35
  return $this;
36
  }
37
-
38
- $resource = array();
39
  $resource['file_url'] = $file_url;
40
  $resource['deps'] = $deps;
41
  $resource['handle'] = $handle;
42
  $resource['version'] = $version;
43
  $resource['media'] = $media;
44
-
45
  $this->all[] = $resource;
46
-
47
  return $this;
48
  }
49
-
50
  public function connect( $source = 'wordpress' ) {
51
  // register all global required scripts
52
  if ( ! empty( $this->required[ $source ] ) ) {
53
-
54
  foreach ( $this->required[ $source ] as $style ) {
55
  if ( 'wordpress' === $source ) {
56
  wp_enqueue_style( $style );
57
- } elseif ( 'bootstrap' === $source ) {
58
  $this->plugin->bootstrap->enqueueStyle( $style );
59
  }
60
  }
61
  }
62
-
63
  if ( $source == 'bootstrap' ) {
64
  return;
65
  }
66
-
67
  if ( empty( $this->all ) ) {
68
  return;
69
  }
70
-
71
  // register all other styles
72
  foreach ( $this->all as $style ) {
73
-
74
  if ( empty( $style['file_url'] ) ) {
75
  continue;
76
  }
77
-
78
  $handle = ! empty( $style['handle'] ) ? $style['handle'] : md5( $style['file_url'] );
79
- $deps = ! is_array( $style['deps'] ) ? array() : $style['deps'];
80
  $version = ! empty( $style['version'] ) ? $style['version'] : $this->plugin->getPluginVersion();
81
-
82
  wp_enqueue_style( $handle, $style['file_url'], $deps, $version );
83
  }
84
  }
2
  /**
3
  * The file contains a class to manage style assets.
4
  *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
6
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
7
  *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
20
  *
21
  * @since 1.0.0
22
  */
23
+ class Wbcr_Factory424_StyleList extends Wbcr_Factory424_AssetsList {
24
+
25
  /**
26
  * Adds new items to the collection (default place).
27
  *
29
  *
30
  * @version 2.0
31
  */
32
+ public function add( $file_url, $deps = [], $handle = null, $version = false, $media = 'all' ) {
33
+
34
  if ( empty( $file_url ) ) {
35
  return $this;
36
  }
37
+
38
+ $resource = [];
39
  $resource['file_url'] = $file_url;
40
  $resource['deps'] = $deps;
41
  $resource['handle'] = $handle;
42
  $resource['version'] = $version;
43
  $resource['media'] = $media;
44
+
45
  $this->all[] = $resource;
46
+
47
  return $this;
48
  }
49
+
50
  public function connect( $source = 'wordpress' ) {
51
  // register all global required scripts
52
  if ( ! empty( $this->required[ $source ] ) ) {
53
+
54
  foreach ( $this->required[ $source ] as $style ) {
55
  if ( 'wordpress' === $source ) {
56
  wp_enqueue_style( $style );
57
+ } else if ( 'bootstrap' === $source ) {
58
  $this->plugin->bootstrap->enqueueStyle( $style );
59
  }
60
  }
61
  }
62
+
63
  if ( $source == 'bootstrap' ) {
64
  return;
65
  }
66
+
67
  if ( empty( $this->all ) ) {
68
  return;
69
  }
70
+
71
  // register all other styles
72
  foreach ( $this->all as $style ) {
73
+
74
  if ( empty( $style['file_url'] ) ) {
75
  continue;
76
  }
77
+
78
  $handle = ! empty( $style['handle'] ) ? $style['handle'] : md5( $style['file_url'] );
79
+ $deps = ! is_array( $style['deps'] ) ? [] : $style['deps'];
80
  $version = ! empty( $style['version'] ) ? $style['version'] : $this->plugin->getPluginVersion();
81
+
82
  wp_enqueue_style( $handle, $style['file_url'], $deps, $version );
83
  }
84
  }
libs/factory/core/includes/assets-managment/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/core/includes/class-check-compatibility.php CHANGED
@@ -1,128 +1,122 @@
1
  <?php
2
 
3
- /**
4
- * Проверяет совместимость с плагинами Webcraftic, с версиями php, с версиями Wordpress
5
- *
6
- * @author Webcraftic <wordpress.webraftic@gmail.com>
7
- * @copyright (c) 26.09.2018, Webcraftic
8
- * @version 1.0.0
9
- * @since 4.0.8
10
- */
11
-
12
- if( !class_exists('Wbcr_Factory_Compatibility') ) {
13
- class Wbcr_Factory_Compatibility {
14
-
15
- protected $plugin_prefix;
16
- protected $plugin_class_prefix;
17
- protected $plugin_name;
18
- protected $plugin_title = "(no title)";
19
- protected $required_php_version = '5.3';
20
- protected $required_wp_version = '4.2.0';
21
-
22
- function __construct(array $plugin_info)
23
- {
24
- foreach((array)$plugin_info as $property => $value) {
25
- $this->$property = $value;
26
- }
27
-
28
- add_action('admin_init', array($this, 'registerNotices'));
29
  }
30
 
31
- /**
32
- * Метод проверяет совместимость плагина с php и wordpress версией
33
- *
34
- * @return bool
35
- */
36
- public function check()
37
- {
38
- if( !$this->isPhpCompatibility() ) {
39
- return false;
40
- }
41
-
42
- if( !$this->isWpCompatibility() ) {
43
- return false;
44
- }
45
 
46
- return true;
 
 
 
 
 
 
 
47
  }
48
 
49
- /**
50
- * Метод проверяет совместимость плагина с php версией сервера
51
- *
52
- * @return mixed
53
- */
54
- public function isPhpCompatibility()
55
- {
56
- return version_compare(PHP_VERSION, $this->required_php_version, '>=');
57
  }
58
 
59
- /**
60
- * Метод проверяет совместимость плагина с Wordpress версией сайта
61
- *
62
- * @return mixed
63
- */
64
- public function isWpCompatibility()
65
- {
66
- // Get the WP Version global.
67
- global $wp_version;
68
-
69
- return version_compare($wp_version, $this->required_wp_version, '>=');
70
- }
71
 
72
- /**
73
- * Метод возвращает текст уведомления
74
- *
75
- * @return string
76
- */
77
- public function getNoticeText()
78
- {
79
- $notice_text = $notice_default_text = '';
80
- $notice_default_text .= '<b>' . $this->plugin_title . ' ' . __('warning', '') . ':</b>' . '<br>';
81
 
82
- $notice_default_text .= sprintf(__('The %s plugin has stopped.', 'wbcr_factory_clearfy_208'), $this->plugin_title) . ' ';
83
- $notice_default_text .= __('Possible reasons:', '') . ' <br>';
 
 
 
 
 
 
84
 
85
- $has_one = false;
 
86
 
87
- if( !$this->isPhpCompatibility() ) {
88
- $has_one = true;
89
- $notice_text .= '- ' . sprintf(__('You need to update the PHP version to %s or higher!', 'wbcr_factory_412'), $this->required_php_version) . '<br>';
90
- }
 
 
 
 
91
 
92
- if( !$this->isWpCompatibility() ) {
93
- $has_one = true;
94
- $notice_text .= '- ' . sprintf(__('You need to update WordPress to %s or higher!', 'wbcr_factory_412'), $this->required_wp_version) . '<br>';
95
- }
96
 
97
- if( $has_one ) {
98
- $notice_text = $notice_default_text . $notice_text;
99
- }
100
 
101
- return $notice_text;
 
 
102
  }
103
 
104
- public function registerNotices()
105
- {
106
- if( current_user_can('activate_plugins') && current_user_can('edit_plugins') && current_user_can('install_plugins') ) {
107
- if( is_multisite() ) {
108
- add_action('network_admin_notices', array($this, 'showNotice'));
109
- }
110
 
111
- add_action('admin_notices', array($this, 'showNotice'));
112
- }
113
  }
114
 
115
- public function showNotice()
116
- {
117
- $notice_text = $this->getNoticeText();
118
 
119
- if( empty($notice_text) ) {
120
- return;
 
 
121
  }
122
 
123
- $notice_text = '<p>' . $this->getNoticeText() . '</p>';
 
 
 
 
 
124
 
125
- echo '<div class="notice notice-error">' . apply_filters('wbcr/factory/check_compatibility/notice_text', $notice_text, $this->plugin_name) . '</div>';
 
126
  }
 
 
 
 
127
  }
128
- }
 
1
  <?php
2
 
3
+ /**
4
+ * Проверяет совместимость с плагинами Webcraftic, с версиями php, с версиями Wordpress
5
+ *
6
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
7
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
8
+ *
9
+ * @version 1.0.0
10
+ * @since 4.0.8
11
+ */
12
+
13
+ if ( ! class_exists( 'Wbcr_Factory_Compatibility' ) ) {
14
+ class Wbcr_Factory_Compatibility {
15
+
16
+ protected $plugin_prefix;
17
+ protected $plugin_class_prefix;
18
+ protected $plugin_name;
19
+ protected $plugin_title = "(no title)";
20
+ protected $required_php_version = '5.3';
21
+ protected $required_wp_version = '4.2.0';
22
+
23
+ function __construct( array $plugin_info ) {
24
+ foreach ( (array) $plugin_info as $property => $value ) {
25
+ $this->$property = $value;
 
 
 
26
  }
27
 
28
+ add_action( 'admin_init', [ $this, 'registerNotices' ] );
29
+ }
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
+ /**
32
+ * Метод проверяет совместимость плагина с php и wordpress версией
33
+ *
34
+ * @return bool
35
+ */
36
+ public function check() {
37
+ if ( ! $this->isPhpCompatibility() ) {
38
+ return false;
39
  }
40
 
41
+ if ( ! $this->isWpCompatibility() ) {
42
+ return false;
 
 
 
 
 
 
43
  }
44
 
45
+ return true;
46
+ }
 
 
 
 
 
 
 
 
 
 
47
 
48
+ /**
49
+ * Метод проверяет совместимость плагина с php версией сервера
50
+ *
51
+ * @return mixed
52
+ */
53
+ public function isPhpCompatibility() {
54
+ return version_compare( PHP_VERSION, $this->required_php_version, '>=' );
55
+ }
 
56
 
57
+ /**
58
+ * Метод проверяет совместимость плагина с Wordpress версией сайта
59
+ *
60
+ * @return mixed
61
+ */
62
+ public function isWpCompatibility() {
63
+ // Get the WP Version global.
64
+ global $wp_version;
65
 
66
+ return version_compare( $wp_version, $this->required_wp_version, '>=' );
67
+ }
68
 
69
+ /**
70
+ * Метод возвращает текст уведомления
71
+ *
72
+ * @return string
73
+ */
74
+ public function getNoticeText() {
75
+ $notice_text = $notice_default_text = '';
76
+ $notice_default_text .= '<b>' . $this->plugin_title . ' ' . __( 'warning', '' ) . ':</b>' . '<br>';
77
 
78
+ $notice_default_text .= sprintf( __( 'The %s plugin has stopped.', 'wbcr_factory_clearfy_216' ), $this->plugin_title ) . ' ';
79
+ $notice_default_text .= __( 'Possible reasons:', '' ) . ' <br>';
 
 
80
 
81
+ $has_one = false;
 
 
82
 
83
+ if ( ! $this->isPhpCompatibility() ) {
84
+ $has_one = true;
85
+ $notice_text .= '- ' . sprintf( __( 'You need to update the PHP version to %s or higher!', 'wbcr_factory_424' ), $this->required_php_version ) . '<br>';
86
  }
87
 
88
+ if ( ! $this->isWpCompatibility() ) {
89
+ $has_one = true;
90
+ $notice_text .= '- ' . sprintf( __( 'You need to update WordPress to %s or higher!', 'wbcr_factory_424' ), $this->required_wp_version ) . '<br>';
91
+ }
 
 
92
 
93
+ if ( $has_one ) {
94
+ $notice_text = $notice_default_text . $notice_text;
95
  }
96
 
97
+ return $notice_text;
98
+ }
 
99
 
100
+ public function registerNotices() {
101
+ if ( current_user_can( 'activate_plugins' ) && current_user_can( 'edit_plugins' ) && current_user_can( 'install_plugins' ) ) {
102
+ if ( is_multisite() ) {
103
+ add_action( 'network_admin_notices', [ $this, 'showNotice' ] );
104
  }
105
 
106
+ add_action( 'admin_notices', [ $this, 'showNotice' ] );
107
+ }
108
+ }
109
+
110
+ public function showNotice() {
111
+ $notice_text = $this->getNoticeText();
112
 
113
+ if ( empty( $notice_text ) ) {
114
+ return;
115
  }
116
+
117
+ $notice_text = '<p>' . $this->getNoticeText() . '</p>';
118
+
119
+ echo '<div class="notice notice-error">' . apply_filters( 'wbcr/factory/check_compatibility/notice_text', $notice_text, $this->plugin_name ) . '</div>';
120
  }
121
+ }
122
+ }
libs/factory/core/includes/class-factory-migrations.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412;
4
 
5
  use Exception;
6
- use Wbcr_Factory412_Plugin;
7
 
8
  if ( ! defined( 'ABSPATH' ) ) {
9
  exit;
@@ -20,41 +20,56 @@ if ( ! defined( 'ABSPATH' ) ) {
20
  * for the plugin, if constant isn't set, then the previous version is taken from
21
  * the database.
22
  *
 
23
  *
24
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
25
- * @link https://webcraftic.com
26
- * @copyright (c) 2018 Webraftic Ltd
27
- * @since 4.1.1
 
28
  */
29
  class Migrations {
30
-
31
  protected $plugin;
32
-
33
  /**
34
  * Migrations constructor.
35
  *
36
- * @param Wbcr_Factory412_Plugin $plugin
37
  *
38
  * @throws Exception
39
  */
40
- public function __construct( Wbcr_Factory412_Plugin $plugin ) {
41
-
42
  $this->plugin = $plugin;
43
  $plugin_name = $plugin->getPluginName();
44
-
45
  if ( ! file_exists( $this->plugin->get_paths()->migrations ) ) {
46
  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.' );
47
  }
48
-
49
  if ( is_admin() ) {
50
- add_action( "admin_init", array( $this, "check_migrations" ) );
51
-
52
- add_action( "wbcr/factory/plugin_{$plugin_name}_activation", array( $this, 'activation_hook' ) );
53
- add_action( "wbcr_factory_notices_000_list", array( $this, "debug_bar_notice" ) );
54
- add_action( "wbcr_factory_notices_000_list", array( $this, "migration_error_notice" ) );
55
  }
56
  }
57
-
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  /**
59
  * Check if migration is necessary for plugin and if there are errors from previous migrations.
60
  * In debug mode, migrations are not performed automatically.
@@ -65,18 +80,18 @@ class Migrations {
65
  wp_redirect( remove_query_arg( 'wbcr_factory_fix_migration_error' ) );
66
  die();
67
  }
68
-
69
  if ( $this->is_debug() && isset( $_GET['wbcr_factory_test_migration'] ) ) {
70
  $this->make_migration();
71
  wp_redirect( remove_query_arg( 'wbcr_factory_test_migration' ) );
72
  die();
73
  }
74
-
75
  if ( $this->need_migration() && ! $this->is_debug() ) {
76
  $this->make_migration();
77
  }
78
  }
79
-
80
  /**
81
  * Notification displays the errors of outstanding migrations to fix errors
82
  * you need to follow the instructions in the notification and click
@@ -90,85 +105,105 @@ class Migrations {
90
  * and framework will intercept them safely for user and display them
91
  * in this notice.
92
  *
93
- * @param array $notices
 
94
  *
95
  * @return array
96
  */
97
- public function migration_error_notice( $notices ) {
98
-
 
 
 
 
99
  if ( ! $this->is_migration_error() || ! current_user_can( 'update_plugins' ) ) {
100
  return $notices;
101
  }
102
-
103
- $migration_error_text = $this->plugin->getPopulateOption( 'plugin_migration_error', '' );
 
 
 
 
 
104
  $fix_migration_error_url = add_query_arg( 'wbcr_factory_fix_migration_error', 1 );
105
-
106
  $notice_text = $migration_error_text;
107
- $notice_text .= "<br><br><a href='{$fix_migration_error_url}' class='button button-default'>" . __( 'I fixed, confirm migration', 'wbcr_factory_412' ) . "</a>";
108
-
109
- $notices[] = array(
110
  'id' => 'migration_debug_bar',
111
  'type' => 'error',
112
  'dismissible' => false,
113
  'dismiss_expires' => 0,
114
- 'text' => '<p><b>' . $this->plugin->getPluginTitle() . ' ' . __( 'migration error', 'wbcr_factory_412' ) . '</b><br>' . $notice_text . '</p>'
115
- );
116
-
117
  return $notices;
118
  }
119
-
120
  /**
121
  * Debug panel, display some information from the database. Also allows
122
  * perform manual migrations to test new migrations.
123
  *
124
- * @param $notices
 
125
  *
126
  * @return array
127
  */
128
- public function debug_bar_notice( $notices ) {
129
-
 
 
 
130
  if ( ! $this->is_debug() || ! current_user_can( 'update_plugins' ) ) {
131
  return $notices;
132
  }
133
-
134
  $migrate_url = add_query_arg( 'wbcr_factory_test_migration', 1 );
135
-
136
- $notice_text = __( "Plugin activated:", "wbcr_factory_412" ) . ' ' . date( "Y-m-d H:i:s", $this->plugin->getPopulateOption( 'plugin_activated', 0 ) ) . "<br>";
137
- $notice_text .= __( "Old plugin version (db):", "wbcr_factory_412" ) . ' ' . $this->plugin->getPopulateOption( 'plugin_version' ) . "<br>";
138
- $notice_text .= __( "Old plugin version (debug):", "wbcr_factory_412" ) . ' ' . $this->get_old_plugin_version() . "<br>";
139
- $notice_text .= __( "Current plugin version:", "wbcr_factory_412" ) . ' ' . $this->get_current_plugin_version() . "<br>";
140
- $notice_text .= __( "Need migration:", "wbcr_factory_412" ) . ' ' . ( $this->need_migration() ? "true" : "false" ) . "<br><br>";
141
- $notice_text .= "<a href='{$migrate_url}' class='button button-default'>" . __( "Migrate now", "wbcr_factory_412" ) . "</a><br>";
142
-
143
- $notices[] = array(
144
  'id' => 'migration_debug_bar',
145
  'type' => 'warning',
146
  'dismissible' => false,
147
  'dismiss_expires' => 0,
148
- 'text' => '<p><b style="color:red;">' . $this->plugin->getPluginTitle() . ' ' . __( 'migrations DEBUG bar', 'wbcr_factory_412' ) . '</b><br>' . $notice_text . '</p>'
149
- );
150
-
151
  return $notices;
152
  }
153
-
154
  /**
155
  * Runs when plugin is activated. Checks if you need to migrate
156
  * and if necessary it does it. Also adds a option when the plugin
157
  * was activated for the first time.
158
  */
159
  public function activation_hook() {
160
- if ( $this->need_migration() && ! $this->is_debug() ) {
161
  $this->make_migration();
162
- }
163
-
164
  // just time to know when the plugin was activated the first time
165
- $activated = $this->plugin->getPopulateOption( 'plugin_activated', 0 );
166
-
167
  if ( ! $activated ) {
168
- $this->plugin->updatePopulateOption( 'plugin_activated', time() );
 
 
 
 
 
 
169
  }
170
  }
171
-
172
  /**
173
  * Checks if debug mode of migrations from version x.x.x to x.x.y is enabled.
174
  *
@@ -177,44 +212,48 @@ class Migrations {
177
  protected function is_debug() {
178
  return defined( 'FACTORY_MIGRATIONS_DEBUG' ) && FACTORY_MIGRATIONS_DEBUG;
179
  }
180
-
181
  /**
182
  * Gets previous version of plugin that plugin had before updating to the new version.
183
  *
184
  * @return string|null
185
  */
186
  protected function get_old_plugin_version() {
187
-
188
  if ( $this->is_debug() && defined( 'FACTORY_MIGRATIONS_FORCE_OLD_VERSION' ) ) {
189
  return FACTORY_MIGRATIONS_FORCE_OLD_VERSION;
190
  }
191
-
192
- $plugin_version = $this->plugin->getPopulateOption( 'plugin_version', null );
193
-
 
 
 
 
194
  if ( ! empty( $plugin_version ) ) {
195
  return $plugin_version;
196
  }
197
-
198
  # TODO: Remove after few releases
199
  # This block for compatibility code with old version of framework < 4.1.1
200
  #-------------------------------------------
201
  if ( $this->plugin->isNetworkActive() ) {
202
- $plugin_versions = get_site_option( 'factory_plugin_versions', array() );
203
  } else {
204
- $plugin_versions = get_option( 'factory_plugin_versions', array() );
205
  }
206
-
207
  $plugin_version = isset( $plugin_versions[ $this->plugin->getPluginName() ] ) ? $plugin_versions[ $this->plugin->getPluginName() ] : null;
208
-
209
  if ( ! empty( $plugin_version ) ) {
210
- $plugin_version = str_replace( array( 'free-', 'premium-', 'offline-' ), '', $plugin_version );
211
  }
212
-
213
  #-------------------------------------------
214
-
215
  return $plugin_version;
216
  }
217
-
218
  /**
219
  * Gets the current version of plugin.
220
  *
@@ -223,7 +262,7 @@ class Migrations {
223
  protected function get_current_plugin_version() {
224
  return $this->plugin->getPluginVersion();
225
  }
226
-
227
  /**
228
  * Do I need migration for plugin? If previous migration was with a error, then
229
  * method will always return false to prevent looping.
@@ -234,28 +273,38 @@ class Migrations {
234
  if ( $this->is_migration_error() ) {
235
  return false;
236
  }
237
-
238
  return version_compare( $this->get_old_plugin_version(), $this->get_current_plugin_version(), '<' );
239
  }
240
-
241
  /**
242
  * Are there errors from previous migrations?
243
  *
244
  * @return bool
245
  */
246
  protected function is_migration_error() {
247
- $error = $this->plugin->getPopulateOption( 'plugin_migration_error', false );
248
-
 
 
 
 
249
  return $error !== false;
250
  }
251
-
252
  /**
253
  * Remove an option in database, thereby fix errors of the previous migration.
254
  */
255
  protected function fix_migration_error() {
256
- $this->plugin->deletePopulateOption( 'plugin_migration_error' );
 
 
 
 
 
 
257
  }
258
-
259
  /**
260
  * Migrates the plugin from version x.x.x to x.x.y. Automatically searches for files
261
  * migrations to the plugin's root directory and executes them. Default files
@@ -265,107 +314,114 @@ class Migrations {
265
  *
266
  */
267
  protected function make_migration() {
268
-
269
  if ( ! current_user_can( 'update_plugins' ) ) {
270
  return;
271
  }
272
-
273
  $old_plugin_version = $this->get_old_plugin_version();
274
  $new_plugin_version = $this->get_current_plugin_version();
275
-
276
  if ( empty( $old_plugin_version ) ) {
277
  $this->update_plugin_version_in_db();
278
  }
279
-
280
  // converts versions like 0.0.0 to 000000
281
  $old_number = $this->get_version_number( $old_plugin_version );
282
  $new_number = $this->get_version_number( $new_plugin_version );
283
-
284
  try {
285
-
286
  $update_files = $this->plugin->get_paths()->migrations;
287
  $files = $this->find_files( $update_files );
288
-
289
  if ( empty( $files ) ) {
290
  $this->update_plugin_version_in_db();
291
-
292
  return;
293
  }
294
-
295
  // finds updates that has intermediate version
296
  foreach ( (array) $files as $item ) {
297
  if ( ! preg_match( '/^\d+$/', $item['name'] ) ) {
298
  continue;
299
  }
300
-
301
  $item_number = intval( $item['name'] );
302
-
303
  if ( $item_number > $old_number && $item_number <= $new_number ) {
304
  $classes = $this->get_classes( $item['path'] );
305
-
306
  if ( count( $classes ) == 0 ) {
307
  continue;
308
  }
309
-
310
  foreach ( $classes as $path => $class_data ) {
311
  include_once( $path );
312
  $update_class = $class_data['name'];
313
-
314
  $update = new $update_class( $this->plugin );
315
  $update->install();
316
  }
317
  }
318
  }
319
-
320
  $this->update_plugin_version_in_db();
321
  } catch( Exception $e ) {
322
- $this->plugin->updatePopulateOption( 'plugin_migration_error', $e->getMessage() );
 
 
 
 
 
323
  }
324
  }
325
-
326
  /**
327
  * Updates version of plugin in database. So that we can track which
328
  * previous version of plugin was at the user, before he updated
329
  * plugin.
330
  */
331
  protected function update_plugin_version_in_db() {
332
-
333
  # TODO: Delete after few releases
334
  # This block for compatibility code with the old version of framework.
335
  # Cleans up old data, after the transition to new version of framework.
336
  #-------------------------------------------
337
  if ( $this->plugin->isNetworkActive() ) {
338
- $plugin_versions = get_site_option( 'factory_plugin_versions', array() );
339
  } else {
340
- $plugin_versions = get_option( 'factory_plugin_versions', array() );
341
  }
342
-
343
  if ( isset( $plugin_versions[ $this->plugin->getPluginName() ] ) ) {
344
  unset( $plugin_versions[ $this->plugin->getPluginName() ] );
345
  }
346
-
347
  if ( $this->plugin->isNetworkActive() ) {
348
  if ( empty( $plugin_versions ) ) {
349
  delete_site_option( 'factory_plugin_versions' );
350
  }
351
  update_site_option( 'factory_plugin_versions', $plugin_versions );
352
- } else {
353
- if ( empty( $plugin_versions ) ) {
354
- delete_option( 'factory_plugin_versions' );
355
- }
356
- update_option( 'factory_plugin_versions', $plugin_versions );
357
  }
358
- #-------------------------------------------
359
-
360
- $this->plugin->updatePopulateOption( 'plugin_version', $this->get_current_plugin_version() );
 
 
 
 
361
  }
362
-
363
  /**
364
  * Converts string representation of the version to the numeric.
365
  *
366
  * @since 1.0.0
367
  *
368
- * @param string $version A string version to convert.
369
  *
370
  * @return integer
371
  */
@@ -374,67 +430,67 @@ class Migrations {
374
  if ( count( $matches ) == 0 ) {
375
  return false;
376
  }
377
-
378
  $number = '';
379
  $number .= ( strlen( $matches[1] ) == 1 ) ? '0' . $matches[1] : $matches[1];
380
  $number .= ( strlen( $matches[2] ) == 1 ) ? '0' . $matches[2] : $matches[2];
381
  $number .= ( strlen( $matches[3] ) == 1 ) ? '0' . $matches[3] : $matches[3];
382
-
383
  return intval( $number );
384
  }
385
-
386
  /**
387
  * Returns a list of files at a given path.
388
  *
389
- * @param string $path path for search
390
  */
391
  private function find_files( $path ) {
392
  return $this->find_file_or_folders( $path, true );
393
  }
394
-
395
  /**
396
  * Returns a list of folders at a given path.
397
  *
398
- * @param string $path path for search
399
  */
400
  /*private function find_folders( $path ) {
401
  return $this->find_file_or_folders( $path, false );
402
  }*/
403
-
404
  /**
405
  * Returns a list of files or folders at a given path.
406
  *
407
- * @param string $path path for search
408
- * @param bool $files files or folders?
409
  */
410
  private function find_file_or_folders( $path, $areFiles = true ) {
411
  if ( ! is_dir( $path ) ) {
412
- return array();
413
  }
414
-
415
  $entries = scandir( $path );
416
  if ( empty( $entries ) ) {
417
- return array();
418
  }
419
-
420
- $files = array();
421
  foreach ( $entries as $entryName ) {
422
  if ( $entryName == '.' || $entryName == '..' ) {
423
  continue;
424
  }
425
-
426
  $filename = $path . '/' . $entryName;
427
  if ( ( $areFiles && is_file( $filename ) ) || ( ! $areFiles && is_dir( $filename ) ) ) {
428
- $files[] = array(
429
  'path' => str_replace( "\\", "/", $filename ),
430
  'name' => $areFiles ? str_replace( '.php', '', $entryName ) : $entryName
431
- );
432
  }
433
  }
434
-
435
  return $files;
436
  }
437
-
438
  /**
439
  * Gets php classes defined in a specified file.
440
  *
@@ -443,34 +499,34 @@ class Migrations {
443
  * @throws Exception
444
  */
445
  private function get_classes( $path ) {
446
-
447
  $phpCode = file_get_contents( $path );
448
-
449
- $classes = array();
450
-
451
  if ( ! function_exists( 'token_get_all' ) ) {
452
- throw new Exception( __( 'There is no PHP Tokenizer extension installed on your server, you cannot use the token_get_all function.', 'wbcr_factory_412' ) );
453
  }
454
-
455
  $tokens = token_get_all( $phpCode );
456
-
457
  $count = count( $tokens );
458
  for ( $i = 2; $i < $count; $i ++ ) {
459
  if ( is_array( $tokens ) && $tokens[ $i - 2 ][0] == T_CLASS && $tokens[ $i - 1 ][0] == T_WHITESPACE && $tokens[ $i ][0] == T_STRING ) {
460
-
461
  $extends = null;
462
  if ( $tokens[ $i + 2 ][0] == T_EXTENDS && $tokens[ $i + 4 ][0] == T_STRING ) {
463
  $extends = $tokens[ $i + 4 ][1];
464
  }
465
-
466
  $class_name = $tokens[ $i ][1];
467
- $classes[ $path ] = array(
468
  'name' => $class_name,
469
  'extends' => $extends
470
- );
471
  }
472
  }
473
-
474
  /**
475
  * result example:
476
  *
@@ -479,7 +535,7 @@ class Migrations {
479
  * 'extendes' => 'PluginNameItemBase'
480
  * )
481
  */
482
-
483
  return $classes;
484
  }
485
  }
1
  <?php
2
 
3
+ namespace WBCR\Factory_424;
4
 
5
  use Exception;
6
+ use Wbcr_Factory424_Plugin;
7
 
8
  if ( ! defined( 'ABSPATH' ) ) {
9
  exit;
20
  * for the plugin, if constant isn't set, then the previous version is taken from
21
  * the database.
22
  *
23
+ * todo: get_option and get_site_option are used because some caching plugins caching options, which causes problems
24
  *
25
+ *
26
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
27
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
28
+ *
29
+ * @since 4.1.1
30
  */
31
  class Migrations {
32
+
33
  protected $plugin;
34
+
35
  /**
36
  * Migrations constructor.
37
  *
38
+ * @param Wbcr_Factory424_Plugin $plugin
39
  *
40
  * @throws Exception
41
  */
42
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
43
+
44
  $this->plugin = $plugin;
45
  $plugin_name = $plugin->getPluginName();
46
+
47
  if ( ! file_exists( $this->plugin->get_paths()->migrations ) ) {
48
  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.' );
49
  }
50
+
51
  if ( is_admin() ) {
52
+ add_action( "admin_init", [ $this, "check_migrations" ] );
53
+
54
+ add_action( "wbcr/factory/plugin_{$plugin_name}_activated", [ $this, 'activation_hook' ] );
55
+ add_action( "wbcr/factory/admin_notices", [ $this, "debug_bar_notice" ], 10, 2 );
56
+ add_action( "wbcr/factory/admin_notices", [ $this, "migration_error_notice" ], 10, 2 );
57
  }
58
  }
59
+
60
+ /**
61
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
62
+ * @since 4.1.1
63
+ * @return mixed|void
64
+ */
65
+ public function get_plugin_activated_time() {
66
+ if ( $this->plugin->isNetworkActive() ) {
67
+ return get_site_option( $this->plugin->getOptionName( 'plugin_activated' ), 0 );
68
+ }
69
+
70
+ return get_option( $this->plugin->getOptionName( 'plugin_activated' ), 0 );
71
+ }
72
+
73
  /**
74
  * Check if migration is necessary for plugin and if there are errors from previous migrations.
75
  * In debug mode, migrations are not performed automatically.
80
  wp_redirect( remove_query_arg( 'wbcr_factory_fix_migration_error' ) );
81
  die();
82
  }
83
+
84
  if ( $this->is_debug() && isset( $_GET['wbcr_factory_test_migration'] ) ) {
85
  $this->make_migration();
86
  wp_redirect( remove_query_arg( 'wbcr_factory_test_migration' ) );
87
  die();
88
  }
89
+
90
  if ( $this->need_migration() && ! $this->is_debug() ) {
91
  $this->make_migration();
92
  }
93
  }
94
+
95
  /**
96
  * Notification displays the errors of outstanding migrations to fix errors
97
  * you need to follow the instructions in the notification and click
105
  * and framework will intercept them safely for user and display them
106
  * in this notice.
107
  *
108
+ * @param array $notices
109
+ * @param static $plugin_name
110
  *
111
  * @return array
112
  */
113
+ public function migration_error_notice( $notices, $plugin_name ) {
114
+
115
+ if ( $this->plugin->getPluginName() !== $plugin_name ) {
116
+ return $notices;
117
+ }
118
+
119
  if ( ! $this->is_migration_error() || ! current_user_can( 'update_plugins' ) ) {
120
  return $notices;
121
  }
122
+
123
+ if ( $this->plugin->isNetworkActive() ) {
124
+ $migration_error_text = get_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ), '' );
125
+ } else {
126
+ $migration_error_text = get_option( $this->plugin->getOptionName( 'plugin_migration_error' ), '' );
127
+ }
128
+
129
  $fix_migration_error_url = add_query_arg( 'wbcr_factory_fix_migration_error', 1 );
130
+
131
  $notice_text = $migration_error_text;
132
+ $notice_text .= "<br><br><a href='{$fix_migration_error_url}' class='button button-default'>" . __( 'I fixed, confirm migration', 'wbcr_factory_424' ) . "</a>";
133
+
134
+ $notices[] = [
135
  'id' => 'migration_debug_bar',
136
  'type' => 'error',
137
  'dismissible' => false,
138
  'dismiss_expires' => 0,
139
+ 'text' => '<p><b>' . $this->plugin->getPluginTitle() . ' ' . __( 'migration error', 'wbcr_factory_424' ) . '</b><br>' . $notice_text . '</p>'
140
+ ];
141
+
142
  return $notices;
143
  }
144
+
145
  /**
146
  * Debug panel, display some information from the database. Also allows
147
  * perform manual migrations to test new migrations.
148
  *
149
+ * @param array $notices
150
+ * @param string $plugin_name
151
  *
152
  * @return array
153
  */
154
+ public function debug_bar_notice( $notices, $plugin_name ) {
155
+
156
+ if ( $this->plugin->getPluginName() !== $plugin_name ) {
157
+ return $notices;
158
+ }
159
  if ( ! $this->is_debug() || ! current_user_can( 'update_plugins' ) ) {
160
  return $notices;
161
  }
162
+
163
  $migrate_url = add_query_arg( 'wbcr_factory_test_migration', 1 );
164
+
165
+ $notice_text = __( "Plugin activated:", "wbcr_factory_424" ) . ' ' . date( "Y-m-d H:i:s", $this->get_plugin_activated_time() ) . "<br>";
166
+
167
+ $notice_text .= __( "Old plugin version (debug):", "wbcr_factory_424" ) . ' ' . $this->get_old_plugin_version() . "<br>";
168
+ $notice_text .= __( "Current plugin version:", "wbcr_factory_424" ) . ' ' . $this->get_current_plugin_version() . "<br>";
169
+ $notice_text .= __( "Need migration:", "wbcr_factory_424" ) . ' ' . ( $this->need_migration() ? "true" : "false" ) . "<br><br>";
170
+ $notice_text .= "<a href='{$migrate_url}' class='button button-default'>" . __( "Migrate now", "wbcr_factory_424" ) . "</a><br>";
171
+
172
+ $notices[] = [
173
  'id' => 'migration_debug_bar',
174
  'type' => 'warning',
175
  'dismissible' => false,
176
  'dismiss_expires' => 0,
177
+ 'text' => '<p><b style="color:red;">' . $this->plugin->getPluginTitle() . ' ' . __( 'migrations DEBUG bar', 'wbcr_factory_424' ) . '</b><br>' . $notice_text . '</p>'
178
+ ];
179
+
180
  return $notices;
181
  }
182
+
183
  /**
184
  * Runs when plugin is activated. Checks if you need to migrate
185
  * and if necessary it does it. Also adds a option when the plugin
186
  * was activated for the first time.
187
  */
188
  public function activation_hook() {
189
+ /*if ( $this->need_migration() && ! $this->is_debug() ) {
190
  $this->make_migration();
191
+ }*/
192
+
193
  // just time to know when the plugin was activated the first time
194
+ $activated = $this->get_plugin_activated_time();
195
+
196
  if ( ! $activated ) {
197
+ if ( $this->plugin->isNetworkActive() ) {
198
+ update_site_option( $this->plugin->getOptionName( 'plugin_activated' ), time() );
199
+ update_site_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
200
+ } else {
201
+ update_option( $this->plugin->getOptionName( 'plugin_activated' ), time() );
202
+ update_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
203
+ }
204
  }
205
  }
206
+
207
  /**
208
  * Checks if debug mode of migrations from version x.x.x to x.x.y is enabled.
209
  *
212
  protected function is_debug() {
213
  return defined( 'FACTORY_MIGRATIONS_DEBUG' ) && FACTORY_MIGRATIONS_DEBUG;
214
  }
215
+
216
  /**
217
  * Gets previous version of plugin that plugin had before updating to the new version.
218
  *
219
  * @return string|null
220
  */
221
  protected function get_old_plugin_version() {
222
+
223
  if ( $this->is_debug() && defined( 'FACTORY_MIGRATIONS_FORCE_OLD_VERSION' ) ) {
224
  return FACTORY_MIGRATIONS_FORCE_OLD_VERSION;
225
  }
226
+
227
+ if ( $this->plugin->isNetworkActive() ) {
228
+ $plugin_version = get_site_option( $this->plugin->getOptionName( 'plugin_version' ), null );
229
+ } else {
230
+ $plugin_version = get_option( $this->plugin->getOptionName( 'plugin_version' ), null );
231
+ }
232
+
233
  if ( ! empty( $plugin_version ) ) {
234
  return $plugin_version;
235
  }
236
+
237
  # TODO: Remove after few releases
238
  # This block for compatibility code with old version of framework < 4.1.1
239
  #-------------------------------------------
240
  if ( $this->plugin->isNetworkActive() ) {
241
+ $plugin_versions = get_site_option( 'factory_plugin_versions', [] );
242
  } else {
243
+ $plugin_versions = get_option( 'factory_plugin_versions', [] );
244
  }
245
+
246
  $plugin_version = isset( $plugin_versions[ $this->plugin->getPluginName() ] ) ? $plugin_versions[ $this->plugin->getPluginName() ] : null;
247
+
248
  if ( ! empty( $plugin_version ) ) {
249
+ $plugin_version = str_replace( [ 'free-', 'premium-', 'offline-' ], '', $plugin_version );
250
  }
251
+
252
  #-------------------------------------------
253
+
254
  return $plugin_version;
255
  }
256
+
257
  /**
258
  * Gets the current version of plugin.
259
  *
262
  protected function get_current_plugin_version() {
263
  return $this->plugin->getPluginVersion();
264
  }
265
+
266
  /**
267
  * Do I need migration for plugin? If previous migration was with a error, then
268
  * method will always return false to prevent looping.
273
  if ( $this->is_migration_error() ) {
274
  return false;
275
  }
276
+
277
  return version_compare( $this->get_old_plugin_version(), $this->get_current_plugin_version(), '<' );
278
  }
279
+
280
  /**
281
  * Are there errors from previous migrations?
282
  *
283
  * @return bool
284
  */
285
  protected function is_migration_error() {
286
+ if ( $this->plugin->isNetworkActive() ) {
287
+ $error = get_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ), false );
288
+ } else {
289
+ $error = get_option( $this->plugin->getOptionName( 'plugin_migration_error' ), false );
290
+ }
291
+
292
  return $error !== false;
293
  }
294
+
295
  /**
296
  * Remove an option in database, thereby fix errors of the previous migration.
297
  */
298
  protected function fix_migration_error() {
299
+ if ( $this->plugin->isNetworkActive() ) {
300
+ delete_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ) );
301
+
302
+ return;
303
+ }
304
+
305
+ delete_option( $this->plugin->getOptionName( 'plugin_migration_error' ) );
306
  }
307
+
308
  /**
309
  * Migrates the plugin from version x.x.x to x.x.y. Automatically searches for files
310
  * migrations to the plugin's root directory and executes them. Default files
314
  *
315
  */
316
  protected function make_migration() {
317
+
318
  if ( ! current_user_can( 'update_plugins' ) ) {
319
  return;
320
  }
321
+
322
  $old_plugin_version = $this->get_old_plugin_version();
323
  $new_plugin_version = $this->get_current_plugin_version();
324
+
325
  if ( empty( $old_plugin_version ) ) {
326
  $this->update_plugin_version_in_db();
327
  }
328
+
329
  // converts versions like 0.0.0 to 000000
330
  $old_number = $this->get_version_number( $old_plugin_version );
331
  $new_number = $this->get_version_number( $new_plugin_version );
332
+
333
  try {
334
+
335
  $update_files = $this->plugin->get_paths()->migrations;
336
  $files = $this->find_files( $update_files );
337
+
338
  if ( empty( $files ) ) {
339
  $this->update_plugin_version_in_db();
340
+
341
  return;
342
  }
343
+
344
  // finds updates that has intermediate version
345
  foreach ( (array) $files as $item ) {
346
  if ( ! preg_match( '/^\d+$/', $item['name'] ) ) {
347
  continue;
348
  }
349
+
350
  $item_number = intval( $item['name'] );
351
+
352
  if ( $item_number > $old_number && $item_number <= $new_number ) {
353
  $classes = $this->get_classes( $item['path'] );
354
+
355
  if ( count( $classes ) == 0 ) {
356
  continue;
357
  }
358
+
359
  foreach ( $classes as $path => $class_data ) {
360
  include_once( $path );
361
  $update_class = $class_data['name'];
362
+
363
  $update = new $update_class( $this->plugin );
364
  $update->install();
365
  }
366
  }
367
  }
368
+
369
  $this->update_plugin_version_in_db();
370
  } catch( Exception $e ) {
371
+ if ( $this->plugin->isNetworkActive() ) {
372
+ update_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ), $e->getMessage() );
373
+
374
+ return;
375
+ }
376
+ update_option( $this->plugin->getOptionName( 'plugin_migration_error' ), $e->getMessage() );
377
  }
378
  }
379
+
380
  /**
381
  * Updates version of plugin in database. So that we can track which
382
  * previous version of plugin was at the user, before he updated
383
  * plugin.
384
  */
385
  protected function update_plugin_version_in_db() {
386
+
387
  # TODO: Delete after few releases
388
  # This block for compatibility code with the old version of framework.
389
  # Cleans up old data, after the transition to new version of framework.
390
  #-------------------------------------------
391
  if ( $this->plugin->isNetworkActive() ) {
392
+ $plugin_versions = get_site_option( 'factory_plugin_versions', [] );
393
  } else {
394
+ $plugin_versions = get_option( 'factory_plugin_versions', [] );
395
  }
396
+
397
  if ( isset( $plugin_versions[ $this->plugin->getPluginName() ] ) ) {
398
  unset( $plugin_versions[ $this->plugin->getPluginName() ] );
399
  }
400
+
401
  if ( $this->plugin->isNetworkActive() ) {
402
  if ( empty( $plugin_versions ) ) {
403
  delete_site_option( 'factory_plugin_versions' );
404
  }
405
  update_site_option( 'factory_plugin_versions', $plugin_versions );
406
+ update_site_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
407
+
408
+ return;
 
 
409
  }
410
+
411
+ if ( empty( $plugin_versions ) ) {
412
+ delete_option( 'factory_plugin_versions' );
413
+ }
414
+
415
+ update_option( 'factory_plugin_versions', $plugin_versions );
416
+ update_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
417
  }
418
+
419
  /**
420
  * Converts string representation of the version to the numeric.
421
  *
422
  * @since 1.0.0
423
  *
424
+ * @param string $version A string version to convert.
425
  *
426
  * @return integer
427
  */
430
  if ( count( $matches ) == 0 ) {
431
  return false;
432
  }
433
+
434
  $number = '';
435
  $number .= ( strlen( $matches[1] ) == 1 ) ? '0' . $matches[1] : $matches[1];
436
  $number .= ( strlen( $matches[2] ) == 1 ) ? '0' . $matches[2] : $matches[2];
437
  $number .= ( strlen( $matches[3] ) == 1 ) ? '0' . $matches[3] : $matches[3];
438
+
439
  return intval( $number );
440
  }
441
+
442
  /**
443
  * Returns a list of files at a given path.
444
  *
445
+ * @param string $path path for search
446
  */
447
  private function find_files( $path ) {
448
  return $this->find_file_or_folders( $path, true );
449
  }
450
+
451
  /**
452
  * Returns a list of folders at a given path.
453
  *
454
+ * @param string $path path for search
455
  */
456
  /*private function find_folders( $path ) {
457
  return $this->find_file_or_folders( $path, false );
458
  }*/
459
+
460
  /**
461
  * Returns a list of files or folders at a given path.
462
  *
463
+ * @param string $path path for search
464
+ * @param bool $files files or folders?
465
  */
466
  private function find_file_or_folders( $path, $areFiles = true ) {
467
  if ( ! is_dir( $path ) ) {
468
+ return [];
469
  }
470
+
471
  $entries = scandir( $path );
472
  if ( empty( $entries ) ) {
473
+ return [];
474
  }
475
+
476
+ $files = [];
477
  foreach ( $entries as $entryName ) {
478
  if ( $entryName == '.' || $entryName == '..' ) {
479
  continue;
480
  }
481
+
482
  $filename = $path . '/' . $entryName;
483
  if ( ( $areFiles && is_file( $filename ) ) || ( ! $areFiles && is_dir( $filename ) ) ) {
484
+ $files[] = [
485
  'path' => str_replace( "\\", "/", $filename ),
486
  'name' => $areFiles ? str_replace( '.php', '', $entryName ) : $entryName
487
+ ];
488
  }
489
  }
490
+
491
  return $files;
492
  }
493
+
494
  /**
495
  * Gets php classes defined in a specified file.
496
  *
499
  * @throws Exception
500
  */
501
  private function get_classes( $path ) {
502
+
503
  $phpCode = file_get_contents( $path );
504
+
505
+ $classes = [];
506
+
507
  if ( ! function_exists( 'token_get_all' ) ) {
508
+ throw new Exception( __( 'There is no PHP Tokenizer extension installed on your server, you cannot use the token_get_all function.', 'wbcr_factory_424' ) );
509
  }
510
+
511
  $tokens = token_get_all( $phpCode );
512
+
513
  $count = count( $tokens );
514
  for ( $i = 2; $i < $count; $i ++ ) {
515
  if ( is_array( $tokens ) && $tokens[ $i - 2 ][0] == T_CLASS && $tokens[ $i - 1 ][0] == T_WHITESPACE && $tokens[ $i ][0] == T_STRING ) {
516
+
517
  $extends = null;
518
  if ( $tokens[ $i + 2 ][0] == T_EXTENDS && $tokens[ $i + 4 ][0] == T_STRING ) {
519
  $extends = $tokens[ $i + 4 ][1];
520
  }
521
+
522
  $class_name = $tokens[ $i ][1];
523
+ $classes[ $path ] = [
524
  'name' => $class_name,
525
  'extends' => $extends
526
+ ];
527
  }
528
  }
529
+
530
  /**
531
  * result example:
532
  *
535
  * 'extendes' => 'PluginNameItemBase'
536
  * )
537
  */
538
+
539
  return $classes;
540
  }
541
  }
libs/factory/core/includes/class-factory-notices.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412;
4
 
5
- use Wbcr_Factory412_Plugin;
6
 
7
  // Exit if accessed directly
8
  if ( ! defined( 'ABSPATH' ) ) {
@@ -18,28 +18,27 @@ if ( ! defined( 'ABSPATH' ) ) {
18
  /**
19
  * A group of classes and methods to create and manage notices.
20
  *
21
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
22
- * @link https://webcraftic.com
23
- * @copyright (c) 2018 Webraftic Ltd
24
  *
25
- * @package factory-notices
26
- * @since 1.0.0
27
  */
28
  class Notices {
29
-
30
  /**
31
- * @var Wbcr_Factory412_Plugin
32
  */
33
  protected $plugin;
34
  /**
35
  * @var array
36
  */
37
- protected $notices = array();
38
-
39
  /**
40
  * @var array
41
  */
42
- protected $default_where = array(
43
  'plugins',
44
  'themes',
45
  'dashboard',
@@ -49,183 +48,188 @@ class Notices {
49
  'plugins-network',
50
  'themes-network',
51
  'settings-network',
52
- );
53
-
54
  /**
55
  * @var array
56
  */
57
  private $dissmised_notices;
58
-
59
  /**
60
  * Инициализируем уведомлений сразу после загрузки модуля уведомлений
61
  *
62
- * @param Wbcr_Factory412_Plugin $plugin
63
  */
64
  public function __construct( $plugin ) {
65
  //default notices
66
  //---
67
-
68
  $this->plugin = $plugin;
69
- $this->dissmised_notices = $this->plugin->getPopulateOption( 'factory_dismissed_notices', array() );
70
-
71
- add_action( 'current_screen', array( $this, 'currentScreenAction' ) );
72
-
73
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
74
- add_action( 'wp_ajax_' . $this->plugin->getPluginName() . '_dismiss_notice', array(
75
  $this,
76
- 'dismissNotice'
77
- ) );
78
  }
79
  }
80
-
81
  /**
82
  * Регистрирует экшены для работы с уведомлениями на текущем экране странице.
83
  * Уведомления собираются через фильтр wbcr_factory_admin_notices, если в массиве уведомлений,
84
  * хотя бы одно, соответствует условиям в параметре $notice['where'], то метод печает вспомогательные скрипты и уведомления.
85
  */
86
  public function currentScreenAction() {
87
- $this->notices = apply_filters( 'wbcr_factory_notices_000_list', $this->notices, $this->plugin->getPluginName() );
88
-
89
- $this->notices = wbcr_factory_412_apply_filters_deprecated( 'wbcr_factory_admin_notices', array(
 
90
  $this->notices,
91
- $this->plugin->getPluginName()
92
- ), '4.0.5', 'wbcr_factory_notices_000_list' );
93
-
 
 
 
 
 
94
  if ( count( $this->notices ) == 0 ) {
95
  return;
96
  }
97
-
98
  $screen = get_current_screen();
99
-
100
  $has_notices = false;
101
- foreach ( $this->notices as $notice ) {
102
-
103
  if ( ! isset( $notice['id'] ) ) {
104
  continue;
105
  }
106
-
107
  $where = ! isset( $notice['where'] ) || empty( $notice['where'] ) ? $this->default_where : $notice['where'];
108
-
109
- if ( in_array( $screen->base, $where ) && ! $this->isDissmissed( $notice['id'] ) ) {
110
  $has_notices = true;
111
  break;
112
  };
113
  }
114
-
115
  if ( $has_notices ) {
116
- add_action( 'admin_footer', array( $this, 'printNoticesScripts' ) );
117
-
118
  if ( $this->plugin->isNetworkActive() ) {
119
  if ( current_user_can( 'manage_network' ) ) {
120
- add_action( 'network_admin_notices', array( $this, 'showNotices' ) );
121
- add_action( 'admin_notices', array( $this, 'showNotices' ) );
122
  }
123
  } else {
124
- add_action( 'admin_notices', array( $this, 'showNotices' ) );
125
  }
126
  }
127
  }
128
-
129
  /**
130
  * Показывает все зарегистрированные уведомления для текущего плагина.
131
  * Уведомления показываются только на определенных страницах через параметр $notice['where'],
132
  * если уведомление ранее было скрыто или не соотвествует правилам $notice['where'], оно не будет показано!
133
  */
134
- public function showNotices() {
135
  if ( count( $this->notices ) == 0 ) {
136
  return;
137
  }
138
-
139
  if ( ! current_user_can( 'activate_plugins' ) || ! current_user_can( 'edit_plugins' ) || ! current_user_can( 'install_plugins' ) ) {
140
  return;
141
  }
142
-
143
  $screen = get_current_screen();
144
-
145
  foreach ( $this->notices as $notice ) {
146
-
147
  if ( ! isset( $notice['id'] ) ) {
148
  continue;
149
  }
150
-
151
  $where = ! isset( $notice['where'] ) || empty( $notice['where'] ) ? $this->default_where : $notice['where'];
152
-
153
- if ( in_array( $screen->base, $where ) && ! $this->isDissmissed( $notice['id'] ) ) {
154
- $this->showNotice( $notice );
155
  };
156
  }
157
  }
158
-
159
  /**
160
  * Показывает уведомление, по переданным параметрам
161
  *
162
- * @param array $data - Параметры уведомления
163
- * $data['id'] - Индентификатор уведомления
164
- * $data['type'] - Тип уведомления (error, warning, success)
165
- * $notice['where'] - На каких страницах показывать уведомление ('plugins', 'dashboard', 'edit')
166
- * $data['text'] - Текст уведомления
167
- * $data['dismissible'] - Если true, уведомление будет с кнопкой закрыть
168
- * $data['dismiss_expires'] - Когда снова показать уведомление, нужно указывать время в unix timestamp.
169
- * Пример time() + 3600 (1ч), уведомление будет скрыто на 1 час.
170
- * $data['classes'] - Произвольный классы для контейнера уведомления.
171
  */
172
- public function showNotice( $data ) {
173
- if ( ! isset( $data['id'] ) || empty( $data['id'] ) ) {
174
- return;
175
- }
176
-
177
- if ( ! isset( $data['text'] ) || empty( $data['text'] ) ) {
 
 
 
 
 
178
  return;
179
  }
180
-
181
- $type = ! isset( $data['type'] ) || empty( $data['type'] ) ? 'error' : $data['type'];
182
-
183
- $dismissible = ! isset( $data['dismissible'] ) || empty( $data['dismissible'] ) ? false : $data['dismissible'];
184
-
185
- $dismiss_expires = ! isset( $data['dismiss_expires'] ) || empty( $data['dismiss_expires'] ) ? 0 : $data['dismiss_expires'];
186
-
187
- $classes = ! isset( $data['classes'] ) || empty( $data['classes'] ) ? array() : $data['classes'];
188
-
189
  $plugin_name = str_replace( '_', '-', $this->plugin->getPluginName() );
190
-
191
- $classes = array_merge( array(
192
  'notice',
193
- 'notice-' . $type,
194
  $plugin_name . '-factory-notice'
195
- ), $classes );
196
-
197
- if ( $dismissible ) {
198
  $classes[] = 'is-dismissible';
199
  $classes[] = $plugin_name . '-factory-notice-dismiss';
200
  }
201
  ?>
202
- <div data-name="wbcr_factory_notice_<?= esc_attr( $data['id'] ) ?>" data-expires="<?= esc_attr( $dismiss_expires ) ?>" data-nonce="<?= esc_attr( wp_create_nonce( $this->plugin->getPluginName() . '_factory_dismiss_notice' ) ); ?>" class="<?= esc_attr( implode( ' ', $classes ) ) ?>">
203
  <?= $data['text'] ?>
204
  </div>
205
  <?php
206
  }
207
-
208
  /**
209
  * Когда пользователь нажимает кнопку закрыть уведомление,
210
  * отправляется ajax запрос с вызовом текущего метода
211
  */
212
- public function dismissNotice() {
 
 
 
 
213
  check_admin_referer( $this->plugin->getPluginName() . '_factory_dismiss_notice', 'nonce' );
214
-
215
  // Имя уведомления (идентификатор)
216
- $name = empty( $_POST['name'] ) ? null : sanitize_text_field( $_POST['name'] );
217
-
218
  // Время в Unix timestamp, по истечению, которого уведомление снова будет показано
219
  // Если передан 0, то уведомление будет скрыто навсегда
220
- $expires = ! isset( $_POST['expires'] ) || empty( $_POST['expires'] ) ? 0 : (int) $_POST['expires'];
221
-
222
  if ( empty( $name ) ) {
223
- echo json_encode( array( 'error' => 'Attribute name is empty!' ) );
224
- exit;
225
  }
226
-
227
- $notices = $this->plugin->getPopulateOption( "factory_dismissed_notices", array() );
228
-
229
  if ( ! empty( $notices ) ) {
230
  foreach ( (array) $notices as $notice_id => $notice_expires ) {
231
  if ( $notice_expires !== 0 && $notice_expires < time() ) {
@@ -233,23 +237,22 @@ class Notices {
233
  }
234
  }
235
  }
236
-
237
  $notices[ $name ] = $expires;
238
-
239
  $this->plugin->updatePopulateOption( 'factory_dismissed_notices', $notices );
240
-
241
- echo json_encode( array( 'success' => 'ok' ) );
242
- exit;
243
  }
244
-
245
  /**
246
  * Javascript code
247
  * Печает в подвале страницы код, для взаимодействия с сервером через ajax,
248
  * код используется при нажатии на кнопку закрыть уведомление. *
249
  */
250
- public function printNoticesScripts() {
251
  $plugin_name = str_replace( '_', '-', $this->plugin->getPluginName() );
252
-
253
  ?>
254
  <script type="text/javascript">
255
  jQuery(function($) {
@@ -267,22 +270,22 @@ class Notices {
267
  </script>
268
  <?php
269
  }
270
-
271
-
272
  /**
273
  * Проверяет скрыто уведоление или нет
274
  *
275
- * @param string $notice_id - имя уведомления
276
  *
277
  * @return bool
278
  */
279
- protected function isDissmissed( $notice_id ) {
280
  if ( ! empty( $this->dissmised_notices ) && isset( $this->dissmised_notices[ 'wbcr_factory_notice_' . $notice_id ] ) ) {
281
  $expires = (int) $this->dissmised_notices[ 'wbcr_factory_notice_' . $notice_id ];
282
-
283
  return $expires === 0 || $expires > time();
284
  }
285
-
286
  return false;
287
  }
288
  }
1
  <?php
2
 
3
+ namespace WBCR\Factory_424;
4
 
5
+ use Wbcr_Factory424_Plugin;
6
 
7
  // Exit if accessed directly
8
  if ( ! defined( 'ABSPATH' ) ) {
18
  /**
19
  * A group of classes and methods to create and manage notices.
20
  *
21
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
22
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
 
23
  *
24
+ * @package factory-notices
25
+ * @since 1.0.0
26
  */
27
  class Notices {
28
+
29
  /**
30
+ * @var Wbcr_Factory424_Plugin
31
  */
32
  protected $plugin;
33
  /**
34
  * @var array
35
  */
36
+ protected $notices = [];
37
+
38
  /**
39
  * @var array
40
  */
41
+ protected $default_where = [
42
  'plugins',
43
  'themes',
44
  'dashboard',
48
  'plugins-network',
49
  'themes-network',
50
  'settings-network',
51
+ ];
52
+
53
  /**
54
  * @var array
55
  */
56
  private $dissmised_notices;
57
+
58
  /**
59
  * Инициализируем уведомлений сразу после загрузки модуля уведомлений
60
  *
61
+ * @param Wbcr_Factory424_Plugin $plugin
62
  */
63
  public function __construct( $plugin ) {
64
  //default notices
65
  //---
66
+
67
  $this->plugin = $plugin;
68
+ $this->dissmised_notices = $this->plugin->getPopulateOption( 'factory_dismissed_notices', [] );
69
+
70
+ add_action( 'current_screen', [ $this, 'currentScreenAction' ] );
71
+
72
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
73
+ add_action( 'wp_ajax_' . $this->plugin->getPluginName() . '_dismiss_notice', [
74
  $this,
75
+ 'dismiss_notice'
76
+ ] );
77
  }
78
  }
79
+
80
  /**
81
  * Регистрирует экшены для работы с уведомлениями на текущем экране странице.
82
  * Уведомления собираются через фильтр wbcr_factory_admin_notices, если в массиве уведомлений,
83
  * хотя бы одно, соответствует условиям в параметре $notice['where'], то метод печает вспомогательные скрипты и уведомления.
84
  */
85
  public function currentScreenAction() {
86
+ /**
87
+ * @since 2.1.2 - является устаревшим
88
+ */
89
+ $this->notices = wbcr_factory_424_apply_filters_deprecated( 'wbcr_factory_notices_000_list', [
90
  $this->notices,
91
+ $this->plugin->getPluginName(),
92
+ ], '2.1.2', 'wbcr/factory/admin_notices' );
93
+
94
+ /**
95
+ * @since 2.1.2 - Добавлен, модуль factory_notices_000 был удален. Поэтому в этому хуке мы заменили префикс на factory_424
96
+ */
97
+ $this->notices = apply_filters( 'wbcr/factory/admin_notices', $this->notices, $this->plugin->getPluginName() );
98
+
99
  if ( count( $this->notices ) == 0 ) {
100
  return;
101
  }
102
+
103
  $screen = get_current_screen();
104
+
105
  $has_notices = false;
106
+ foreach ( (array) $this->notices as $notice ) {
 
107
  if ( ! isset( $notice['id'] ) ) {
108
  continue;
109
  }
110
+
111
  $where = ! isset( $notice['where'] ) || empty( $notice['where'] ) ? $this->default_where : $notice['where'];
112
+
113
+ if ( in_array( $screen->base, $where ) && ! $this->is_dissmissed( $notice['id'] ) ) {
114
  $has_notices = true;
115
  break;
116
  };
117
  }
118
+
119
  if ( $has_notices ) {
120
+ add_action( 'admin_footer', [ $this, 'print_js_code' ] );
121
+
122
  if ( $this->plugin->isNetworkActive() ) {
123
  if ( current_user_can( 'manage_network' ) ) {
124
+ add_action( 'network_admin_notices', [ $this, 'show_notices' ] );
125
+ add_action( 'admin_notices', [ $this, 'show_notices' ] );
126
  }
127
  } else {
128
+ add_action( 'admin_notices', [ $this, 'show_notices' ] );
129
  }
130
  }
131
  }
132
+
133
  /**
134
  * Показывает все зарегистрированные уведомления для текущего плагина.
135
  * Уведомления показываются только на определенных страницах через параметр $notice['where'],
136
  * если уведомление ранее было скрыто или не соотвествует правилам $notice['where'], оно не будет показано!
137
  */
138
+ public function show_notices() {
139
  if ( count( $this->notices ) == 0 ) {
140
  return;
141
  }
142
+
143
  if ( ! current_user_can( 'activate_plugins' ) || ! current_user_can( 'edit_plugins' ) || ! current_user_can( 'install_plugins' ) ) {
144
  return;
145
  }
146
+
147
  $screen = get_current_screen();
148
+
149
  foreach ( $this->notices as $notice ) {
150
+
151
  if ( ! isset( $notice['id'] ) ) {
152
  continue;
153
  }
154
+
155
  $where = ! isset( $notice['where'] ) || empty( $notice['where'] ) ? $this->default_where : $notice['where'];
156
+
157
+ if ( in_array( $screen->base, $where ) && ! $this->is_dissmissed( $notice['id'] ) ) {
158
+ $this->show_notice( $notice );
159
  };
160
  }
161
  }
162
+
163
  /**
164
  * Показывает уведомление, по переданным параметрам
165
  *
166
+ * @param array $data - Параметры уведомления
167
+ * $data['id'] - Индентификатор уведомления
168
+ * $data['type'] - Тип уведомления (error, warning, success)
169
+ * $notice['where'] - На каких страницах показывать уведомление ('plugins', 'dashboard', 'edit')
170
+ * $data['text'] - Текст уведомления
171
+ * $data['dismissible'] - Если true, уведомление будет с кнопкой закрыть
172
+ * $data['dismiss_expires'] - Когда снова показать уведомление, нужно указывать время в unix timestamp.
173
+ * Пример time() + 3600 (1ч), уведомление будет скрыто на 1 час.
174
+ * $data['classes'] - Произвольный классы для контейнера уведомления.
175
  */
176
+ public function show_notice( $data ) {
177
+ $settings = wp_parse_args( $data, [
178
+ 'id' => null,
179
+ 'text' => null,
180
+ 'type' => 'error',
181
+ 'dismissible' => false,
182
+ 'dismiss_expires' => 0,
183
+ 'classes' => []
184
+ ] );
185
+
186
+ if ( empty( $settings['id'] ) || empty( $settings['text'] ) ) {
187
  return;
188
  }
189
+
 
 
 
 
 
 
 
 
190
  $plugin_name = str_replace( '_', '-', $this->plugin->getPluginName() );
191
+
192
+ $classes = array_merge( [
193
  'notice',
194
+ 'notice-' . $settings['type'],
195
  $plugin_name . '-factory-notice'
196
+ ], $settings['classes'] );
197
+
198
+ if ( $settings['dismissible'] ) {
199
  $classes[] = 'is-dismissible';
200
  $classes[] = $plugin_name . '-factory-notice-dismiss';
201
  }
202
  ?>
203
+ <div data-name="wbcr_factory_notice_<?php echo esc_attr( $data['id'] ) ?>" data-expires="<?= 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 ) ) ?>">
204
  <?= $data['text'] ?>
205
  </div>
206
  <?php
207
  }
208
+
209
  /**
210
  * Когда пользователь нажимает кнопку закрыть уведомление,
211
  * отправляется ajax запрос с вызовом текущего метода
212
  */
213
+ public function dismiss_notice() {
214
+ if ( ! current_user_can( 'activate_plugins' ) || ! current_user_can( 'edit_plugins' ) || ! current_user_can( 'install_plugins' ) ) {
215
+ wp_die( - 1, 403 );
216
+ }
217
+
218
  check_admin_referer( $this->plugin->getPluginName() . '_factory_dismiss_notice', 'nonce' );
219
+
220
  // Имя уведомления (идентификатор)
221
+ $name = $this->plugin->request->post( 'name', null, true );
222
+
223
  // Время в Unix timestamp, по истечению, которого уведомление снова будет показано
224
  // Если передан 0, то уведомление будет скрыто навсегда
225
+ $expires = $this->plugin->request->post( 'expires', 0, 'intval' );
226
+
227
  if ( empty( $name ) ) {
228
+ wp_send_json_error( [ 'error_message' => 'You must pass the notification "Name"! Action was rejected.' ] );
 
229
  }
230
+
231
+ $notices = $this->plugin->getPopulateOption( "factory_dismissed_notices", [] );
232
+
233
  if ( ! empty( $notices ) ) {
234
  foreach ( (array) $notices as $notice_id => $notice_expires ) {
235
  if ( $notice_expires !== 0 && $notice_expires < time() ) {
237
  }
238
  }
239
  }
240
+
241
  $notices[ $name ] = $expires;
242
+
243
  $this->plugin->updatePopulateOption( 'factory_dismissed_notices', $notices );
244
+
245
+ wp_send_json_success();
 
246
  }
247
+
248
  /**
249
  * Javascript code
250
  * Печает в подвале страницы код, для взаимодействия с сервером через ajax,
251
  * код используется при нажатии на кнопку закрыть уведомление. *
252
  */
253
+ public function print_js_code() {
254
  $plugin_name = str_replace( '_', '-', $this->plugin->getPluginName() );
255
+
256
  ?>
257
  <script type="text/javascript">
258
  jQuery(function($) {
270
  </script>
271
  <?php
272
  }
273
+
274
+
275
  /**
276
  * Проверяет скрыто уведоление или нет
277
  *
278
+ * @param string $notice_id - имя уведомления
279
  *
280
  * @return bool
281
  */
282
+ protected function is_dissmissed( $notice_id ) {
283
  if ( ! empty( $this->dissmised_notices ) && isset( $this->dissmised_notices[ 'wbcr_factory_notice_' . $notice_id ] ) ) {
284
  $expires = (int) $this->dissmised_notices[ 'wbcr_factory_notice_' . $notice_id ];
285
+
286
  return $expires === 0 || $expires > time();
287
  }
288
+
289
  return false;
290
  }
291
  }
libs/factory/core/includes/class-factory-options.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412;
4
 
5
  // Exit if accessed directly
6
  use Exception;
@@ -10,101 +10,137 @@ if ( ! defined( 'ABSPATH' ) ) {
10
  }
11
 
12
  /**
13
- * Работа с опциями плагинов
14
  *
15
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
16
- * @link https://webcraftic.com
17
- * @copyright (c) 2018 Webraftic Ltd
18
- * @version 1.0
 
 
 
 
 
 
 
 
 
 
 
19
  */
20
  trait Options {
21
-
 
 
 
 
 
 
 
 
22
  abstract public function getPrefix();
23
-
24
  /**
25
- * Получает все опции плагина
 
 
 
26
  *
27
- * @since 4.0.8
28
- * @return array
29
  */
30
  public function loadAllOptions() {
31
  global $wpdb;
32
-
33
  $is_option_loaded = wp_cache_get( $this->getPrefix() . 'all_options_loaded', $this->getPrefix() . 'options' );
34
-
35
  if ( false === $is_option_loaded ) {
36
  $result = $wpdb->get_results( "SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE '{$this->getPrefix()}%'" );
37
-
38
- $options = array();
39
-
40
  if ( ! empty( $result ) ) {
41
  wp_cache_add( $this->getPrefix() . 'all_options_loaded', 1, $this->getPrefix() . 'options' );
42
-
43
  foreach ( $result as $option ) {
44
  $value = maybe_unserialize( $option->option_value );
45
  $value = $this->normalizeValue( $value );
46
-
47
  wp_cache_add( $option->option_name, $value, $this->getPrefix() . 'options' );
48
  $options[ $option->option_name ] = $value;
49
  }
50
-
51
  /**
52
- * @since 4.0.9
 
 
 
 
 
53
  */
54
  do_action( 'wbcr/factory/all_options_loaded', $options, $this->plugin_name );
55
  }
56
  }
57
  }
58
-
59
  /**
60
- * Получает все опции плагина
 
 
 
61
  *
62
- * @since 4.0.8
63
  * @return void
64
  */
65
  public function loadAllNetworkOptions() {
66
  global $wpdb;
67
-
68
  $network_id = (int) get_current_network_id();
69
-
70
  $is_option_loaded = wp_cache_get( $network_id . ":" . $this->getPrefix() . 'all_options_loaded', $this->getPrefix() . 'network_options' );
71
-
72
  if ( false === $is_option_loaded ) {
73
- wp_cache_add_global_groups( array( $this->getPrefix() . 'network_options' ) );
74
-
75
  $result = $wpdb->get_results( "SELECT meta_key, meta_value FROM {$wpdb->sitemeta} WHERE site_id='{$network_id}' AND meta_key LIKE '{$this->getPrefix()}%'" );
76
-
77
- $options = array();
78
  if ( ! empty( $result ) ) {
79
  wp_cache_add( $network_id . ":" . $this->getPrefix() . 'all_options_loaded', 1, $this->getPrefix() . 'network_options' );
80
-
81
  foreach ( $result as $option ) {
82
  $value = maybe_unserialize( $option->meta_value );
83
  $value = $this->normalizeValue( $value );
84
-
85
  $cache_key = $network_id . ":" . $option->meta_key;
86
  wp_cache_add( $cache_key, $value, $this->getPrefix() . 'network_options' );
87
  $options[ $option->meta_key ] = $value;
88
  }
89
-
90
  /**
91
- * @since 4.0.9
 
 
 
 
 
 
92
  */
93
  do_action( 'wbcr/factory/all_network_options_loaded', $options, $this->plugin_name );
94
  }
95
  }
96
  }
97
-
98
  /**
99
- * Если плагин установлен для сети, то метод возвращает опции только для сети,
100
- * иначе метод возвращает опцию для текущего сайта.
 
101
  *
102
- * @since 4.0.8
103
  *
104
- * @param string $option_name
105
- * @param string $default
106
  *
107
- * @return bool|mixed
108
  */
109
  public function getPopulateOption( $option_name, $default = false ) {
110
  if ( $this->isNetworkActive() ) {
@@ -112,57 +148,77 @@ trait Options {
112
  } else {
113
  $option_value = $this->getOption( $option_name, $default );
114
  }
115
-
 
 
 
 
 
 
 
 
 
116
  return apply_filters( "wbcr/factory/populate_option_{$option_name}", $option_value, $option_name, $default );
117
  }
118
-
119
  /**
120
- * Получает опцию для сети, используется в режиме мультисайтов
 
 
 
 
 
 
 
121
  *
122
- * @param $option_name
123
- * @param bool $default
124
  *
125
- * @return bool|mixed
126
  */
127
  public function getNetworkOption( $option_name, $default = false ) {
128
  if ( empty( $option_name ) || ! is_string( $option_name ) ) {
129
  throw new Exception( 'Option name must be a string and must not be empty.' );
130
  }
131
-
132
  if ( ! is_multisite() ) {
133
  return $this->getOption( $option_name, $default );
134
  }
135
-
136
  $this->loadAllNetworkOptions();
137
-
138
  $network_id = (int) get_current_network_id();
139
  $cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
140
  $option_value = wp_cache_get( $cache_key, $this->getPrefix() . 'network_options' );
141
-
142
  if ( false === $option_value ) {
143
  $option_value = $default;
144
  }
145
-
146
  /**
147
- * @param mixed $option_value
148
- * @param string $option_name
149
- * @param mixed $default
150
- * @param int $network_id
151
  *
152
- * @since 4.0.8
 
 
 
 
 
153
  */
154
-
155
  return apply_filters( "wbcr/factory/network_option_{$option_name}", $option_value, $option_name, $default, $network_id );
156
  }
157
-
158
  /**
159
- * Получает опцию из кеша или из базы данныеs
 
 
160
  *
161
- * @since 4.0.0
162
- * @since 4.0.8 - полностью переделан
163
  *
164
- * @param string $option_name
165
- * @param bool $default
166
  *
167
  * @return mixed
168
  */
@@ -170,31 +226,34 @@ trait Options {
170
  if ( empty( $option_name ) || ! is_string( $option_name ) ) {
171
  throw new Exception( 'Option name must be a string and must not be empty.' );
172
  }
173
-
174
  $this->loadAllOptions();
175
-
176
  $option_value = wp_cache_get( $this->getPrefix() . $option_name, $this->getPrefix() . 'options' );
177
-
178
  if ( false === $option_value ) {
179
  $option_value = $default;
180
  }
181
-
182
  /**
183
- * @param mixed $option_value
184
- * @param string $option_name
185
- * @param mixed $default
186
  *
187
- * @since 4.0.8
 
 
 
 
188
  */
189
-
190
  return apply_filters( "wbcr/factory/option_{$option_name}", $option_value, $option_name, $default );
191
  }
192
-
193
  /**
194
- * @param $option_name
195
- * @param $option_value
196
  *
197
- * @return bool
 
198
  */
199
  public function updatePopulateOption( $option_name, $option_value ) {
200
  if ( $this->isNetworkActive() ) {
@@ -203,68 +262,69 @@ trait Options {
203
  $this->updateOption( $option_name, $option_value );
204
  }
205
  }
206
-
207
  /**
208
- * Обновляет опцию для сети в базе данных и в кеше
209
- *
210
- * @since 4.0.8
211
  *
212
- * @param string $option_name
213
- * @param mixed $value
214
  *
215
- * @return bool
 
216
  */
217
  public function updateNetworkOption( $option_name, $option_value ) {
218
  $network_id = (int) get_current_network_id();
219
  $cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
220
  wp_cache_set( $cache_key, $option_value, $this->getPrefix() . 'network_options' );
221
-
222
- $result = update_site_option( $this->getPrefix() . $option_name, $option_value );
223
-
224
  /**
225
- * @param mixed $option_value
226
- * @param string $option_name
227
  *
228
- * @since 4.0.8
 
 
 
229
  */
230
  do_action( "wbcr/factory/update_network_option", $option_name, $option_value );
231
-
232
- return $result;
233
  }
234
-
235
  /**
236
- * Обновляет опцию в базе данных и в кеше
 
237
  *
238
- * @since 4.0.0
239
- * @since 4.0.8 - полностью переделан
240
  *
241
- * @param string $option_name
242
- * @param mixed $value
243
  *
244
  * @return bool
245
  */
246
  public function updateOption( $option_name, $option_value ) {
247
  wp_cache_set( $this->getPrefix() . $option_name, $option_value, $this->getPrefix() . 'options' );
248
  $result = update_option( $this->getPrefix() . $option_name, $option_value );
249
-
250
  /**
251
- * @param mixed $option_value
 
252
  * @param string $option_name
253
  *
254
- * @since 4.0.8
255
  */
256
  do_action( "wbcr/factory/update_option", $option_name, $option_value );
257
-
258
  return $result;
259
  }
260
-
261
  /**
262
- * Удаляет опцию из базы данных, если опция есть в кеше,
263
- * индивидуально удаляет опцию из кеша.
264
  *
265
- * @param string $option_name
266
  *
267
- * @return void
268
  */
269
  public function deletePopulateOption( $option_name ) {
270
  if ( $this->isNetworkActive() ) {
@@ -273,79 +333,91 @@ trait Options {
273
  $this->deleteOption( $option_name );
274
  }
275
  }
276
-
277
  /**
278
- * Удаляет опцию из базы данных, если опция есть в кеше,
279
- * индивидуально удаляет опцию из кеша.
280
  *
281
- * @param string $option_name
282
  *
283
- * @return bool
 
 
284
  */
285
  public function deleteNetworkOption( $option_name ) {
286
  $network_id = (int) get_current_network_id();
287
  $cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
288
  $delete_cache = wp_cache_delete( $cache_key, $this->getPrefix() . 'network_options' );
289
-
290
  $delete_opt1 = delete_site_option( $this->getPrefix() . $option_name );
291
-
292
  return $delete_cache && $delete_opt1;
293
  }
294
-
295
  /**
296
- * Удаляет опцию из базы данных, если опция есть в кеше,
297
- * индивидуально удаляет опцию из кеша.
298
  *
299
- * @param string $option_name
300
  *
301
- * @return bool
 
 
302
  */
303
  public function deleteOption( $option_name ) {
304
  $delete_cache = wp_cache_delete( $this->getPrefix() . $option_name, $this->getPrefix() . 'options' );
305
-
306
  // todo: удалить, когда большая часть пользователей обновятся до современных релизов
307
  $delete_opt1 = delete_option( $this->getPrefix() . $option_name . '_is_active' );
308
  $delete_opt2 = delete_option( $this->getPrefix() . $option_name );
309
-
310
  return $delete_cache && $delete_opt1 && $delete_opt2;
311
  }
312
-
313
  /**
314
- * Сбрасывает объектный кеш опций
315
  *
316
- * @return bool
 
317
  */
318
  public function flushOptionsCache() {
319
  return wp_cache_flush();
320
  }
321
-
322
  /**
323
- * Возвращает название опции в пространстве имен плагина
 
 
 
324
  *
325
- * @param string $option_name
326
  *
327
- * @return null|string
328
  */
329
  public function getOptionName( $option_name ) {
330
  $option_name = trim( rtrim( $option_name ) );
331
  if ( empty( $option_name ) || ! is_string( $option_name ) ) {
332
  return null;
333
  }
334
-
335
  return $this->getPrefix() . $option_name;
336
  }
337
-
338
  /**
339
- * Приведение значений опций к строгому типу данных
 
 
 
 
340
  *
341
- * @param mixed $string
342
  *
343
- * @return bool|int
 
 
344
  */
345
  public function normalizeValue( $data ) {
346
  if ( is_string( $data ) ) {
347
  $check_string = rtrim( trim( $data ) );
348
-
349
  if ( $check_string == "1" || $check_string == "0" ) {
350
  return intval( $data );
351
  } else if ( $check_string === 'false' ) {
@@ -354,7 +426,7 @@ trait Options {
354
  return true;
355
  }
356
  }
357
-
358
  return $data;
359
  }
360
  }
1
  <?php
2
 
3
+ namespace WBCR\Factory_424;
4
 
5
  // Exit if accessed directly
6
  use Exception;
10
  }
11
 
12
  /**
13
+ * Трейт используется для расширения базового класса плагина Wbcr_Factory424_Base, позволяя работать с опциями плагина.
14
  *
15
+ * Этот трейт является оберткой для Wordpress функций get_option, get_site_option, update_option, update_site_option,
16
+ * delete_option, delete_site_option. Основная задача была получать, обновлять, удалять опции без использования префиксов,
17
+ * чтобы класс выполнял эту работу за программиста. В дополнение, трейт содержит методы для полной выгрузки всех опций
18
+ * плагина, что позволяет при инициализации плагина автоматически выгрузить все существующие опции плагина в объектный
19
+ * кеш. Все опции, с которыми работает плагин, могут быть отфильтрованы.
20
+ *
21
+ * Документация по трейту: https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/393805831/
22
+ * Документация по созданию плагина: https://webcraftic.atlassian.net/wiki/spaces/CNCFC/pages/327828
23
+ * Репозиторий: https://github.com/alexkovalevv
24
+ *
25
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
26
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
27
+ *
28
+ * @since 4.0.8 - Добавлен
29
+ * @package factory-core
30
  */
31
  trait Options {
32
+
33
+ /**
34
+ * Абстрактный метод, должен быть реализован в классе использующем этот трейт. Метод позволяет получить префикс
35
+ * плагина для формирования имен опций в базе данных Wordpress. У опций должно быть свое пространство имен,
36
+ * иначе может быть конфликт с другими плагинами или с сами ядром Wordpress.
37
+ *
38
+ * @since 4.0.8 - Добавлен
39
+ * @return string Возвращает префикс плагина. Пример: wbcr_clearfy_
40
+ */
41
  abstract public function getPrefix();
42
+
43
  /**
44
+ * Выгружает все опции плагина в объектный кеш. Плагин может получить любую свою опцию без запроса к базе данных.
45
+ * Метод ускоряет работу плагина, если опций очень много.
46
+ *
47
+ * Используется только один раз при инициализации плагина.
48
  *
49
+ * @since 4.0.8 - Добавлен
 
50
  */
51
  public function loadAllOptions() {
52
  global $wpdb;
53
+
54
  $is_option_loaded = wp_cache_get( $this->getPrefix() . 'all_options_loaded', $this->getPrefix() . 'options' );
55
+
56
  if ( false === $is_option_loaded ) {
57
  $result = $wpdb->get_results( "SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE '{$this->getPrefix()}%'" );
58
+
59
+ $options = [];
60
+
61
  if ( ! empty( $result ) ) {
62
  wp_cache_add( $this->getPrefix() . 'all_options_loaded', 1, $this->getPrefix() . 'options' );
63
+
64
  foreach ( $result as $option ) {
65
  $value = maybe_unserialize( $option->option_value );
66
  $value = $this->normalizeValue( $value );
67
+
68
  wp_cache_add( $option->option_name, $value, $this->getPrefix() . 'options' );
69
  $options[ $option->option_name ] = $value;
70
  }
71
+
72
  /**
73
+ * Действие, которое будет выполнено, когда все опции плагина будут выгружены.
74
+ *
75
+ * @since 4.0.9 - Добавлен
76
+ *
77
+ * @param string $plugin_name Имя плагина
78
+ * @param array $options Ассоциативный массив опций плагина
79
  */
80
  do_action( 'wbcr/factory/all_options_loaded', $options, $this->plugin_name );
81
  }
82
  }
83
  }
84
+
85
  /**
86
+ * Выгружает все сетевые опции плагина в объектный кеш. Плагин может получить любую свою опцию без запроса к базе
87
+ * данных. Метод ускоряет работу плагина, если опций очень много.
88
+ *
89
+ * Используется и работает только в режиме мультисайтов, один раз при инициализации плагина.!
90
  *
91
+ * @since 4.0.8 - Добавлен
92
  * @return void
93
  */
94
  public function loadAllNetworkOptions() {
95
  global $wpdb;
96
+
97
  $network_id = (int) get_current_network_id();
98
+
99
  $is_option_loaded = wp_cache_get( $network_id . ":" . $this->getPrefix() . 'all_options_loaded', $this->getPrefix() . 'network_options' );
100
+
101
  if ( false === $is_option_loaded ) {
102
+ wp_cache_add_global_groups( [ $this->getPrefix() . 'network_options' ] );
103
+
104
  $result = $wpdb->get_results( "SELECT meta_key, meta_value FROM {$wpdb->sitemeta} WHERE site_id='{$network_id}' AND meta_key LIKE '{$this->getPrefix()}%'" );
105
+
106
+ $options = [];
107
  if ( ! empty( $result ) ) {
108
  wp_cache_add( $network_id . ":" . $this->getPrefix() . 'all_options_loaded', 1, $this->getPrefix() . 'network_options' );
109
+
110
  foreach ( $result as $option ) {
111
  $value = maybe_unserialize( $option->meta_value );
112
  $value = $this->normalizeValue( $value );
113
+
114
  $cache_key = $network_id . ":" . $option->meta_key;
115
  wp_cache_add( $cache_key, $value, $this->getPrefix() . 'network_options' );
116
  $options[ $option->meta_key ] = $value;
117
  }
118
+
119
  /**
120
+ *
121
+ * Действие, которое будет выполнено, когда все сетевые опции плагина будут выгружены.
122
+ *
123
+ * @since 4.0.9 - Добавлен
124
+ *
125
+ * @param array $options Ассоциативный массив опций плагина
126
+ * @param string $plugin_name Имя плагина
127
  */
128
  do_action( 'wbcr/factory/all_network_options_loaded', $options, $this->plugin_name );
129
  }
130
  }
131
  }
132
+
133
  /**
134
+ * Позволяет получить популярную опцию. В случае если плагин установлен для сети (в режиме мультисайтов),
135
+ * то метод возвращает опции только для сети, иначе метод возвращает опцию для текущего сайта. Работает
136
+ * на основе self::getOption и self::getNetworkOption, смотрите полную реализацию в этих методах.
137
  *
138
+ * @since 4.0.8 - Добавлен
139
  *
140
+ * @param string $option_name Имя опции без префикса.
141
+ * @param mixed $default Значение по умолчанию. Если опции нет в базе данных, будет возвращено это значение. По умолчанию false
142
  *
143
+ * @return mixed Возвращает значение опции, если это сериализованная строка, то автоматически распаковывает ее.
144
  */
145
  public function getPopulateOption( $option_name, $default = false ) {
146
  if ( $this->isNetworkActive() ) {
148
  } else {
149
  $option_value = $this->getOption( $option_name, $default );
150
  }
151
+
152
+ /**
153
+ * Фильтр позволяет отфильтровать возвращаемое значение популярной опции.
154
+ *
155
+ * @since 4.0.9 - Добавлен
156
+ *
157
+ * @param mixed $option_value Значение опции
158
+ * @param string $option_name Имя опции
159
+ * @param mixed $default Значение опции по умолчанию
160
+ */
161
  return apply_filters( "wbcr/factory/populate_option_{$option_name}", $option_value, $option_name, $default );
162
  }
163
+
164
  /**
165
+ * Позволяет получить сетевые опции. Если плагин установлен для сети (в режиме мультисайтов), то
166
+ * метод возвращает опции только для сети, иначе метод возвращает опцию для текущего сайта.
167
+ *
168
+ * Опция вытаскивается из объектного кеша, после выполнения метода self:loadAllNetworkOptions,
169
+ * а не напрямую из базы данных, из-за чего при работе с некоторыми кеширующими плагинами,
170
+ * может быть странное поведение в работе плагина.
171
+ *
172
+ * @since 4.0.8 - Добавлен
173
  *
174
+ * @param string $option_name Имя опции без префикса.
175
+ * @param mixed $default Значение по умолчанию. Если опции нет в базе данных, будет возвращено это значение. По умолчанию false
176
  *
177
+ * @return mixed Возвращает значение опции, если это сериализованная строка, то автоматически распаковывает ее.
178
  */
179
  public function getNetworkOption( $option_name, $default = false ) {
180
  if ( empty( $option_name ) || ! is_string( $option_name ) ) {
181
  throw new Exception( 'Option name must be a string and must not be empty.' );
182
  }
183
+
184
  if ( ! is_multisite() ) {
185
  return $this->getOption( $option_name, $default );
186
  }
187
+
188
  $this->loadAllNetworkOptions();
189
+
190
  $network_id = (int) get_current_network_id();
191
  $cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
192
  $option_value = wp_cache_get( $cache_key, $this->getPrefix() . 'network_options' );
193
+
194
  if ( false === $option_value ) {
195
  $option_value = $default;
196
  }
197
+
198
  /**
199
+ * Фильтр позволяет отфильтровать возвращаемое значение сетевой опции.
 
 
 
200
  *
201
+ * @since 4.0.9 - Добавлен
202
+ *
203
+ * @param mixed $option_value Значение опции
204
+ * @param string $option_name Имя опции
205
+ * @param mixed $default Значение опции по умолчанию
206
+ * @param int $network_id ID сети
207
  */
208
+
209
  return apply_filters( "wbcr/factory/network_option_{$option_name}", $option_value, $option_name, $default, $network_id );
210
  }
211
+
212
  /**
213
+ * Метод позволяет получить опцию для текущего сайта. Опция вытаскивается из объектного кеша, после выполнения метода
214
+ * self:loadAllOptions, а не напрямую из базы данных, из-за чего при работе с некоторыми кеширующими плагинами,
215
+ * может быть странное поведение в работе плагина.
216
  *
217
+ * @since 4.0.0 - Добавлен
218
+ * @since 4.0.8 - Полностью переделан
219
  *
220
+ * @param string $option_name Имя опции без префикса.
221
+ * @param mixed $default Значение по умолчанию. Если опции нет в базе данных, будет возвращено это значение. По умолчанию false
222
  *
223
  * @return mixed
224
  */
226
  if ( empty( $option_name ) || ! is_string( $option_name ) ) {
227
  throw new Exception( 'Option name must be a string and must not be empty.' );
228
  }
229
+
230
  $this->loadAllOptions();
231
+
232
  $option_value = wp_cache_get( $this->getPrefix() . $option_name, $this->getPrefix() . 'options' );
233
+
234
  if ( false === $option_value ) {
235
  $option_value = $default;
236
  }
237
+
238
  /**
239
+ * Фильтр позволяет отфильтровать возвращаемое значение опции сайта.
 
 
240
  *
241
+ * @since 4.0.9 - Добавлен
242
+ *
243
+ * @param mixed $option_value Значение опции
244
+ * @param string $option_name Имя опции
245
+ * @param mixed $default Значение опции по умолчанию
246
  */
247
+
248
  return apply_filters( "wbcr/factory/option_{$option_name}", $option_value, $option_name, $default );
249
  }
250
+
251
  /**
252
+ * Позволяет обновить популярную опцию в базе данных. Если плагин установлен для сети (в режиме мультисайтов), то метод обновляет опцию
253
+ * только в таблице sitemeta, иначе в таблице options для текущего сайта.
254
  *
255
+ * @param string $option_name Имя опции без префикса.
256
+ * @param mixed $option_value Значение опции. Может принимать массив или объект.
257
  */
258
  public function updatePopulateOption( $option_name, $option_value ) {
259
  if ( $this->isNetworkActive() ) {
262
  $this->updateOption( $option_name, $option_value );
263
  }
264
  }
265
+
266
  /**
267
+ * Обновляет сетевую опцию в БД таблица sitemeta. После успешного обновления опции в базе данных, метод добавляет опцию в объектный кеш,
268
+ * чтобы плагин мог приступить к работе с этой опцией незамедлительно.
 
269
  *
270
+ * @since 4.0.8 - Добавлен
 
271
  *
272
+ * @param string $option_name Имя опции без префикса.
273
+ * @param mixed $option_value Значение опции. Может принимать массив или объект.
274
  */
275
  public function updateNetworkOption( $option_name, $option_value ) {
276
  $network_id = (int) get_current_network_id();
277
  $cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
278
  wp_cache_set( $cache_key, $option_value, $this->getPrefix() . 'network_options' );
279
+
280
+ update_site_option( $this->getPrefix() . $option_name, $option_value );
281
+
282
  /**
283
+ * Действие будет выполнено, когда сетевая опция будет обновлена.
 
284
  *
285
+ * @since 4.0.8 - Добавлен
286
+ *
287
+ * @param string $option_name Имя опции без префикса.
288
+ * @param mixed $option_value Значение опции. Может принимать массив или объект.
289
  */
290
  do_action( "wbcr/factory/update_network_option", $option_name, $option_value );
 
 
291
  }
292
+
293
  /**
294
+ * Обновляет опцию сайта в БД таблица options. После успешного обновления опции в базе данных, метод добавляет опцию в объектный кеш,
295
+ * чтобы плагин мог приступить к работе с этой опцией незамедлительно.
296
  *
297
+ * @since 4.0.0 - Добавлен
298
+ * @since 4.0.8 - Полностью переделан
299
  *
300
+ * @param string $option_name Имя опции без префикса.
301
+ * @param mixed $option_value Значение опции. Может принимать массив или объект.
302
  *
303
  * @return bool
304
  */
305
  public function updateOption( $option_name, $option_value ) {
306
  wp_cache_set( $this->getPrefix() . $option_name, $option_value, $this->getPrefix() . 'options' );
307
  $result = update_option( $this->getPrefix() . $option_name, $option_value );
308
+
309
  /**
310
+ * @since 4.0.8
311
+ *
312
  * @param string $option_name
313
  *
314
+ * @param mixed $option_value
315
  */
316
  do_action( "wbcr/factory/update_option", $option_name, $option_value );
317
+
318
  return $result;
319
  }
320
+
321
  /**
322
+ * Позволяет удалять популярную опцию в базе данных. Если плагин установлен для сети (в режиме мультисайтов), то метод удаляет опцию
323
+ * только в таблице sitemeta, иначе в таблице options для текущего сайта.
324
  *
325
+ * @since 4.0.0 - Добавлен
326
  *
327
+ * @param string $option_name Имя опции без префикса.
328
  */
329
  public function deletePopulateOption( $option_name ) {
330
  if ( $this->isNetworkActive() ) {
333
  $this->deleteOption( $option_name );
334
  }
335
  }
336
+
337
  /**
338
+ * Удаляет сетевую.опцию в БД таблица sitemeta, а если опция есть в кеше, индивидуально удаляет опцию из кеша.
 
339
  *
340
+ * @since 4.0.0 - Добавлен
341
  *
342
+ * @param string $option_name Имя опции без префикса.
343
+ *
344
+ * @return bool Возвращает true, если опция удалена успешно, false в случае ошибки.
345
  */
346
  public function deleteNetworkOption( $option_name ) {
347
  $network_id = (int) get_current_network_id();
348
  $cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
349
  $delete_cache = wp_cache_delete( $cache_key, $this->getPrefix() . 'network_options' );
350
+
351
  $delete_opt1 = delete_site_option( $this->getPrefix() . $option_name );
352
+
353
  return $delete_cache && $delete_opt1;
354
  }
355
+
356
  /**
357
+ * Удаляет опцию сайта в БД таблица options, а если опция есть в кеше, индивидуально удаляет опцию из кеша.
 
358
  *
359
+ * @since 4.0.0 - Добавлен
360
  *
361
+ * @param string $option_name Имя опции без префикса.
362
+ *
363
+ * @return bool Возвращает true, если опция удалена успешно, false в случае ошибки.
364
  */
365
  public function deleteOption( $option_name ) {
366
  $delete_cache = wp_cache_delete( $this->getPrefix() . $option_name, $this->getPrefix() . 'options' );
367
+
368
  // todo: удалить, когда большая часть пользователей обновятся до современных релизов
369
  $delete_opt1 = delete_option( $this->getPrefix() . $option_name . '_is_active' );
370
  $delete_opt2 = delete_option( $this->getPrefix() . $option_name );
371
+
372
  return $delete_cache && $delete_opt1 && $delete_opt2;
373
  }
374
+
375
  /**
376
+ * Сбрасывает объектный кеш. Может использоваться для перезагрузки опций плагина и Wordpress в целом.
377
  *
378
+ * @since 4.0.0 - Добавлен
379
+ * @return bool Возвращает true, если кеш сброшен успешно, false в случае ошибки.
380
  */
381
  public function flushOptionsCache() {
382
  return wp_cache_flush();
383
  }
384
+
385
  /**
386
+ * Позволяет получить полное имя опции с префиксом. Может быть использовано в тех случаях, где нужно получить
387
+ * полное имя опции.
388
+ *
389
+ * @since 4.0.0 - Добавлен
390
  *
391
+ * @param string $option_name Имя опции без префикса.
392
  *
393
+ * @return null|string Возвращает имя опции с префиксом. Например wbcr_clearfy_{options_name}
394
  */
395
  public function getOptionName( $option_name ) {
396
  $option_name = trim( rtrim( $option_name ) );
397
  if ( empty( $option_name ) || ! is_string( $option_name ) ) {
398
  return null;
399
  }
400
+
401
  return $this->getPrefix() . $option_name;
402
  }
403
+
404
  /**
405
+ * Позволяет нормализовать данные. В некоторых методах этого трейта, ожидаются данные определенного типа, чтобы
406
+ * выполнить различные логические операции. Как раз в этом случае этот метод можно использовать, чтобы привести
407
+ * все сырые данные в строгий тип. Такое решение позволит избежать ошибок в работе программиста.
408
+ *
409
+ * @since 4.0.0 - Добавлен
410
  *
411
+ * @param mixed $data Данные, которые нужно нормализовать.
412
  *
413
+ * @return mixed Возвращает нормализованное значение.
414
+ * - Если передана строка "true" или "false" вернет булево значение.
415
+ * - Если передана строка "1" или "0" вернет число.
416
  */
417
  public function normalizeValue( $data ) {
418
  if ( is_string( $data ) ) {
419
  $check_string = rtrim( trim( $data ) );
420
+
421
  if ( $check_string == "1" || $check_string == "0" ) {
422
  return intval( $data );
423
  } else if ( $check_string === 'false' ) {
426
  return true;
427
  }
428
  }
429
+
430
  return $data;
431
  }
432
  }
libs/factory/core/includes/class-factory-plugin-abstract.php CHANGED
@@ -4,67 +4,94 @@ if ( ! defined( 'ABSPATH' ) ) {
4
  exit;
5
  }
6
 
7
-
8
  /**
9
- * The file contains the class to register a plugin in the Factory.
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  *
11
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
12
  * @since 1.0.0
13
  * @package factory-core
14
- * @copyright (c) 2018 Webcraftic Ltd
15
  *
16
  */
17
- abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
18
 
19
  /**
20
- * Instance class Wbcr_Factory412_Request, required manages http requests
21
  *
22
- * @var Wbcr_Factory412_Request
 
23
  */
24
  public $request;
25
 
26
  /**
27
- * @var \WBCR\Factory_412\Premium\Provider
 
28
  */
29
  public $premium;
30
 
31
  /**
32
  * The Bootstrap Manager class
33
  *
34
- * @var Wbcr_FactoryBootstrap412_Manager
35
  */
36
  public $bootstrap;
37
 
38
  /**
39
  * The Bootstrap Manager class
40
  *
41
- * @var Wbcr_FactoryForms412_Manager
42
  */
43
  public $forms;
44
 
45
  /**
46
- * A class name of an activator to activate the plugin.
 
 
47
  *
48
- * @var string
49
  */
50
  protected $activator_class = [];
51
 
52
  /**
53
- * Framework modules loaded
 
54
  *
55
  * @var array
56
  */
57
  private $loaded_factory_modules = [];
58
 
59
  /**
60
- * Plugin components loaded
 
61
  *
62
- * @var array[] Wbcr_Factory412_Plugin
 
 
63
  */
64
- private $plugin_addons;
65
 
66
  /**
67
- * Creates an instance of Factory plugin.
 
 
 
 
 
 
 
 
 
68
  *
69
  * @since 1.0.0
70
  *
@@ -78,8 +105,8 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
78
 
79
  parent::__construct( $plugin_path, $data );
80
 
81
- $this->request = new Wbcr_Factory412_Request();
82
- //$this->route = new Wbcr_Factory412_Route();
83
 
84
  // INIT PLUGIN FRAMEWORK MODULES
85
  // Framework modules should always be loaded first,
@@ -102,29 +129,100 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
102
 
103
  // init actions
104
  $this->register_plugin_hooks();
105
- }
106
 
107
- /* Services region
108
- /* -------------------------------------------------------------*/
 
109
 
110
  /**
111
- * @param Wbcr_FactoryBootstrap412_Manager $bootstrap
 
 
 
112
  */
113
- public function setBootstap( Wbcr_FactoryBootstrap412_Manager $bootstrap ) {
114
  $this->bootstrap = $bootstrap;
115
  }
116
 
117
  /**
118
- * @param Wbcr_FactoryForms412_Manager $forms
 
 
119
  */
120
- public function setForms( Wbcr_FactoryForms412_Manager $forms ) {
121
  $this->forms = $forms;
122
  }
123
 
124
  /**
125
- * Устанавливает текстовый домен для плагина
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  */
127
- public function set_text_domain( $domain ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  if ( empty( $this->plugin_text_domain ) ) {
129
  return;
130
  }
@@ -138,9 +236,29 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
138
  }
139
  }
140
 
 
 
 
 
 
 
 
 
141
  /**
142
- * @param $class_name
143
- * @param $file_path
 
 
 
 
 
 
 
 
 
 
 
 
144
  *
145
  * @throws Exception
146
  */
@@ -160,36 +278,28 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
160
  throw new Exception( 'A class with this name {' . $class_name . '} does not exist.' );
161
  }
162
 
163
- if ( ! class_exists( 'Wbcr_FactoryPages412' ) ) {
164
- throw new Exception( 'The factory_pages_412 module is not included.' );
165
  }
166
 
167
- Wbcr_FactoryPages412::register( $this, $class_name );
168
  }
169
 
170
  /**
171
- * @param string $class_name
172
- * @param string $path
 
 
 
 
 
 
173
  *
174
  * @throws Exception
 
175
  */
176
  public function registerType( $class_name, $file_path ) {
177
-
178
- if ( ! file_exists( $file_path ) ) {
179
- throw new Exception( 'The page file was not found by the path {' . $file_path . '} you set.' );
180
- }
181
-
182
- require_once( $file_path );
183
-
184
- if ( ! class_exists( $class_name ) ) {
185
- throw new Exception( 'A class with this name {' . $class_name . '} does not exist.' );
186
- }
187
-
188
- if ( ! class_exists( 'Wbcr_FactoryTypes000' ) ) {
189
- throw new Exception( 'The factory_types_000 module is not included.' );
190
- }
191
-
192
- Wbcr_FactoryTypes000::register( $class_name, $this );
193
  }
194
 
195
  /**
@@ -219,33 +329,59 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
219
  /**
220
  * @since 4.1.1 - change hook name
221
  */
222
- if ( apply_filters( "wbcr/factory_412/cancel_plugin_activation_{$this->plugin_name}", false ) ) {
223
  return;
224
  }
225
 
226
  /**
 
 
227
  * @since 4.1.1 - deprecated
228
  */
229
- wbcr_factory_412_do_action_deprecated( 'wbcr_factory_412_plugin_activation', [
230
  $this
231
  ], '4.1.1', "wbcr/factory/plugin_activation" );
232
 
233
  /**
234
- * @since 4.1.1 - added
 
 
 
 
 
 
 
 
 
 
 
235
  */
236
- do_action( 'wbcr/factory/plugin_activation', $this->plugin_name );
237
 
238
  /**
 
 
 
 
 
 
 
 
 
 
 
239
  * @since 4.1.1 - deprecated
240
  */
241
- wbcr_factory_412_do_action_deprecated( 'wbcr_factory_412_plugin_activation_' . $this->plugin_name, [
242
  $this
243
- ], '4.1.1', "wbcr/factory/plugin_{$this->plugin_name}_activation" );
244
 
245
  /**
246
- * @since 4.1.1 - added
 
 
247
  */
248
- do_action( "wbcr/factory/plugin_{$this->plugin_name}_activation" );
249
 
250
  if ( ! empty( $this->activator_class ) ) {
251
  foreach ( (array) $this->activator_class as $activator_class ) {
@@ -253,6 +389,97 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
253
  $activator->activate();
254
  }
255
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  }
257
 
258
  /**
@@ -265,8 +492,8 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
265
  * @throws Exception
266
  */
267
  public function getPluginPageUrl( $page_id, $args = [] ) {
268
- if ( ! class_exists( 'Wbcr_FactoryPages412' ) ) {
269
- throw new Exception( 'The factory_pages_412 module is not included.' );
270
  }
271
 
272
  if ( ! is_admin() ) {
@@ -275,53 +502,60 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
275
  return null;
276
  }
277
 
278
- return Wbcr_FactoryPages412::getPageUrl( $this, $page_id, $args );
279
  }
280
 
281
-
282
  /**
283
  * Загружает аддоны для плагина, как часть проекта, а не как отдельный плагин
284
  *
285
- * @param array $addons - массив со списком загружаемых аддонов.
286
- * array(
287
- * 'hide_login_page' => - ключ, идентификатора массива с информацией об аддоне
288
- * array(
289
- * 'WHLP_Plugin', - имя основного класса аддона
290
- * WCL_PLUGIN_DIR . '/components/hide-login-page/hide-login-page.php' - пусть к
291
- * основному файлу аддона
292
- * ));
293
  */
294
- protected function loadAddons( $addons ) {
295
- if ( empty( $addons ) ) {
 
 
 
296
  return;
297
  }
298
 
299
- foreach ( $addons as $addon_name => $addon_path ) {
300
- if ( ! isset( $this->plugin_addons[ $addon_name ] ) ) {
301
-
302
- // При подключении аддона, мы объявляем константу, что такой аддон уже загружен
303
- // $addon_name индентификатор аддона в вверхнем регистре
304
- $const_name = strtoupper( 'LOADING_' . str_replace( '-', '_', $addon_name ) . '_AS_ADDON' );
305
 
306
- if ( ! defined( $const_name ) ) {
307
- define( $const_name, true );
308
  }
309
 
310
- require_once( $addon_path[1] );
311
 
312
- // Передаем аддону информацию о родительском плагине
313
- $plugin_data = $this->getPluginInfo();
 
314
 
315
- // Устанавливаем метку для аддона, которая указывает на то, что это аддон
316
- $plugin_data['as_addon'] = true;
317
 
318
- // Передаем класс родителя в аддон, для того,
319
- // чтобы аддон использовал экземпляр класса родителя, а не создавал свой собственный.
320
- $plugin_data['plugin_parent'] = $this;
321
 
322
- // Создаем экземпляр класса аддона и записываем его в список загруженных аддонов
323
- if ( class_exists( $addon_path[0] ) ) {
324
- $this->plugin_addons[ $addon_name ] = new $addon_path[0]( $this->get_paths()->main_file, $plugin_data );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  }
326
  }
327
  }
@@ -362,12 +596,12 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
362
  /**
363
  * @since 4.1.1 - deprecated
364
  */
365
- wbcr_factory_412_do_action_deprecated( 'wbcr_factory_412_core_modules_loaded-' . $this->plugin_name, [], '4.1.1', "wbcr/factory/plugin_activation" );
366
 
367
  /**
368
  * @since 4.1.1 - add
369
  */
370
- do_action( 'wbcr/factory_412/modules_loaded-' . $this->plugin_name );
371
  }
372
 
373
 
@@ -381,60 +615,13 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
381
  add_action( 'plugins_loaded', [ $this, 'set_text_domain' ] );
382
 
383
  if ( is_admin() ) {
384
- add_filter( 'wbcr_factory_412_core_admin_allow_multisite', '__return_true' );
385
 
386
  register_activation_hook( $this->get_paths()->main_file, [ $this, 'activation_hook' ] );
387
  register_deactivation_hook( $this->get_paths()->main_file, [ $this, 'deactivation_hook' ] );
388
  }
389
  }
390
 
391
- /**
392
- * It's invoked on plugin deactionvation. Don't excite it directly.
393
- *
394
- * @since 1.0.0
395
- * @return void
396
- */
397
- public function deactivation_hook() {
398
-
399
- /**
400
- * @since 4.1.1 - change hook name
401
- */
402
- if ( apply_filters( "wbcr/factory_412/cancel_plugin_deactivation_{$this->plugin_name}", false ) ) {
403
- return;
404
- }
405
-
406
- /**
407
- * @since 4.1.1 - deprecated
408
- */
409
- wbcr_factory_412_do_action_deprecated( 'wbcr_factory_412_plugin_deactivation', [
410
- $this
411
- ], '4.1.1', "wbcr/factory/plugin_deactivation" );
412
-
413
- /**
414
- * @since 4.1.1 - added
415
- */
416
- do_action( 'wbcr/factory/plugin_deactivation', $this->plugin_name );
417
-
418
- /**
419
- * @since 4.1.1 - deprecated
420
- */
421
- wbcr_factory_412_do_action_deprecated( 'wbcr_factory_412_plugin_deactivation_' . $this->plugin_name, [
422
- $this
423
- ], '4.1.1', "wbcr/factory/plugin_{$this->plugin_name}_deactivation" );
424
-
425
- /**
426
- * @since 4.1.1 - added
427
- */
428
- do_action( "wbcr/factory/plugin_{$this->plugin_name}_deactivation" );
429
-
430
- if ( ! empty( $this->activator_class ) ) {
431
- foreach ( (array) $this->activator_class as $activator_class ) {
432
- $activator = new $activator_class( $this );
433
- $activator->deactivate();
434
- }
435
- }
436
- }
437
-
438
  /**
439
  * Инициализируем миграции плагина
440
  *
@@ -443,7 +630,7 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
443
  * @throws Exception
444
  */
445
  protected function init_plugin_migrations() {
446
- new WBCR\Factory_412\Migrations( $this );
447
  }
448
 
449
  /**
@@ -453,11 +640,11 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
453
  * @return void
454
  */
455
  protected function init_plugin_notices() {
456
- new Wbcr\Factory_412\Notices( $this );
457
  }
458
 
459
  /**
460
- * Создает нового рабочего для проверки обновлений и апгрейда текущего плагина. *
461
  *
462
  * @since 4.1.1
463
  *
@@ -468,7 +655,7 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
468
  */
469
  protected function init_plugin_updates() {
470
  if ( $this->has_updates ) {
471
- new WBCR\Factory_412\Updates\Upgrader( $this );
472
  }
473
  }
474
 
@@ -490,49 +677,12 @@ abstract class Wbcr_Factory412_Plugin extends Wbcr_Factory412_Base {
490
  }
491
 
492
  // Создаем экземляр премиум менеджера, мы сможем к нему обращаться глобально.
493
- $this->premium = WBCR\Factory_412\Premium\Manager::instance( $this, $this->license_settings );
494
 
495
  // Подключаем премиум апгрейдер
496
  if ( isset( $this->license_settings['has_updates'] ) && $this->license_settings['has_updates'] ) {
497
- new WBCR\Factory_412\Updates\Premium_Upgrader( $this );
498
- }
499
- }
500
-
501
- /**
502
- * @since 4.1.1
503
- *
504
- * @param array | string $dependents
505
- *
506
- * @throws Exception
507
- */
508
- /*protected function modules_dependent( $dependents ) {
509
- $modules = array();
510
-
511
- if ( is_array( $dependents ) ) {
512
- foreach ( $dependents as $module_name ) {
513
- if ( ! isset( $this->loaded_factory_modules[ $module_name ] ) ) {
514
- $modules[] = $module_name;
515
- }
516
- }
517
- } else if ( ! isset( $this->loaded_factory_modules[ $dependents ] ) ) {
518
- $modules[] = $dependents;
519
- }
520
-
521
- if ( ! empty( $modules ) ) {
522
- throw new Exception( "Error in factory framework. Your plugin configuration requires include of additional framework modules: " . implode( ',', $modules ) . "." );
523
  }
524
- }*/
525
-
526
- // ----------------------------------------------------------------------
527
- // Public methods
528
- // ----------------------------------------------------------------------
529
-
530
- public function newScriptList() {
531
- return new Wbcr_Factory412_ScriptList( $this );
532
- }
533
-
534
- public function newStyleList() {
535
- return new Wbcr_Factory412_StyleList( $this );
536
  }
537
  }
538
 
4
  exit;
5
  }
6
 
 
7
  /**
8
+ * Основной класс для создания плагина.
9
+ *
10
+ * Это основной класс плагина. который отвечает за подключение модулей фреймворка, линзирование, обновление,
11
+ * миграции разрабатываемого плагина. При создании нового плагина, вы должны создать основной класс реализующий
12
+ * функции плагина, этот класс будет наследовать текущий.
13
+ *
14
+ * Смотрите подробную инструкцию по созданию плагина и экземпляра основного класса в документации по созданию
15
+ * плагина для Wordpress.
16
+ *
17
+ * Документация по классу: https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/393052164
18
+ * Документация по созданию плагина: https://webcraftic.atlassian.net/wiki/spaces/CNCFC/pages/327828
19
+ *
20
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
21
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
22
  *
 
23
  * @since 1.0.0
24
  * @package factory-core
 
25
  *
26
  */
27
+ abstract class Wbcr_Factory424_Plugin extends Wbcr_Factory424_Base {
28
 
29
  /**
30
+ * Instance class Wbcr_Factory424_Request, required manages http requests
31
  *
32
+ * @see https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/390561806
33
+ * @var Wbcr_Factory424_Request
34
  */
35
  public $request;
36
 
37
  /**
38
+ * @see https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/393936924
39
+ * @var \WBCR\Factory_424\Premium\Provider
40
  */
41
  public $premium;
42
 
43
  /**
44
  * The Bootstrap Manager class
45
  *
46
+ * @var Wbcr_FactoryBootstrap425_Manager
47
  */
48
  public $bootstrap;
49
 
50
  /**
51
  * The Bootstrap Manager class
52
  *
53
+ * @var Wbcr_FactoryForms422_Manager
54
  */
55
  public $forms;
56
 
57
  /**
58
+ * Простой массив со списком зарегистрированных классов унаследованных от Wbcr_Factory424_Activator.
59
+ * Классы активации используются для упаковки набора функций, которые нужно выполнить во время
60
+ * активации плагина.
61
  *
62
+ * @var array[] Wbcr_Factory424_Activator
63
  */
64
  protected $activator_class = [];
65
 
66
  /**
67
+ * Ассоциативный массив со списком уже загруженных модулей фреймворка. Используется для того, чтобы
68
+ * проверить, каких модули уже были загружены, а какие еще нет.
69
  *
70
  * @var array
71
  */
72
  private $loaded_factory_modules = [];
73
 
74
  /**
75
+ * Ассоциативный массив со списком аддонов плагина. Аддоны плагина являются частью одного проекта,
76
+ * но не как отдельный плагин.
77
  *
78
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
79
+ * @since 4.2.0
80
+ * @var array
81
  */
82
+ private $loaded_plugin_components = [];
83
 
84
  /**
85
+ * The Adverts Manager class
86
+ *
87
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
88
+ * @since 4.1.9
89
+ * @var WBCR\Factory_Adverts_105\Base
90
+ */
91
+ private $adverts;
92
+
93
+ /**
94
+ * Инициализирует компоненты фреймворка и плагина.
95
  *
96
  * @since 1.0.0
97
  *
105
 
106
  parent::__construct( $plugin_path, $data );
107
 
108
+ $this->request = new Wbcr_Factory424_Request();
109
+ //$this->route = new Wbcr_Factory424_Route();
110
 
111
  // INIT PLUGIN FRAMEWORK MODULES
112
  // Framework modules should always be loaded first,
129
 
130
  // init actions
131
  $this->register_plugin_hooks();
 
132
 
133
+ // INIT PLUGIN COMPONENTS
134
+ $this->init_plugin_components();
135
+ }
136
 
137
  /**
138
+ * Устанавливает класс менеджер, которому плагин будет делегировать подключение ресурсов (картинок,
139
+ * скриптов, стилей) фреймворка.
140
+ *
141
+ * @param Wbcr_FactoryBootstrap425_Manager $bootstrap
142
  */
143
+ public function setBootstap( Wbcr_FactoryBootstrap425_Manager $bootstrap ) {
144
  $this->bootstrap = $bootstrap;
145
  }
146
 
147
  /**
148
+ * Устанавливает класс менеджер, которому будет делегирована работа с html формами фреймворка.
149
+ *
150
+ * @param Wbcr_FactoryForms422_Manager $forms
151
  */
152
+ public function setForms( Wbcr_FactoryForms422_Manager $forms ) {
153
  $this->forms = $forms;
154
  }
155
 
156
  /**
157
+ * Устанавливает класс менеджер, которому будет делегирована работа с объявлениями в Wordpress
158
+ *
159
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
160
+ * @since 4.1.9
161
+ */
162
+ public function set_adverts_manager( $class_name ) {
163
+ if ( empty( $this->adverts ) && $this->render_adverts ) {
164
+ $this->adverts = new $class_name( $this, $this->adverts_settings );
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Устанавливает класс провайдера лицензий
170
+ *
171
+ * С помощью этого класса, мы проверяем валидность лицензий и получаем дополнительную информацию
172
+ * о лицензии и ее покупателе. Класс используется в премиум менеджере.
173
+ *
174
+ * @since 4.1.6 - Добавлен
175
+ *
176
+ * @param string $name Имя провайдер
177
+ * @param string $class_name Имя класса провайдера
178
+ */
179
+ public function set_license_provider( $name, $class_name ) {
180
+ if ( ! isset( WBCR\Factory_424\Premium\Manager::$providers[ $name ] ) ) {
181
+ WBCR\Factory_424\Premium\Manager::$providers[ $name ] = $class_name;
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Регистрируем класс репозитория
187
+ *
188
+ * С помощью этого класса мы реализиуем доставку и откат обновлений плагина, на сайт пользователя.
189
+ * Скачиваение премиум версий происходит по защенному каналу. Класс используется в менеджере обновлений.
190
+ *
191
+ * @since 4.1.7 - Добавлен
192
+ *
193
+ * @param string $name Имя репозитория
194
+ * @param string $class_name Имя класса репозитория
195
  */
196
+ public function set_update_repository( $name, $class_name ) {
197
+ if ( ! isset( WBCR\Factory_424\Updates\Upgrader::$repositories[ $name ] ) ) {
198
+ WBCR\Factory_424\Updates\Upgrader::$repositories[ $name ] = $class_name;
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Позволяет получить экземпляр менеджера объявления
204
+ *
205
+ * Доступен глобально через метод app(), чаще всего используется для создания точек для ротации
206
+ * рекламных объявлений.
207
+ *
208
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
209
+ * @since 1.1
210
+ * @return \WBCR\Factory_Adverts_105\Base
211
+ */
212
+ public function get_adverts_manager() {
213
+ return $this->adverts;
214
+ }
215
+
216
+ /**
217
+ * Устанавливает текстовый домен для плагина. Текстовый домен берется из заголовка входного
218
+ * файла плагина.
219
+ *
220
+ * @since 4.0.8 - Добавлен
221
+ *
222
+ * @see https://codex.wordpress.org/I18n_for_WordPress_Developers
223
+ * @see https://webcraftic.atlassian.net/wiki/spaces/CNCFC/pages/327828 - документация по входному файлу
224
+ */
225
+ public function set_text_domain() {
226
  if ( empty( $this->plugin_text_domain ) ) {
227
  return;
228
  }
236
  }
237
  }
238
 
239
+ public function newScriptList() {
240
+ return new Wbcr_Factory424_ScriptList( $this );
241
+ }
242
+
243
+ public function newStyleList() {
244
+ return new Wbcr_Factory424_StyleList( $this );
245
+ }
246
+
247
  /**
248
+ * Все страницы плагина создаются через специальную обертку, за которую отвечает модуль
249
+ * фреймворка pages. Разработчик создает собственный класс, унаследованный от
250
+ * Wbcr_FactoryPages424_AdminPage, а затем регистрирует его через этот метод.
251
+ * Метод выполняет подключение класса страницы и регистрирует его в модуле фреймворка
252
+ * pages.
253
+ *
254
+ * Больше информации о создании и регистрации страниц, вы можете узнать из документации по созданию
255
+ * страниц плагина.
256
+ *
257
+ * @see https://webcraftic.atlassian.net/wiki/spaces/CNCFC/pages/222887949 - документация по созданию страниц
258
+ *
259
+ * @param string $class_name Имя регистрируемого класса страницы. Пример: WCL_Page_Name.
260
+ * Регистрируемый класс должен быть унаследован от класса Wbcr_FactoryPages424_AdminPage.
261
+ * @param string $file_path Абсолютный путь к файлу с классом страницы.
262
  *
263
  * @throws Exception
264
  */
278
  throw new Exception( 'A class with this name {' . $class_name . '} does not exist.' );
279
  }
280
 
281
+ if ( ! class_exists( 'Wbcr_FactoryPages424' ) ) {
282
+ throw new Exception( 'The factory_pages_424 module is not included.' );
283
  }
284
 
285
+ Wbcr_FactoryPages424::register( $this, $class_name );
286
  }
287
 
288
  /**
289
+ * Произвольные типы записей в плагине, создаются через специальную обертку, за которую отвечает
290
+ * модуль фреймворка types. Разработчик создает собственный класс, унаследованный от
291
+ * Wbcr_FactoryTypes000_Type, а затем регистрирует его через этот метод. Метод выполняет
292
+ * подключение класса с новым типом записи и регистрирует его в модуле фреймворка types. *
293
+ *
294
+ * @param string $class_name Имя регистрируемого класса страницы. Пример: WCL_Type_Name.
295
+ * Регистрируемый класс должен быть унаследован от класса Wbcr_FactoryTypes000_Type.
296
+ * @param string $file_path Абсолютный путь к файлу с классом страницы.
297
  *
298
  * @throws Exception
299
+ * @deprecated 4.1.7 You cannot use it!
300
  */
301
  public function registerType( $class_name, $file_path ) {
302
+ throw new Exception( 'As of factory core module 4.1.7, the "registerType" method is deprecated. You cannot use it!' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  }
304
 
305
  /**
329
  /**
330
  * @since 4.1.1 - change hook name
331
  */
332
+ if ( apply_filters( "wbcr/factory_424/cancel_plugin_activation_{$this->plugin_name}", false ) ) {
333
  return;
334
  }
335
 
336
  /**
337
+ * wbcr_factory_424_plugin_activation
338
+ *
339
  * @since 4.1.1 - deprecated
340
  */
341
+ wbcr_factory_424_do_action_deprecated( 'wbcr_factory_424_plugin_activation', [
342
  $this
343
  ], '4.1.1', "wbcr/factory/plugin_activation" );
344
 
345
  /**
346
+ * wbcr/factory/plugin_activation
347
+ *
348
+ * @since 4.1.2 - deprecated
349
+ */
350
+ wbcr_factory_424_do_action_deprecated( 'wbcr/factory/plugin_activation', [
351
+ $this
352
+ ], '4.1.2', "wbcr/factory/before_plugin_activation" );
353
+
354
+ /**
355
+ * wbcr/factory/before_plugin_activation
356
+ *
357
+ * @since 4.1.2 - added
358
  */
359
+ do_action( 'wbcr/factory/before_plugin_activation', $this );
360
 
361
  /**
362
+ * # wbcr/factory/plugin_{$this->plugin_name}_activation
363
+ *
364
+ * @since 4.1.2 - deprecated
365
+ */
366
+ wbcr_factory_424_do_action_deprecated( "wbcr/factory/plugin_{$this->plugin_name}_activation", [
367
+ $this
368
+ ], '4.1.2', "wbcr/factory/before_plugin_{$this->plugin_name}_activation" );
369
+
370
+ /**
371
+ * wbcr_factory_424_plugin_activation_' . $this->plugin_name
372
+ *
373
  * @since 4.1.1 - deprecated
374
  */
375
+ wbcr_factory_424_do_action_deprecated( 'wbcr_factory_424_plugin_activation_' . $this->plugin_name, [
376
  $this
377
+ ], '4.1.1', "wbcr/factory/before_plugin_{$this->plugin_name}_activation" );
378
 
379
  /**
380
+ * wbcr/factory/plugin_{$this->plugin_name}_activation
381
+ *
382
+ * @since 4.1.2 - added
383
  */
384
+ do_action( "wbcr/factory/plugin_{$this->plugin_name}_activation", $this );
385
 
386
  if ( ! empty( $this->activator_class ) ) {
387
  foreach ( (array) $this->activator_class as $activator_class ) {
389
  $activator->activate();
390
  }
391
  }
392
+
393
+ /**
394
+ * @since 4.1.2 - added
395
+ */
396
+ do_action( 'wbcr/factory/plugin_activated', $this );
397
+
398
+ /**
399
+ * @since 4.1.2 - added
400
+ */
401
+ do_action( "wbcr/factory/plugin_{$this->plugin_name}_activated", $this );
402
+ }
403
+
404
+ /**
405
+ * It's invoked on plugin deactionvation. Don't excite it directly.
406
+ *
407
+ * @since 1.0.0
408
+ * @return void
409
+ */
410
+ public function deactivation_hook() {
411
+
412
+ /**
413
+ * @since 4.1.1 - change hook name
414
+ */
415
+ if ( apply_filters( "wbcr/factory_424/cancel_plugin_deactivation_{$this->plugin_name}", false ) ) {
416
+ return;
417
+ }
418
+
419
+ /**
420
+ * wbcr_factory_424_plugin_deactivation
421
+ *
422
+ * @since 4.1.1 - deprecated
423
+ */
424
+ wbcr_factory_424_do_action_deprecated( 'wbcr_factory_424_plugin_deactivation', [
425
+ $this
426
+ ], '4.1.1', "wbcr/factory/plugin_deactivation" );
427
+
428
+ /**
429
+ * wbcr/factory/plugin_deactivation
430
+ *
431
+ * @since 4.1.2 - deprecated
432
+ */
433
+ wbcr_factory_424_do_action_deprecated( 'wbcr/factory/plugin_deactivation', [
434
+ $this
435
+ ], '4.1.2', "wbcr/factory/before_plugin_deactivation" );
436
+
437
+ /**
438
+ * wbcr/factory/plugin_deactivation
439
+ *
440
+ * @since 4.1.2 - added
441
+ */
442
+ do_action( 'wbcr/factory/plugin_deactivation', $this );
443
+
444
+ /**
445
+ * wbcr_factory_424_plugin_deactivation_ . $this->plugin_name
446
+ *
447
+ * @since 4.1.1 - deprecated
448
+ */
449
+ wbcr_factory_424_do_action_deprecated( 'wbcr_factory_424_plugin_deactivation_' . $this->plugin_name, [
450
+ $this
451
+ ], '4.1.1', "wbcr/factory/before_plugin_{$this->plugin_name}_deactivation" );
452
+
453
+ /**
454
+ * wbcr/factory/plugin_{$this->plugin_name}_deactivation
455
+ *
456
+ * @since 4.1.2 - deprecated
457
+ */
458
+ wbcr_factory_424_do_action_deprecated( "wbcr/factory/plugin_{$this->plugin_name}_deactivation", [
459
+ $this
460
+ ], '4.1.2', "wbcr/factory/before_plugin_{$this->plugin_name}_deactivation" );
461
+
462
+ /**
463
+ * @since 4.1.2 - added
464
+ */
465
+ do_action( "wbcr/factory/before_plugin_{$this->plugin_name}_deactivation" );
466
+
467
+ if ( ! empty( $this->activator_class ) ) {
468
+ foreach ( (array) $this->activator_class as $activator_class ) {
469
+ $activator = new $activator_class( $this );
470
+ $activator->deactivate();
471
+ }
472
+ }
473
+
474
+ /**
475
+ * @since 4.1.2 - added
476
+ */
477
+ do_action( 'wbcr/factory/plugin_deactivated', $this );
478
+
479
+ /**
480
+ * @since 4.1.2 - added
481
+ */
482
+ do_action( "wbcr/factory/plugin_{$this->plugin_name}_deactivated", $this );
483
  }
484
 
485
  /**
492
  * @throws Exception
493
  */
494
  public function getPluginPageUrl( $page_id, $args = [] ) {
495
+ if ( ! class_exists( 'Wbcr_FactoryPages424' ) ) {
496
+ throw new Exception( 'The factory_pages_424 module is not included.' );
497
  }
498
 
499
  if ( ! is_admin() ) {
502
  return null;
503
  }
504
 
505
+ return Wbcr_FactoryPages424::getPageUrl( $this, $page_id, $args );
506
  }
507
 
 
508
  /**
509
  * Загружает аддоны для плагина, как часть проекта, а не как отдельный плагин
510
  *
511
+ * @throws \Exception
 
 
 
 
 
 
 
512
  */
513
+ private function init_plugin_components() {
514
+
515
+ $load_plugin_components = $this->get_load_plugin_components();
516
+
517
+ if ( empty( $load_plugin_components ) || ! is_array( $load_plugin_components ) ) {
518
  return;
519
  }
520
 
521
+ foreach ( $load_plugin_components as $component_ID => $component ) {
522
+ if ( ! isset( $this->loaded_plugin_components[ $component_ID ] ) ) {
 
 
 
 
523
 
524
+ if ( ! isset( $component['autoload'] ) || ! isset( $component['plugin_prefix'] ) ) {
525
+ throw new Exception( sprintf( "Component %s cannot be loaded, you must specify the path to the component autoload file and plugin prefix!", $component_ID ) );
526
  }
527
 
528
+ $prefix = rtrim( $component['plugin_prefix'], '_' ) . '_';
529
 
530
+ if ( defined( $prefix . 'PLUGIN_ACTIVE' ) ) {
531
+ continue;
532
+ }
533
 
534
+ $autoload_file = trailingslashit( $this->get_paths()->absolute ) . $component['autoload'];
 
535
 
536
+ if ( ! file_exists( $autoload_file ) ) {
537
+ throw new Exception( sprintf( "Component %s autoload file not found!", $component_ID ) );
538
+ }
539
 
540
+ require_once( $autoload_file );
541
+
542
+ if ( defined( $prefix . 'PLUGIN_ACTIVE' ) && class_exists( $prefix . 'Plugin' ) ) {
543
+ $this->loaded_plugin_components[ $component_ID ] = [
544
+ 'plugin_dir' => constant( $prefix . 'PLUGIN_DIR' ),
545
+ 'plugin_url' => constant( $prefix . 'PLUGIN_URL' ),
546
+ 'plugin_base' => constant( $prefix . 'PLUGIN_BASE' ),
547
+ 'plugin_version' => constant( $prefix . 'PLUGIN_VERSION' )
548
+ ];
549
+
550
+ /**
551
+ * Оповещает внешние приложения, что компонент плагина был загружен
552
+ *
553
+ * @param array $load_plugin_components Информация о загруженном компоненте
554
+ * @param string $plugin_name Имя плагина
555
+ */
556
+ do_action( "wbcr/factory/component_{$component_ID}_loaded", $this->loaded_plugin_components[ $component_ID ], $this->getPluginName() );
557
+ } else {
558
+ throw new Exception( sprintf( "Сomponent %s does not meet development standards!", $component_ID ) );
559
  }
560
  }
561
  }
596
  /**
597
  * @since 4.1.1 - deprecated
598
  */
599
+ wbcr_factory_424_do_action_deprecated( 'wbcr_factory_424_core_modules_loaded-' . $this->plugin_name, [], '4.1.1', "wbcr/factory_424/modules_loaded-" . $this->plugin_name );
600
 
601
  /**
602
  * @since 4.1.1 - add
603
  */
604
+ do_action( 'wbcr/factory_424/modules_loaded-' . $this->plugin_name );
605
  }
606
 
607
 
615
  add_action( 'plugins_loaded', [ $this, 'set_text_domain' ] );
616
 
617
  if ( is_admin() ) {
618
+ add_filter( 'wbcr_factory_424_core_admin_allow_multisite', '__return_true' );
619
 
620
  register_activation_hook( $this->get_paths()->main_file, [ $this, 'activation_hook' ] );
621
  register_deactivation_hook( $this->get_paths()->main_file, [ $this, 'deactivation_hook' ] );
622
  }
623
  }
624
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
625
  /**
626
  * Инициализируем миграции плагина
627
  *
630
  * @throws Exception
631
  */
632
  protected function init_plugin_migrations() {
633
+ new WBCR\Factory_424\Migrations( $this );
634
  }
635
 
636
  /**
640
  * @return void
641
  */
642
  protected function init_plugin_notices() {
643
+ new Wbcr\Factory_424\Notices( $this );
644
  }
645
 
646
  /**
647
+ * Создает нового рабочего для проверки обновлений и апгрейда текущего плагина.
648
  *
649
  * @since 4.1.1
650
  *
655
  */
656
  protected function init_plugin_updates() {
657
  if ( $this->has_updates ) {
658
+ new WBCR\Factory_424\Updates\Upgrader( $this );
659
  }
660
  }
661
 
677
  }
678
 
679
  // Создаем экземляр премиум менеджера, мы сможем к нему обращаться глобально.
680
+ $this->premium = WBCR\Factory_424\Premium\Manager::instance( $this, $this->license_settings );
681
 
682
  // Подключаем премиум апгрейдер
683
  if ( isset( $this->license_settings['has_updates'] ) && $this->license_settings['has_updates'] ) {
684
+ new WBCR\Factory_424\Updates\Premium_Upgrader( $this );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
685
  }
 
 
 
 
 
 
 
 
 
 
 
 
686
  }
687
  }
688
 
libs/factory/core/includes/class-factory-plugin-base.php CHANGED
@@ -5,110 +5,166 @@ if ( ! defined( 'ABSPATH' ) ) {
5
  }
6
 
7
  /**
8
- * Базовый класс
9
  *
10
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
11
- * @link https://webcraftic.com
12
- * @copyright (c) 2018 Webraftic Ltd
13
- * @since 4.0.8
 
 
 
 
 
14
  */
15
- class Wbcr_Factory412_Base {
16
-
17
- use WBCR\Factory_412\Options;
18
-
19
  /**
20
- * Namespace Prefix among Wordpress Options
 
 
 
 
 
21
  *
22
  * @var string
23
  */
24
  protected $prefix;
25
-
26
  /**
27
- * Plugin title
 
 
28
  *
29
  * @var string
30
  */
31
  protected $plugin_title;
32
-
33
  /**
34
- * Plugin name. Valid characters [A-z0-9_-]
 
 
 
35
  *
36
  * @var string
37
  */
38
  protected $plugin_name;
39
-
40
  /**
41
- * Plugin version. Valid characters [0-9.]
42
- * Example: 1.4.5
43
  *
44
  * @var string
45
  */
46
  protected $plugin_version;
47
-
48
  /**
 
 
 
 
49
  * @since 4.1.1
50
  * @var string
51
  */
52
  protected $plugin_text_domain;
53
-
54
  /**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  * @var array
56
  */
57
  protected $support_details;
58
-
59
  /**
 
 
 
 
 
60
  * @var bool
61
  */
62
  protected $has_updates = false;
63
-
64
  /**
65
- * Optional. Settings for plugin updates from a remote repository.
 
 
 
 
66
  *
67
- * @var array {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  *
69
- * Update settings for free plugin.
 
 
 
 
70
  *
71
- * {type} string repository Type where we download plugin updates
72
- * (wordpress | freemius | other)
73
  *
74
- * {type} string slug Plugin slug
 
 
75
  *
76
- * {type} array rollback Settings for rollback to the previous version of
77
- * the plugin, will gain only one option prev_stable_version,
78
- * you must specify previous version of the plugin *
79
- * }
80
  */
81
- protected $updates_settings = array();
82
-
83
  /**
84
- * Does plugin have a premium version?
 
 
 
 
85
  *
 
 
86
  * @var bool
87
  */
88
- protected $has_premium = false;
89
-
90
  /**
91
- * Optional. Settings for download, update and upgrage to premium of the plugin.
92
  *
93
- * @var array {
94
- * {type} string license_provider Store where premium plugin was sold (freemius | codecanyon | template_monster)
95
- * {type} string plugin_id Plugin id, only for freemius
96
- * {type} string public_key Plugin public key, only for freemius
97
- * {type} string slug Plugin name, only for freemius
98
- *
99
- * {type} array premium_plugin_updates {
100
- * Update settings for free plugin.
101
- *
102
- * {type} array rollback Settings for rollback to the previous version of
103
- * the plugin, will gain only one option prev_stable_version,
104
- * you must specify previous version of the plugin *
105
- * }
106
- * }
107
  */
108
- protected $license_settings = array();
109
-
110
  /**
111
- * Required. Framework modules needed to develop a plugin.
 
 
112
  *
113
  * @var array {
114
  * Array with information about the loadable module
@@ -120,85 +176,133 @@ class Wbcr_Factory412_Base {
120
  * all - Module will be loaded everywhere
121
  * }
122
  */
123
- protected $load_factory_modules = array(
124
- array( 'libs/factory/bootstrap', 'factory_bootstrap_412', 'admin' ),
125
- array( 'libs/factory/forms', 'factory_forms_412', 'admin' ),
126
- array( 'libs/factory/pages', 'factory_pages_412', 'admin' ),
127
- );
128
-
129
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  /**
131
- * @var \WBCR\Factory_412\Entities\Support
 
 
 
 
132
  */
133
  protected $support;
134
-
135
  /**
136
- * @var \WBCR\Factory_412\Entities\Paths
 
 
 
 
137
  */
138
  protected $paths;
139
-
140
  /**
 
 
141
  * @var string
142
  */
143
  private $plugin_file;
144
-
145
  /**
 
 
 
146
  * @var array
147
  */
148
  private $plugin_data;
149
-
150
  /**
 
 
 
 
 
151
  * @since 4.1.1 - добавил две сущности support, paths. Удалил свойства, plugin_build
152
  * plugin_assembly, main_file, plugin_root, relative_path, plugin_url
153
  * @since 4.0.8 - добавлена дополнительная логика
154
  *
155
  * @param string $plugin_file
156
- * @param array $data
157
  *
158
  * @throws Exception
159
  */
160
  public function __construct( $plugin_file, $data ) {
161
  $this->plugin_file = $plugin_file;
162
  $this->plugin_data = $data;
163
-
164
  foreach ( (array) $data as $option_name => $option_value ) {
165
  if ( property_exists( $this, $option_name ) ) {
166
  $this->$option_name = $option_value;
167
  }
168
  }
169
-
170
  if ( empty( $this->prefix ) || empty( $this->plugin_name ) || empty( $this->plugin_title ) || empty( $this->plugin_version ) || empty( $this->plugin_text_domain ) ) {
171
  throw new Exception( 'One of the required attributes has not been passed (prefix, plugin_title, plugin_name, plugin_version, plugin_text_domain).' );
172
  }
173
-
174
- $this->support = new \WBCR\Factory_412\Entities\Support( $this->support_details );
175
- $this->paths = new \WBCR\Factory_412\Entities\Paths( $plugin_file );
176
-
177
  // used only in the module 'updates'
178
  $this->plugin_slug = ! empty( $this->plugin_name ) ? $this->plugin_name : basename( $plugin_file );
179
  }
180
-
181
  /**
182
- * @param $name
 
 
 
 
 
183
  *
184
- * @return string|null
185
  */
186
  public function __get( $name ) {
187
-
188
- $deprecated_props = array(
189
  'plugin_build',
190
  'plugin_assembly',
191
  'main_file',
192
  'plugin_root',
193
  'relative_path',
194
  'plugin_url'
195
- );
196
-
197
  if ( in_array( $name, $deprecated_props ) ) {
198
  $deprecated_message = 'In version 4.1.1 of the Factory framework, the class properties ';
199
  $deprecated_message .= '(' . implode( ',', $deprecated_props ) . ')';
200
  $deprecated_message .= 'have been removed. To get plugin paths, use the new paths property.' . PHP_EOL;
201
-
202
  $backtrace = debug_backtrace();
203
  if ( ! empty( $backtrace ) && isset( $backtrace[1] ) ) {
204
  $deprecated_message .= 'BACKTRACE:(';
@@ -207,9 +311,9 @@ class Wbcr_Factory412_Base {
207
  $deprecated_message .= 'Line: ' . $backtrace[1]['line'];
208
  $deprecated_message .= ')';
209
  }
210
-
211
  _deprecated_argument( __METHOD__, '4.1.1', $deprecated_message );
212
-
213
  switch ( $name ) {
214
  case 'plugin_build':
215
  return null;
@@ -231,28 +335,32 @@ class Wbcr_Factory412_Base {
231
  break;
232
  }
233
  }
234
-
235
  return null;
236
  }
237
-
238
  /**
239
- * @param $name
240
- * @param $arguments
 
 
 
 
241
  *
242
  * @return stdClass|null
243
  * @throws Exception
244
  */
245
  public function __call( $name, $arguments ) {
246
-
247
- $deprecated_methods = array(
248
  'getPluginBuild',
249
  'getPluginAssembly',
250
  'getPluginPathInfo'
251
- );
252
-
253
  if ( in_array( $name, $deprecated_methods ) ) {
254
  $deprecated_message = 'In version 4.1.1 of the Factory framework, methods (' . implode( ',', $deprecated_methods ) . ') have been removed.';
255
-
256
  $backtrace = debug_backtrace();
257
  if ( ! empty( $backtrace ) && isset( $backtrace[1] ) ) {
258
  $deprecated_message .= 'BACKTRACE:(';
@@ -261,61 +369,87 @@ class Wbcr_Factory412_Base {
261
  $deprecated_message .= 'Line: ' . $backtrace[1]['line'];
262
  $deprecated_message .= ')';
263
  }
264
-
265
  _deprecated_argument( __METHOD__, '4.1.1', $deprecated_message );
266
-
267
  if ( 'getPluginPathInfo' == $name ) {
268
  $object = new stdClass;
269
-
270
  $object->main_file = $this->get_paths()->main_file;
271
  $object->plugin_root = $this->get_paths()->absolute;
272
  $object->relative_path = $this->get_paths()->basename;
273
  $object->plugin_url = $this->get_paths()->url;
274
-
275
  return $object;
276
  }
277
  }
278
-
279
  throw new Exception( "Method {$name} does not exist" );
280
  }
281
-
282
  /**
283
- * @return bool
 
 
 
284
  */
285
  public function has_premium() {
286
  return $this->has_premium;
287
  }
288
-
289
  /**
290
- * @return string
 
 
291
  */
292
  public function getPluginTitle() {
293
  return $this->plugin_title;
294
  }
295
-
296
  /**
297
- * @return string
 
 
298
  */
299
  public function getPrefix() {
300
  return $this->prefix;
301
  }
302
-
303
  /**
304
- * @return string
 
 
305
  */
306
  public function getPluginName() {
307
  return $this->plugin_name;
308
  }
309
-
310
  /**
311
- * @return string
 
 
312
  */
313
  public function getPluginVersion() {
314
  return $this->plugin_version;
315
  }
316
-
 
 
 
 
 
 
 
 
 
 
 
317
  /**
318
- * @param $attr_name
 
 
 
 
319
  *
320
  * @return null
321
  */
@@ -323,85 +457,108 @@ class Wbcr_Factory412_Base {
323
  if ( isset( $this->plugin_data[ $attr_name ] ) ) {
324
  return $this->plugin_data[ $attr_name ];
325
  }
326
-
327
  return null;
328
  }
329
-
330
  /**
331
- * @return \WBCR\Factory_412\Entities\Support
 
 
332
  */
333
  public function get_support() {
334
  return $this->support;
335
  }
336
-
337
  /**
338
- * @return \WBCR\Factory_412\Entities\Paths
 
 
339
  */
340
  public function get_paths() {
341
  return $this->paths;
342
  }
343
-
344
  /**
345
- * @return object
 
 
346
  */
347
  public function getPluginInfo() {
348
  return (object) $this->plugin_data;
349
  }
350
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  /**
352
- * Активирован ли сайт в режиме мультисайтов и мы находимся в области суперадминистратора
353
- * TODO: Вынести метод в функции
 
 
354
  * @return bool
355
  */
356
  public function isNetworkAdmin() {
357
  return is_multisite() && is_network_admin();
358
  }
359
-
360
  /**
361
- * Активирован ли плагин для сети
362
- * TODO: Вынести метод в функции
363
- * @since 4.0.8
364
- * @return bool
365
  */
366
  public function isNetworkActive() {
367
  // Makes sure the plugin is defined before trying to use it
368
  if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
369
  require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
370
  }
371
-
372
  $activate = is_plugin_active_for_network( $this->get_paths()->basename );
373
-
374
  if ( ! $activate && $this->isNetworkAdmin() && isset( $_GET['action'] ) && $_GET['action'] == 'activate' ) {
375
- $is_activate_for_network = isset( $_GET['plugin_status'] ) && $_GET['plugin_status'] == 'all';
376
-
377
- if ( $is_activate_for_network ) {
378
- return true;
379
- }
380
  }
381
-
382
  return $activate;
383
  }
384
-
385
  /**
386
- * Получает список активных сайтов сети
387
- * TODO: Вынести метод в функции
388
  * @since 4.0.8
389
  * @return array|int
390
  */
391
- public function getActiveSites( $args = array( 'archived' => 0, 'mature' => 0, 'spam' => 0, 'deleted' => 0 ) ) {
392
  global $wp_version;
393
-
394
  if ( version_compare( $wp_version, '4.6', '>=' ) ) {
395
  return get_sites( $args );
396
  } else {
397
- $converted_array = array();
398
-
399
  $sites = wp_get_sites( $args );
400
-
401
  if ( empty( $sites ) ) {
402
  return $converted_array;
403
  }
404
-
405
  foreach ( (array) $sites as $key => $site ) {
406
  $obj = new stdClass();
407
  foreach ( $site as $attr => $value ) {
@@ -409,7 +566,7 @@ class Wbcr_Factory412_Base {
409
  }
410
  $converted_array[ $key ] = $obj;
411
  }
412
-
413
  return $converted_array;
414
  }
415
  }
5
  }
6
 
7
  /**
8
+ * Базовый класс для создания нового плагина. Полную реализацию класса смотрите в Wbcr_Factory424_Plugin
9
  *
10
+ * Документация по классу: https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/392724484
11
+ * Документация по созданию плагина: https://webcraftic.atlassian.net/wiki/spaces/CNCFC/pages/327828
12
+ * Репозиторий: https://github.com/alexkovalevv
13
+ *
14
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
15
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
16
+ *
17
+ * @since 1.0.0
18
+ * @package factory-core
19
  */
20
+ class Wbcr_Factory424_Base {
21
+
22
+ use WBCR\Factory_424\Options;
23
+
24
  /**
25
+ * Обязательное свойство. Префикс, используется для создания пространство имен.
26
+ * Чаще всего используется на именования опций в базе данных. Также может быть
27
+ * использован для именования полей html форм, создания уникальных имен, хуков.
28
+ * Пример: wrio_
29
+ *
30
+ * Для префикса всегда используете нижнее подчеркивание справа!
31
  *
32
  * @var string
33
  */
34
  protected $prefix;
35
+
36
  /**
37
+ * Обязательное свойство. Заголовок плагина. Используете в интерфейсе плагина,
38
+ * может быть использован в уведомлениях для администратора, чтобы пользователь
39
+ * мог понять, с каким плагином он ведет коммуникацию. Пример: Robin image optimizer
40
  *
41
  * @var string
42
  */
43
  protected $plugin_title;
44
+
45
  /**
46
+ * Обязательное свойство. Имя плагина. Используется аналогично префиксу, но с небольшим
47
+ * отличием. Имя плагина имеет человеку понятную строку, которую можно использовать в
48
+ * именовании хуков, созданию условной логики. Допустимые символы [A-z0-9_].
49
+ * Пример: wbcr_clearfy
50
  *
51
  * @var string
52
  */
53
  protected $plugin_name;
54
+
55
  /**
56
+ * Обязательное свойство. Версия плагина в формате 0.0.0. Допустимые символы [0-9.]
 
57
  *
58
  * @var string
59
  */
60
  protected $plugin_version;
61
+
62
  /**
63
+ * Обязательное свойство. Текстовый домен плагина, используется для подключения файлов
64
+ * переводов. Рекомендуется использовать slug плагина, идентичный slug в репозитории
65
+ * Wordpress.org
66
+ *
67
  * @since 4.1.1
68
  * @var string
69
  */
70
  protected $plugin_text_domain;
71
+
72
  /**
73
+ * Обязательное свойство. Информация для поддержки клиента. Для начала работы плагина,
74
+ * достаточно только указать адрес лендинга в атрибут url. На лендинге должны быть
75
+ * созданы страницы features, pricing, support, docs. Если страницы (features, pricing,
76
+ * support, docs) не могут иметь такие же адреса, вы можете наложить карту адресов в
77
+ * атрибуте pages_map. К примеру: я создал страницу "Pro Features" и она имеет адрес
78
+ * {site}/premium-features, для pages_map в атрибуте features, я указал, что адрес
79
+ * страницы со списком функций имеет слаг premium-features. Теперь плагин будет понимать,
80
+ * что адрес страницы со списком функций будет таким:
81
+ * https://robin-image-optimizer.webcraftic.com/premium-features.
82
+ *
83
+ * Это свойство заполняется для того, чтобы в процессе разработки вы могли использовать
84
+ * экземпляр класса \WBCR\Factory_424\Entities\Support, для получения информации о сайте плагина.
85
+ * Тем самым вы избавляете себя от жесткого прописывания ссылок на лендинг плагина и
86
+ * можете изменить все ссылки в одном месте.
87
+ *
88
  * @var array
89
  */
90
  protected $support_details;
91
+
92
  /**
93
+ * Включение/отключение обновлений для бесплатного плагина. Если вашего плагина нет в репозитори
94
+ * Wordpress.org, вы можете включить собственный режим обновлений, например через GitHub или
95
+ * собственный репозиторий. Если установлено true, плагин будет проверять наличие обновлений
96
+ * для этого плагина.
97
+ *
98
  * @var bool
99
  */
100
  protected $has_updates = false;
101
+
102
  /**
103
+ * Настройка обновлений для бесплатного плагина. Если вы хотите настроить обновления для
104
+ * бесплатного плагина через собственный репозиторий (например: github), вам нужно указать имя
105
+ * репозитория и slug плагина. Slug может быть идентичен имени репозитория в github. Для Wordpress.org
106
+ * эти настройки не обязательны, так как в wordpress ядре есть встроенные функции для обновлений
107
+ * плагинов и тем.
108
  *
109
+ * @var array
110
+ */
111
+ protected $updates_settings = [];
112
+
113
+ /**
114
+ * Включение/отключение премиум версии для плагина. Если вы создаете бесплатный плагин и хотите
115
+ * реализовать для него премиум версию, вам нужно начать с этого свойства. Если свойство установлено,
116
+ * как true, при инициализации плагина будут подключены функции лицензирования, проверки обновлений
117
+ * для премиум версии.
118
+ *
119
+ * @var bool
120
+ */
121
+ protected $has_premium = false;
122
+
123
+ /**
124
+ * Настройки лицензирования
125
  *
126
+ * Лицензирование плагина может быть реализовано для любого провайдера,
127
+ * к примеру: freemius, codecanyon, templatemonster, вам нужно указать только настройки для
128
+ * взаимодействия с выбранным вами провайдером. Каждая реализация провайдера лицензий может иметь
129
+ * индивидуальный настройки, в этом примере приведены настройки для freemius провайдера
130
+ * WBCR\Factory_424\Premium\Provider > WBCR\Factory_Freemius_112\Premium\Provider
131
  *
132
+ * На текущий момент существует только реализация для freemius провайдера.
 
133
  *
134
+ * Для премиум плагина вы должны также указать настройки обновлений. Атрибут has_updates
135
+ * включает/отключает обновления для премиум плагина, в атрибуте updates_settings вы указываете
136
+ * дополнительные настройки обновлений.
137
  *
138
+ * @var array
 
 
 
139
  */
140
+ protected $license_settings = [];
141
+
142
  /**
143
+ * Переключатель внутренней рекламы в плагине
144
+ *
145
+ * Если установить true, то плагин будет показывать рекламу компании в интерфейсе Wordpress.
146
+ * Рекламный модуль может отображать рекламу внутри инрефейса плагина, на странице dashboard
147
+ * и создавать сквозные уведомления на всех страницах админ панели Wordpress.
148
  *
149
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
150
+ * @since 4.1.9
151
  * @var bool
152
  */
153
+ protected $render_adverts = false;
154
+
155
  /**
156
+ * Настройки внутренней рекламы компании
157
  *
158
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
159
+ * @since 4.1.9
160
+ * @var array
 
 
 
 
 
 
 
 
 
 
 
161
  */
162
+ protected $adverts_settings = [];
163
+
164
  /**
165
+ * Обязательное свойство. Подключаемые модули фреймворка.
166
+ *
167
+ * Модули фреймворка позволяют расширять его функциональность.
168
  *
169
  * @var array {
170
  * Array with information about the loadable module
176
  * all - Module will be loaded everywhere
177
  * }
178
  */
179
+ protected $load_factory_modules = [
180
+ [ 'libs/factory/bootstrap', 'factory_bootstrap_425', 'admin' ],
181
+ [ 'libs/factory/forms', 'factory_forms_422', 'admin' ],
182
+ [ 'libs/factory/pages', 'factory_pages_424', 'admin' ],
183
+ ];
184
+
185
+ /**
186
+ * Не обязательное свойство. Список подключаемых компонентов плагина.
187
+ *
188
+ * Компоненты плагина, это независимые плагины, которые расширяют возможности текущего плагина.
189
+ * Вы должны указать файл для автозагрузки компонента и префикс плагина, чтобы фреймворк
190
+ * мог обращаться к классам и константам компонентов.
191
+ *
192
+ *
193
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
194
+ * @since 4.2.0 Добавлен
195
+ * @var array Пример данных
196
+ * array(
197
+ * 'component_ID' => array(
198
+ * 'autoload' => 'relative_path/autoload_filename.php',
199
+ * 'plugin_prefix' => 'WPRFX_'
200
+ * ),
201
+ * // Реальный пример
202
+ * 'cyrlitera' => array(
203
+ * 'autoload' => 'components/cyrlitera/clearfy.php',
204
+ * 'plugin_prefix' => 'WCTR_'
205
+ * ),
206
+ * )
207
+ */
208
+ protected $load_plugin_components = [];
209
+
210
+
211
  /**
212
+ * Экземпляр класса \WBCR\Factory_424\Entities\Support используется для получения информации
213
+ * о сайте плагина. Чаще всего используется для получения ссылки на страницу с тарифами или
214
+ * ссылки на форму обратной связи. Встроен механизм отслеживания по utm меткам.
215
+ *
216
+ * @var \WBCR\Factory_424\Entities\Support
217
  */
218
  protected $support;
219
+
220
  /**
221
+ * Экземпляр класса \WBCR\Factory_424\Entities\Paths используется для получения информации о
222
+ * путях плагина. Часто используется для получения путей или ссылок на место хранения плагина
223
+ * или его входного файла.
224
+ *
225
+ * @var \WBCR\Factory_424\Entities\Paths
226
  */
227
  protected $paths;
228
+
229
  /**
230
+ * Абсолютный путь к входному файлу плагина: C://server/site.dev/wp-content/plugins/plugin_name/plugin_name.php
231
+ *
232
  * @var string
233
  */
234
  private $plugin_file;
235
+
236
  /**
237
+ * Свойство хранит сырые настройки плагина, а также дополнительные настройки, которые не описаны
238
+ * в интерфейсе класса.
239
+ *
240
  * @var array
241
  */
242
  private $plugin_data;
243
+
244
  /**
245
+ * Конструктор:
246
+ * - Заполняет свойства класса из сырых данных плагина
247
+ * - Выполняет проверку на обязательные настройки
248
+ * - Инициализирует сущности support и paths
249
+ *
250
  * @since 4.1.1 - добавил две сущности support, paths. Удалил свойства, plugin_build
251
  * plugin_assembly, main_file, plugin_root, relative_path, plugin_url
252
  * @since 4.0.8 - добавлена дополнительная логика
253
  *
254
  * @param string $plugin_file
255
+ * @param array $data
256
  *
257
  * @throws Exception
258
  */
259
  public function __construct( $plugin_file, $data ) {
260
  $this->plugin_file = $plugin_file;
261
  $this->plugin_data = $data;
262
+
263
  foreach ( (array) $data as $option_name => $option_value ) {
264
  if ( property_exists( $this, $option_name ) ) {
265
  $this->$option_name = $option_value;
266
  }
267
  }
268
+
269
  if ( empty( $this->prefix ) || empty( $this->plugin_name ) || empty( $this->plugin_title ) || empty( $this->plugin_version ) || empty( $this->plugin_text_domain ) ) {
270
  throw new Exception( 'One of the required attributes has not been passed (prefix, plugin_title, plugin_name, plugin_version, plugin_text_domain).' );
271
  }
272
+
273
+ $this->support = new \WBCR\Factory_424\Entities\Support( $this->support_details );
274
+ $this->paths = new \WBCR\Factory_424\Entities\Paths( $plugin_file );
275
+
276
  // used only in the module 'updates'
277
  $this->plugin_slug = ! empty( $this->plugin_name ) ? $this->plugin_name : basename( $plugin_file );
278
  }
279
+
280
  /**
281
+ * При обновлении фреймворка, некоторые свойства класса были удалены. Однако плагины на старом
282
+ * фреймворке по прежнему используют удаленные свойства. С помощью этого магического метода мы
283
+ * добавляем совместимость со старыми плагинами, но при этом выводим предупреждение, что нужно
284
+ * обновить некоторые свойства.
285
+ *
286
+ * @param string $name Имя свойства класса.
287
  *
288
+ * @return mixed
289
  */
290
  public function __get( $name ) {
291
+
292
+ $deprecated_props = [
293
  'plugin_build',
294
  'plugin_assembly',
295
  'main_file',
296
  'plugin_root',
297
  'relative_path',
298
  'plugin_url'
299
+ ];
300
+
301
  if ( in_array( $name, $deprecated_props ) ) {
302
  $deprecated_message = 'In version 4.1.1 of the Factory framework, the class properties ';
303
  $deprecated_message .= '(' . implode( ',', $deprecated_props ) . ')';
304
  $deprecated_message .= 'have been removed. To get plugin paths, use the new paths property.' . PHP_EOL;
305
+
306
  $backtrace = debug_backtrace();
307
  if ( ! empty( $backtrace ) && isset( $backtrace[1] ) ) {
308
  $deprecated_message .= 'BACKTRACE:(';
311
  $deprecated_message .= 'Line: ' . $backtrace[1]['line'];
312
  $deprecated_message .= ')';
313
  }
314
+
315
  _deprecated_argument( __METHOD__, '4.1.1', $deprecated_message );
316
+
317
  switch ( $name ) {
318
  case 'plugin_build':
319
  return null;
335
  break;
336
  }
337
  }
338
+
339
  return null;
340
  }
341
+
342
  /**
343
+ * При обновлении фреймворка, некоторые методы класса были удалены. Однако плагины на старом фреймворке
344
+ * по прежнему используют удаленные методы. С помощью этого магического метода мы добавляем совместимость
345
+ * со старыми плагинами, но при этом выводим предупреждение, что нужно обновить некоторые методы.
346
+ *
347
+ * @param string $name Имя метода класса.
348
+ * @param array $arguments Массив аргументов метода класса.
349
  *
350
  * @return stdClass|null
351
  * @throws Exception
352
  */
353
  public function __call( $name, $arguments ) {
354
+
355
+ $deprecated_methods = [
356
  'getPluginBuild',
357
  'getPluginAssembly',
358
  'getPluginPathInfo'
359
+ ];
360
+
361
  if ( in_array( $name, $deprecated_methods ) ) {
362
  $deprecated_message = 'In version 4.1.1 of the Factory framework, methods (' . implode( ',', $deprecated_methods ) . ') have been removed.';
363
+
364
  $backtrace = debug_backtrace();
365
  if ( ! empty( $backtrace ) && isset( $backtrace[1] ) ) {
366
  $deprecated_message .= 'BACKTRACE:(';
369
  $deprecated_message .= 'Line: ' . $backtrace[1]['line'];
370
  $deprecated_message .= ')';
371
  }
372
+
373
  _deprecated_argument( __METHOD__, '4.1.1', $deprecated_message );
374
+
375
  if ( 'getPluginPathInfo' == $name ) {
376
  $object = new stdClass;
377
+
378
  $object->main_file = $this->get_paths()->main_file;
379
  $object->plugin_root = $this->get_paths()->absolute;
380
  $object->relative_path = $this->get_paths()->basename;
381
  $object->plugin_url = $this->get_paths()->url;
382
+
383
  return $object;
384
  }
385
  }
386
+
387
  throw new Exception( "Method {$name} does not exist" );
388
  }
389
+
390
  /**
391
+ * Проверяет, включен ли премиум для этого плагина или нет.
392
+ *
393
+ * @return bool Возвращает true, если премиум пакет включен для этого плагина.
394
+ * См. Wbcr_Factory424_Base::has_premium
395
  */
396
  public function has_premium() {
397
  return $this->has_premium;
398
  }
399
+
400
  /**
401
+ * Позволяет получить заголовок плагина.
402
+ *
403
+ * @return string Возвращает заголовок плагина. См. Wbcr_Factory424_Base::plugin_title
404
  */
405
  public function getPluginTitle() {
406
  return $this->plugin_title;
407
  }
408
+
409
  /**
410
+ * Позволяет получить префикс плагина.
411
+ *
412
+ * @return string Возвращает префикс плагина.См. Wbcr_Factory424_Base::prefix
413
  */
414
  public function getPrefix() {
415
  return $this->prefix;
416
  }
417
+
418
  /**
419
+ * Позволяет получить имя плагина.
420
+ *
421
+ * @return string Возвращает имя плагина. См. Wbcr_Factory424_Base::plugin_name
422
  */
423
  public function getPluginName() {
424
  return $this->plugin_name;
425
  }
426
+
427
  /**
428
+ * Позволяет получить версию плагина.
429
+ *
430
+ * @return string Возвращает версию плагина. См. Wbcr_Factory424_Base::plugin_version
431
  */
432
  public function getPluginVersion() {
433
  return $this->plugin_version;
434
  }
435
+
436
+ /**
437
+ * Позволяет получить список подключаемых к плагином компонентов
438
+ *
439
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
440
+ * @since 4.2.0
441
+ * @return array
442
+ */
443
+ public function get_load_plugin_components() {
444
+ return $this->load_plugin_components;
445
+ }
446
+
447
  /**
448
+ * Предоставляет доступ к сырым данным плагина. Может быть полезен, если вы хотите получить
449
+ * какие-то данные не описанные в интерфейсе этого плагина.
450
+ *
451
+ * @param string $attr_name Имя атрибута, который нужно получить. Идентично ключу в массиве
452
+ * Wbcr_Factory424_Base::plugin_data
453
  *
454
  * @return null
455
  */
457
  if ( isset( $this->plugin_data[ $attr_name ] ) ) {
458
  return $this->plugin_data[ $attr_name ];
459
  }
460
+
461
  return null;
462
  }
463
+
464
  /**
465
+ * Предоставляет доступ к экземпляру класса \WBCR\Factory_424\Entities\Support.
466
+ *
467
+ * @return \WBCR\Factory_424\Entities\Support
468
  */
469
  public function get_support() {
470
  return $this->support;
471
  }
472
+
473
  /**
474
+ * Предоставляет доступ к экземпляру класса \WBCR\Factory_424\Entities\Paths.
475
+ *
476
+ * @return \WBCR\Factory_424\Entities\Paths
477
  */
478
  public function get_paths() {
479
  return $this->paths;
480
  }
481
+
482
  /**
483
+ * Позволяет получить сырые данные плагина в виде объекта StdClass.
484
+ *
485
+ * @return object Возвращает объект с сырыми данными плагина. См. Wbcr_Factory424_Base::plugin_data
486
  */
487
  public function getPluginInfo() {
488
  return (object) $this->plugin_data;
489
  }
490
+
491
+ /**
492
+ * Проверяет права пользователя
493
+ *
494
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
495
+ * @since 4.2.0 Добавлен
496
+ * @return bool
497
+ */
498
+ public function current_user_can( $capability = 'manage_options' ) {
499
+ // Просмотр страниц: read_pages
500
+ // Просмотр уведомлений: read_notices
501
+ // Редактирование: edit_forms
502
+
503
+ if ( 'manage_options' == $capability && is_multisite() && $this->isNetworkActive() ) {
504
+ $capability = 'manage_network';
505
+ }
506
+
507
+ return current_user_can( $capability );
508
+ }
509
+
510
  /**
511
+ * Проверят, находится ли пользователь в панели усправления сетью сайтов
512
+ *
513
+ * @since 4.0.8 Добавлен
514
+ *
515
  * @return bool
516
  */
517
  public function isNetworkAdmin() {
518
  return is_multisite() && is_network_admin();
519
  }
520
+
521
  /**
522
+ * Проверяет активирован ли плагин для сети. Если проект работает в режиме мультисайтов..
523
+ *
524
+ * @since 4.0.8 Добавлен
525
+ * @return bool Если true, плагин активирован для сети или в текущий момент активируется для сети.
526
  */
527
  public function isNetworkActive() {
528
  // Makes sure the plugin is defined before trying to use it
529
  if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
530
  require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
531
  }
532
+
533
  $activate = is_plugin_active_for_network( $this->get_paths()->basename );
534
+
535
  if ( ! $activate && $this->isNetworkAdmin() && isset( $_GET['action'] ) && $_GET['action'] == 'activate' ) {
536
+ return isset( $_GET['networkwide'] ) && 1 == (int) $_GET['networkwide'];
 
 
 
 
537
  }
538
+
539
  return $activate;
540
  }
541
+
542
  /**
543
+ * Позволяет получить все активные сайты сети. Если проект работает в режиме мультисайтов.
544
+ *
545
  * @since 4.0.8
546
  * @return array|int
547
  */
548
+ public function getActiveSites( $args = [ 'archived' => 0, 'mature' => 0, 'spam' => 0, 'deleted' => 0 ] ) {
549
  global $wp_version;
550
+
551
  if ( version_compare( $wp_version, '4.6', '>=' ) ) {
552
  return get_sites( $args );
553
  } else {
554
+ $converted_array = [];
555
+
556
  $sites = wp_get_sites( $args );
557
+
558
  if ( empty( $sites ) ) {
559
  return $converted_array;
560
  }
561
+
562
  foreach ( (array) $sites as $key => $site ) {
563
  $obj = new stdClass();
564
  foreach ( $site as $attr => $value ) {
566
  }
567
  $converted_array[ $key ] = $obj;
568
  }
569
+
570
  return $converted_array;
571
  }
572
  }
libs/factory/core/includes/class-factory-requests.php CHANGED
@@ -4,20 +4,27 @@ if ( ! defined( 'ABSPATH' ) ) {
4
  exit;
5
  }
6
 
7
- class Wbcr_Factory412_Request {
8
-
 
 
 
 
 
 
 
9
  /**
10
- * @param null $param
11
- * @param bool|string $sanitize true/false or sanitize function name
12
- * @param bool $default
13
- * @param string $method_name
14
  *
15
  * @return array|bool|mixed
16
  */
17
  private function getBody( $param = null, $sanitize = false, $default = false, $method_name = 'REQUEST' ) {
18
  $sanitize_function_name = 'sanitize_text_field';
19
  $method = $_REQUEST;
20
-
21
  switch ( strtoupper( $method_name ) ) {
22
  case 'GET':
23
  $method = $_GET;
@@ -29,15 +36,15 @@ class Wbcr_Factory412_Request {
29
  $method = $_REQUEST;
30
  break;
31
  }
32
-
33
  if ( ! empty( $sanitize ) && is_string( $sanitize ) && $sanitize !== $sanitize_function_name ) {
34
  $sanitize_function_name = $sanitize;
35
  }
36
-
37
  if ( ! function_exists( $sanitize_function_name ) ) {
38
  throw new Exception( 'Function ' . $sanitize_function_name . 'is undefined.' );
39
  }
40
-
41
  if ( ! empty( $param ) ) {
42
  if ( isset( $method[ $param ] ) && ! empty( $method[ $param ] ) ) {
43
  if ( is_array( $method[ $param ] ) ) {
@@ -46,18 +53,18 @@ class Wbcr_Factory412_Request {
46
  return ! empty( $sanitize ) ? call_user_func( $sanitize_function_name, $method[ $param ] ) : $method[ $param ];
47
  }
48
  }
49
-
50
  return $default;
51
  }
52
-
53
  return ! empty( $sanitize ) ? array_map( $sanitize_function_name, $method ) : $method;
54
  }
55
-
56
  /**
57
  * Recursive sanitation for an array
58
  *
59
  * @param string $function_name
60
- * @param $array
61
  *
62
  * @return mixed
63
  */
@@ -69,26 +76,26 @@ class Wbcr_Factory412_Request {
69
  if ( ! function_exists( $function_name ) ) {
70
  throw new Exception( 'Function ' . $function_name . 'is undefined.' );
71
  }
72
-
73
  $value = $function_name( $value );
74
  }
75
  }
76
-
77
  return $array;
78
  }
79
-
80
  /**
81
  * @param bool|string see method getBody
82
  * @param array $default
83
  *
84
  * @return mixed|null
85
  */
86
- public function requestAll( $sanitize = false, $default = array() ) {
87
  return $this->getBody( null, $sanitize, $default );
88
  }
89
-
90
  /**
91
- * @param $param
92
  * @param bool|string see method getBody
93
  * @param bool $default
94
  *
@@ -97,17 +104,17 @@ class Wbcr_Factory412_Request {
97
  public function request( $param, $default = false, $sanitize = false ) {
98
  return $this->getBody( $param, $sanitize, $default );
99
  }
100
-
101
  /**
102
  * @param bool|string see method getBody
103
  * @param array $default
104
  *
105
  * @return mixed|null
106
  */
107
- public function getAll( $sanitize = false, $default = array() ) {
108
  return $this->getBody( null, $sanitize, $default, 'get' );
109
  }
110
-
111
  /**
112
  * @param null $param
113
  * @param bool|string see method getBody
@@ -118,19 +125,19 @@ class Wbcr_Factory412_Request {
118
  public function get( $param, $default = false, $sanitize = false ) {
119
  return $this->getBody( $param, $sanitize, $default, 'get' );
120
  }
121
-
122
  /**
123
  * @param bool|string see method getBody
124
  * @param array $default
125
  *
126
  * @return mixed|null
127
  */
128
- public function postAll( $sanitize = false, $default = array() ) {
129
  return $this->getBody( null, $sanitize, $default, 'post' );
130
  }
131
-
132
  /**
133
- * @param $param
134
  * @param bool|string see method getBody
135
  * @param bool $default
136
  *
4
  exit;
5
  }
6
 
7
+ /*
8
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
9
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
10
+ *
11
+ * @package factory-core
12
+ */
13
+
14
+ class Wbcr_Factory424_Request {
15
+
16
  /**
17
+ * @param null $param
18
+ * @param bool|string $sanitize true/false or sanitize function name
19
+ * @param bool $default
20
+ * @param string $method_name
21
  *
22
  * @return array|bool|mixed
23
  */
24
  private function getBody( $param = null, $sanitize = false, $default = false, $method_name = 'REQUEST' ) {
25
  $sanitize_function_name = 'sanitize_text_field';
26
  $method = $_REQUEST;
27
+
28
  switch ( strtoupper( $method_name ) ) {
29
  case 'GET':
30
  $method = $_GET;
36
  $method = $_REQUEST;
37
  break;
38
  }
39
+
40
  if ( ! empty( $sanitize ) && is_string( $sanitize ) && $sanitize !== $sanitize_function_name ) {
41
  $sanitize_function_name = $sanitize;
42
  }
43
+
44
  if ( ! function_exists( $sanitize_function_name ) ) {
45
  throw new Exception( 'Function ' . $sanitize_function_name . 'is undefined.' );
46
  }
47
+
48
  if ( ! empty( $param ) ) {
49
  if ( isset( $method[ $param ] ) && ! empty( $method[ $param ] ) ) {
50
  if ( is_array( $method[ $param ] ) ) {
53
  return ! empty( $sanitize ) ? call_user_func( $sanitize_function_name, $method[ $param ] ) : $method[ $param ];
54
  }
55
  }
56
+
57
  return $default;
58
  }
59
+
60
  return ! empty( $sanitize ) ? array_map( $sanitize_function_name, $method ) : $method;
61
  }
62
+
63
  /**
64
  * Recursive sanitation for an array
65
  *
66
  * @param string $function_name
67
+ * @param $array
68
  *
69
  * @return mixed
70
  */
76
  if ( ! function_exists( $function_name ) ) {
77
  throw new Exception( 'Function ' . $function_name . 'is undefined.' );
78
  }
79
+
80
  $value = $function_name( $value );
81
  }
82
  }
83
+
84
  return $array;
85
  }
86
+
87
  /**
88
  * @param bool|string see method getBody
89
  * @param array $default
90
  *
91
  * @return mixed|null
92
  */
93
+ public function requestAll( $sanitize = false, $default = [] ) {
94
  return $this->getBody( null, $sanitize, $default );
95
  }
96
+
97
  /**
98
+ * @param $param
99
  * @param bool|string see method getBody
100
  * @param bool $default
101
  *
104
  public function request( $param, $default = false, $sanitize = false ) {
105
  return $this->getBody( $param, $sanitize, $default );
106
  }
107
+
108
  /**
109
  * @param bool|string see method getBody
110
  * @param array $default
111
  *
112
  * @return mixed|null
113
  */
114
+ public function getAll( $sanitize = false, $default = [] ) {
115
  return $this->getBody( null, $sanitize, $default, 'get' );
116
  }
117
+
118
  /**
119
  * @param null $param
120
  * @param bool|string see method getBody
125
  public function get( $param, $default = false, $sanitize = false ) {
126
  return $this->getBody( $param, $sanitize, $default, 'get' );
127
  }
128
+
129
  /**
130
  * @param bool|string see method getBody
131
  * @param array $default
132
  *
133
  * @return mixed|null
134
  */
135
+ public function postAll( $sanitize = false, $default = [] ) {
136
  return $this->getBody( null, $sanitize, $default, 'post' );
137
  }
138
+
139
  /**
140
+ * @param $param
141
  * @param bool|string see method getBody
142
  * @param bool $default
143
  *
libs/factory/core/includes/class-factory-requirements.php CHANGED
@@ -3,162 +3,163 @@
3
  /**
4
  * Class to check if the current WordPress and PHP versions meet our requirements
5
  *
6
- * @see Docs https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/21692485/WFF+Requirements
7
  *
8
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alea Kovalev <alex.kovalevv@gmail.com>
9
- * @copyright (c) 26.09.2018, Webcraftic
10
- * @version 2.0.0
11
- * @since 4.0.9
 
12
  */
 
 
 
13
 
14
- if ( ! class_exists( 'Wbcr_Factory412_Requirements' ) ) {
15
- class Wbcr_Factory412_Requirements {
16
-
17
  /**
18
  * Factory framework version
19
  *
20
  * @var string
21
  */
22
  protected $factory_version;
23
-
24
  /**
25
  * @var string
26
  */
27
  protected $plugin_version;
28
-
29
  /**
30
  * Plugin file path
31
  *
32
  * @var string
33
  */
34
  protected $plugin_file;
35
-
36
  /**
37
  * Plugin dir
38
  *
39
  * @var string
40
  */
41
  protected $plugin_abs_path;
42
-
43
  /**
44
  * Plugin base dir
45
  *
46
  * @var string
47
  */
48
  protected $plugin_basename;
49
-
50
  /**
51
  * Plugin url
52
  *
53
  * @var string
54
  */
55
  protected $plugin_url;
56
-
57
  /**
58
  * Plugin prefix
59
  *
60
  * @var string
61
  */
62
  protected $plugin_prefix;
63
-
64
  /**
65
  * Plugin name
66
  *
67
  * @var string
68
  */
69
  protected $plugin_name;
70
-
71
  /**
72
  * Plugin title
73
  *
74
  * @var string
75
  */
76
  protected $plugin_title = "(no title)";
77
-
78
  /**
79
  * @var string
80
  */
81
  protected $plugin_text_domain;
82
-
83
  /**
84
  * Required PHP version
85
  *
86
  * @var string
87
  */
88
  protected $required_php_version = '5.3';
89
-
90
  /**
91
  * Required WordPress version
92
  *
93
  * @var string
94
  */
95
  protected $required_wp_version = '4.2.0';
96
-
97
  /**
98
  * Is this plugin already activated?
99
  *
100
  * @var bool
101
  */
102
  protected $plugin_already_activate = false;
103
-
104
  /**
105
  * WFF_Requirements constructor.
106
  *
107
  * @param string $plugin_file
108
- * @param array $plugin_info
109
  */
110
- function __construct( $plugin_file, array $plugin_info ) {
111
-
112
  foreach ( (array) $plugin_info as $property => $value ) {
113
  if ( property_exists( $this, $property ) ) {
114
  $this->$property = $value;
115
  }
116
  }
117
-
118
  $this->plugin_file = $plugin_file;
119
  $this->plugin_abs_path = dirname( $plugin_file );
120
  $this->plugin_basename = plugin_basename( $plugin_file );
121
  $this->plugin_url = plugins_url( null, $plugin_file );
122
-
123
  $plugin_info = get_file_data( $this->plugin_file, array(
124
  'Version' => 'Version',
125
  'FrameworkVersion' => 'Framework Version',
126
  'TextDomain' => 'Text Domain'
127
  ), 'plugin' );
128
-
129
  if ( isset( $plugin_info['FrameworkVersion'] ) ) {
130
  $this->factory_version = $plugin_info['FrameworkVersion'];
131
  }
132
-
133
  if ( isset( $plugin_info['Version'] ) ) {
134
  $this->plugin_version = $plugin_info['Version'];
135
  }
136
-
137
  if ( isset( $plugin_info['TextDomain'] ) ) {
138
  $this->plugin_text_domain = $plugin_info['TextDomain'];
139
  }
140
-
141
  add_action( 'admin_init', array( $this, 'register_notices' ) );
142
  }
143
-
144
  public function get_plugin_version() {
145
  return $this->plugin_version;
146
  }
147
-
148
  public function get_text_domain() {
149
  return $this->plugin_text_domain;
150
  }
151
-
152
  /**
153
  * @since 4.1.1
154
  * @return void
155
  */
156
  public function register_notices() {
157
  if ( current_user_can( 'activate_plugins' ) && current_user_can( 'edit_plugins' ) && current_user_can( 'install_plugins' ) ) {
158
-
159
  if ( is_multisite() ) {
160
  add_action( 'network_admin_notices', array( $this, 'show_notice' ) );
161
-
162
  if ( ! empty( $this->plugin_basename ) && in_array( $this->plugin_basename, (array) get_option( 'active_plugins', array() ) ) ) {
163
  add_action( 'admin_notices', array( $this, 'show_notice' ) );
164
  }
@@ -167,9 +168,10 @@ if ( ! class_exists( 'Wbcr_Factory412_Requirements' ) ) {
167
  }
168
  }
169
  }
170
-
171
  /**
172
  * Shows the incompatibility notification.
 
173
  * @since 4.1.1
174
  * @return void
175
  */
@@ -177,18 +179,19 @@ if ( ! class_exists( 'Wbcr_Factory412_Requirements' ) ) {
177
  if ( $this->check() ) {
178
  return;
179
  }
180
-
181
  echo '<div class="notice notice-error"><p>' . $this->get_notice_text() . '</p></div>';
182
  }
183
-
184
-
185
  /**
186
  * The method checks the compatibility of the plugin with php and wordpress version.
 
187
  * @since 4.1.1
188
  * @return bool
189
  */
190
  public function check() {
191
-
192
  // Fix for ithemes sync. When the ithemes sync plugin accepts the request, set the WP_ADMIN constant,
193
  // after which the plugin Clearfy begins to create errors, and how the logic of its work is broken.
194
  // Solution to simply terminate the plugin if there is a request from ithemes sync
@@ -196,19 +199,19 @@ if ( ! class_exists( 'Wbcr_Factory412_Requirements' ) ) {
196
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'ithemes_sync_request' ) {
197
  return false;
198
  }
199
-
200
  if ( isset( $_GET['ithemes-sync-request'] ) && ! empty( $_GET['ithemes-sync-request'] ) ) {
201
  return false;
202
  }
203
  // ----------------------------------------
204
-
205
  if ( ! $this->check_php_compat() || ! $this->check_wp_compat() || $this->plugin_already_activate ) {
206
  return false;
207
  }
208
-
209
  return true;
210
  }
211
-
212
  /**
213
  * The method checks the compatibility of the plugin with the php version of the server.
214
  *
@@ -217,7 +220,7 @@ if ( ! class_exists( 'Wbcr_Factory412_Requirements' ) ) {
217
  public function check_php_compat() {
218
  return version_compare( PHP_VERSION, $this->required_php_version, '>=' );
219
  }
220
-
221
  /**
222
  * The method checks the compatibility of the plugin with the Wordpress version of the site.
223
  *
@@ -226,10 +229,10 @@ if ( ! class_exists( 'Wbcr_Factory412_Requirements' ) ) {
226
  public function check_wp_compat() {
227
  // Get the WP Version global.
228
  global $wp_version;
229
-
230
  return version_compare( $wp_version, $this->required_wp_version, '>=' );
231
  }
232
-
233
  /**
234
  * Method returns notification text
235
  *
@@ -238,53 +241,54 @@ if ( ! class_exists( 'Wbcr_Factory412_Requirements' ) ) {
238
  protected function get_notice_text() {
239
  $notice_text = $notice_default_text = '';
240
  $notice_default_text .= '<b>' . $this->plugin_title . ' ' . __( 'warning', '' ) . ':</b>' . '<br>';
241
-
242
- $notice_default_text .= sprintf( __( 'The %s plugin has stopped.', 'wbcr_factory_clearfy_208' ), $this->plugin_title ) . ' ';
243
  $notice_default_text .= __( 'Possible reasons:', '' ) . ' <br>';
244
-
245
  $has_one = false;
246
-
247
  if ( ! $this->check_php_compat() ) {
248
  $has_one = true;
249
  $notice_text .= '- ' . $this->get_php_incompat_text() . '<br>';
250
  }
251
-
252
  if ( ! $this->check_wp_compat() ) {
253
  $has_one = true;
254
  $notice_text .= '- ' . $this->get_wp_incompat_text() . '<br>';
255
  }
256
-
257
  if ( $this->plugin_already_activate ) {
258
  $has_one = true;
259
  $notice_text = '- ' . $this->get_plugin_already_activate_text() . '<br>';
260
  }
261
-
262
  if ( $has_one ) {
263
  $notice_text = $notice_default_text . $notice_text;
264
  }
265
-
266
  return $notice_text;
267
  }
268
-
269
  /**
270
  * @return string
271
  */
272
  protected function get_php_incompat_text() {
273
- return sprintf( __( 'You need to update the PHP version to %s or higher!', 'wbcr_factory_412' ), $this->required_php_version );
274
  }
275
-
276
  /**
277
  * @return string
278
  */
279
  protected function get_wp_incompat_text() {
280
- return sprintf( __( 'You need to update WordPress to %s or higher!', 'wbcr_factory_412' ), $this->required_wp_version );
281
  }
282
-
283
  /**
284
  * @return string
285
  */
286
  protected function get_plugin_already_activate_text() {
287
- return sprintf( __( 'Plugin %s is already activated, you are trying to activate it again.', 'wbcr_factory_412' ), $this->plugin_title );
288
  }
289
  }
290
- }
 
3
  /**
4
  * Class to check if the current WordPress and PHP versions meet our requirements
5
  *
6
+ * @see Docs https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/21692485/WFF+Requirements
7
  *
8
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
9
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
10
+ *
11
+ * @version 2.0.0
12
+ * @since 4.0.9
13
  */
14
+ // @formatter:off
15
+ if ( ! class_exists( 'Wbcr_Factory424_Requirements' ) ) {
16
+ class Wbcr_Factory424_Requirements {
17
 
 
 
 
18
  /**
19
  * Factory framework version
20
  *
21
  * @var string
22
  */
23
  protected $factory_version;
24
+
25
  /**
26
  * @var string
27
  */
28
  protected $plugin_version;
29
+
30
  /**
31
  * Plugin file path
32
  *
33
  * @var string
34
  */
35
  protected $plugin_file;
36
+
37
  /**
38
  * Plugin dir
39
  *
40
  * @var string
41
  */
42
  protected $plugin_abs_path;
43
+
44
  /**
45
  * Plugin base dir
46
  *
47
  * @var string
48
  */
49
  protected $plugin_basename;
50
+
51
  /**
52
  * Plugin url
53
  *
54
  * @var string
55
  */
56
  protected $plugin_url;
57
+
58
  /**
59
  * Plugin prefix
60
  *
61
  * @var string
62
  */
63
  protected $plugin_prefix;
64
+
65
  /**
66
  * Plugin name
67
  *
68
  * @var string
69
  */
70
  protected $plugin_name;
71
+
72
  /**
73
  * Plugin title
74
  *
75
  * @var string
76
  */
77
  protected $plugin_title = "(no title)";
78
+
79
  /**
80
  * @var string
81
  */
82
  protected $plugin_text_domain;
83
+
84
  /**
85
  * Required PHP version
86
  *
87
  * @var string
88
  */
89
  protected $required_php_version = '5.3';
90
+
91
  /**
92
  * Required WordPress version
93
  *
94
  * @var string
95
  */
96
  protected $required_wp_version = '4.2.0';
97
+
98
  /**
99
  * Is this plugin already activated?
100
  *
101
  * @var bool
102
  */
103
  protected $plugin_already_activate = false;
104
+
105
  /**
106
  * WFF_Requirements constructor.
107
  *
108
  * @param string $plugin_file
109
+ * @param array $plugin_info
110
  */
111
+ public function __construct( $plugin_file, array $plugin_info ) {
112
+
113
  foreach ( (array) $plugin_info as $property => $value ) {
114
  if ( property_exists( $this, $property ) ) {
115
  $this->$property = $value;
116
  }
117
  }
118
+
119
  $this->plugin_file = $plugin_file;
120
  $this->plugin_abs_path = dirname( $plugin_file );
121
  $this->plugin_basename = plugin_basename( $plugin_file );
122
  $this->plugin_url = plugins_url( null, $plugin_file );
123
+
124
  $plugin_info = get_file_data( $this->plugin_file, array(
125
  'Version' => 'Version',
126
  'FrameworkVersion' => 'Framework Version',
127
  'TextDomain' => 'Text Domain'
128
  ), 'plugin' );
129
+
130
  if ( isset( $plugin_info['FrameworkVersion'] ) ) {
131
  $this->factory_version = $plugin_info['FrameworkVersion'];
132
  }
133
+
134
  if ( isset( $plugin_info['Version'] ) ) {
135
  $this->plugin_version = $plugin_info['Version'];
136
  }
137
+
138
  if ( isset( $plugin_info['TextDomain'] ) ) {
139
  $this->plugin_text_domain = $plugin_info['TextDomain'];
140
  }
141
+
142
  add_action( 'admin_init', array( $this, 'register_notices' ) );
143
  }
144
+
145
  public function get_plugin_version() {
146
  return $this->plugin_version;
147
  }
148
+
149
  public function get_text_domain() {
150
  return $this->plugin_text_domain;
151
  }
152
+
153
  /**
154
  * @since 4.1.1
155
  * @return void
156
  */
157
  public function register_notices() {
158
  if ( current_user_can( 'activate_plugins' ) && current_user_can( 'edit_plugins' ) && current_user_can( 'install_plugins' ) ) {
159
+
160
  if ( is_multisite() ) {
161
  add_action( 'network_admin_notices', array( $this, 'show_notice' ) );
162
+
163
  if ( ! empty( $this->plugin_basename ) && in_array( $this->plugin_basename, (array) get_option( 'active_plugins', array() ) ) ) {
164
  add_action( 'admin_notices', array( $this, 'show_notice' ) );
165
  }
168
  }
169
  }
170
  }
171
+
172
  /**
173
  * Shows the incompatibility notification.
174
+ *
175
  * @since 4.1.1
176
  * @return void
177
  */
179
  if ( $this->check() ) {
180
  return;
181
  }
182
+
183
  echo '<div class="notice notice-error"><p>' . $this->get_notice_text() . '</p></div>';
184
  }
185
+
186
+
187
  /**
188
  * The method checks the compatibility of the plugin with php and wordpress version.
189
+ *
190
  * @since 4.1.1
191
  * @return bool
192
  */
193
  public function check() {
194
+
195
  // Fix for ithemes sync. When the ithemes sync plugin accepts the request, set the WP_ADMIN constant,
196
  // after which the plugin Clearfy begins to create errors, and how the logic of its work is broken.
197
  // Solution to simply terminate the plugin if there is a request from ithemes sync
199
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'ithemes_sync_request' ) {
200
  return false;
201
  }
202
+
203
  if ( isset( $_GET['ithemes-sync-request'] ) && ! empty( $_GET['ithemes-sync-request'] ) ) {
204
  return false;
205
  }
206
  // ----------------------------------------
207
+
208
  if ( ! $this->check_php_compat() || ! $this->check_wp_compat() || $this->plugin_already_activate ) {
209
  return false;
210
  }
211
+
212
  return true;
213
  }
214
+
215
  /**
216
  * The method checks the compatibility of the plugin with the php version of the server.
217
  *
220
  public function check_php_compat() {
221
  return version_compare( PHP_VERSION, $this->required_php_version, '>=' );
222
  }
223
+
224
  /**
225
  * The method checks the compatibility of the plugin with the Wordpress version of the site.
226
  *
229
  public function check_wp_compat() {
230
  // Get the WP Version global.
231
  global $wp_version;
232
+
233
  return version_compare( $wp_version, $this->required_wp_version, '>=' );
234
  }
235
+
236
  /**
237
  * Method returns notification text
238
  *
241
  protected function get_notice_text() {
242
  $notice_text = $notice_default_text = '';
243
  $notice_default_text .= '<b>' . $this->plugin_title . ' ' . __( 'warning', '' ) . ':</b>' . '<br>';
244
+
245
+ $notice_default_text .= sprintf( __( 'The %s plugin has stopped.', 'wbcr_factory_clearfy_216' ), $this->plugin_title ) . ' ';
246
  $notice_default_text .= __( 'Possible reasons:', '' ) . ' <br>';
247
+
248
  $has_one = false;
249
+
250
  if ( ! $this->check_php_compat() ) {
251
  $has_one = true;
252
  $notice_text .= '- ' . $this->get_php_incompat_text() . '<br>';
253
  }
254
+
255
  if ( ! $this->check_wp_compat() ) {
256
  $has_one = true;
257
  $notice_text .= '- ' . $this->get_wp_incompat_text() . '<br>';
258
  }
259
+
260
  if ( $this->plugin_already_activate ) {
261
  $has_one = true;
262
  $notice_text = '- ' . $this->get_plugin_already_activate_text() . '<br>';
263
  }
264
+
265
  if ( $has_one ) {
266
  $notice_text = $notice_default_text . $notice_text;
267
  }
268
+
269
  return $notice_text;
270
  }
271
+
272
  /**
273
  * @return string
274
  */
275
  protected function get_php_incompat_text() {
276
+ return sprintf( __( 'You need to update the PHP version to %s or higher!', 'wbcr_factory_424' ), $this->required_php_version );
277
  }
278
+
279
  /**
280
  * @return string
281
  */
282
  protected function get_wp_incompat_text() {
283
+ return sprintf( __( 'You need to update WordPress to %s or higher!', 'wbcr_factory_424' ), $this->required_wp_version );
284
  }
285
+
286
  /**
287
  * @return string
288
  */
289
  protected function get_plugin_already_activate_text() {
290
+ return sprintf( __( 'Plugin %s is already activated, you are trying to activate it again.', 'wbcr_factory_424' ), $this->plugin_title );
291
  }
292
  }
293
+ }
294
+ // @formatter:on
libs/factory/core/includes/entities/class-factory-paths.php CHANGED
@@ -1,30 +1,29 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412\Entities;
4
 
5
  if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
7
  }
8
 
9
  /*
10
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
11
- * @link https://webcraftic.com
12
- * @copyright (c) 2018 Webraftic Ltd
13
  * @since 4.1.1
14
  */
15
 
16
  class Paths {
17
-
18
  public $absolute;
19
  public $main_file;
20
  public $relative;
21
  public $url;
22
-
23
  protected $plugin_path;
24
-
25
  public function __construct( $plugin_file ) {
26
  $this->plugin_path = $plugin_file;
27
-
28
  $this->main_file = $plugin_file;
29
  $this->absolute = dirname( $plugin_file );
30
  $this->basename = plugin_basename( $plugin_file );
1
  <?php
2
 
3
+ namespace WBCR\Factory_424\Entities;
4
 
5
  if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
7
  }
8
 
9
  /*
10
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
11
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
 
12
  * @since 4.1.1
13
  */
14
 
15
  class Paths {
16
+
17
  public $absolute;
18
  public $main_file;
19
  public $relative;
20
  public $url;
21
+
22
  protected $plugin_path;
23
+
24
  public function __construct( $plugin_file ) {
25
  $this->plugin_path = $plugin_file;
26
+
27
  $this->main_file = $plugin_file;
28
  $this->absolute = dirname( $plugin_file );
29
  $this->basename = plugin_basename( $plugin_file );
libs/factory/core/includes/entities/class-factory-support.php CHANGED
@@ -1,28 +1,27 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412\Entities;
4
 
5
  if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
7
  }
8
 
9
  /*
10
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
11
- * @link https://webcraftic.com
12
- * @copyright (c) 2018 Webraftic Ltd
13
  * @since 4.1.1
14
  */
15
 
16
  class Support {
17
-
18
  protected $plugin_name;
19
  protected $site_url;
20
-
21
  protected $features_page_slug = 'premium-features';
22
  protected $pricing_page_slug = 'pricing';
23
  protected $support_page_slug = 'support';
24
  protected $docs_page_slug = 'docs';
25
-
26
  /**
27
  * Plugin_Site constructor.
28
  *
@@ -30,7 +29,7 @@ class Support {
30
  */
31
  public function __construct( array $data ) {
32
  $this->site_url = isset( $data['url'] ) ? $data['url'] : null;
33
-
34
  if ( isset( $data['pages_map'] ) && is_array( $data['pages_map'] ) ) {
35
  foreach ( $data['pages_map'] as $key => $def_value ) {
36
  $attr = $key . '_page_slug';
@@ -38,7 +37,7 @@ class Support {
38
  }
39
  }
40
  }
41
-
42
  /**
43
  * @return string
44
  */
@@ -46,11 +45,11 @@ class Support {
46
  if ( $track ) {
47
  return $this->get_tracking_page_url( $this->site_url, $utm_content );
48
  }
49
-
50
  return $this->site_url;
51
  }
52
-
53
-
54
  /**
55
  * @return string
56
  */
@@ -58,11 +57,11 @@ class Support {
58
  if ( $track ) {
59
  return $this->get_tracking_page_url( $this->features_page_slug, $utm_content );
60
  }
61
-
62
  return $this->get_site_url() . '/' . $this->features_page_slug;
63
  }
64
-
65
-
66
  /**
67
  * @return string
68
  */
@@ -70,11 +69,11 @@ class Support {
70
  if ( $track ) {
71
  return $this->get_tracking_page_url( $this->pricing_page_slug, $utm_content );
72
  }
73
-
74
  return $this->get_site_url() . '/' . $this->pricing_page_slug;
75
  }
76
-
77
-
78
  /**
79
  * @return string
80
  */
@@ -82,11 +81,11 @@ class Support {
82
  if ( $track ) {
83
  return $this->get_tracking_page_url( $this->support_page_slug, $utm_content );
84
  }
85
-
86
  return $this->get_site_url() . '/' . $this->support_page_slug;
87
  }
88
-
89
-
90
  /**
91
  * @return string
92
  */
@@ -94,32 +93,32 @@ class Support {
94
  if ( $track ) {
95
  return $this->get_tracking_page_url( $this->docs_page_slug, $utm_content );
96
  }
97
-
98
  return $this->get_site_url() . '/' . $this->docs_page_slug;
99
  }
100
-
101
-
102
  /**
103
- * @param null $page
104
- * @param null $utm_content
105
  * @param string $urm_source
106
  *
107
  * @return string
108
  */
109
  public function get_tracking_page_url( $page = null, $utm_content = null, $urm_source = 'wordpress.org' ) {
110
-
111
- $args = array( 'utm_source' => $urm_source );
112
-
113
  if ( ! empty( $plugin_name ) ) {
114
  $args['utm_campaign'] = $plugin_name;
115
  }
116
-
117
  if ( ! empty( $utm_content ) ) {
118
  $args['utm_content'] = $utm_content;
119
  }
120
-
121
  $raw_url = add_query_arg( $args, $this->get_site_url() . '/' . $page . '/' );
122
-
123
  return esc_url( $raw_url );
124
  }
125
  }
1
  <?php
2
 
3
+ namespace WBCR\Factory_424\Entities;
4
 
5
  if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
7
  }
8
 
9
  /*
10
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
11
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
 
12
  * @since 4.1.1
13
  */
14
 
15
  class Support {
16
+
17
  protected $plugin_name;
18
  protected $site_url;
19
+
20
  protected $features_page_slug = 'premium-features';
21
  protected $pricing_page_slug = 'pricing';
22
  protected $support_page_slug = 'support';
23
  protected $docs_page_slug = 'docs';
24
+
25
  /**
26
  * Plugin_Site constructor.
27
  *
29
  */
30
  public function __construct( array $data ) {
31
  $this->site_url = isset( $data['url'] ) ? $data['url'] : null;
32
+
33
  if ( isset( $data['pages_map'] ) && is_array( $data['pages_map'] ) ) {
34
  foreach ( $data['pages_map'] as $key => $def_value ) {
35
  $attr = $key . '_page_slug';
37
  }
38
  }
39
  }
40
+
41
  /**
42
  * @return string
43
  */
45
  if ( $track ) {
46
  return $this->get_tracking_page_url( $this->site_url, $utm_content );
47
  }
48
+
49
  return $this->site_url;
50
  }
51
+
52
+
53
  /**
54
  * @return string
55
  */
57
  if ( $track ) {
58
  return $this->get_tracking_page_url( $this->features_page_slug, $utm_content );
59
  }
60
+
61
  return $this->get_site_url() . '/' . $this->features_page_slug;
62
  }
63
+
64
+
65
  /**
66
  * @return string
67
  */
69
  if ( $track ) {
70
  return $this->get_tracking_page_url( $this->pricing_page_slug, $utm_content );
71
  }
72
+
73
  return $this->get_site_url() . '/' . $this->pricing_page_slug;
74
  }
75
+
76
+
77
  /**
78
  * @return string
79
  */
81
  if ( $track ) {
82
  return $this->get_tracking_page_url( $this->support_page_slug, $utm_content );
83
  }
84
+
85
  return $this->get_site_url() . '/' . $this->support_page_slug;
86
  }
87
+
88
+
89
  /**
90
  * @return string
91
  */
93
  if ( $track ) {
94
  return $this->get_tracking_page_url( $this->docs_page_slug, $utm_content );
95
  }
96
+
97
  return $this->get_site_url() . '/' . $this->docs_page_slug;
98
  }
99
+
100
+
101
  /**
102
+ * @param null $page
103
+ * @param null $utm_content
104
  * @param string $urm_source
105
  *
106
  * @return string
107
  */
108
  public function get_tracking_page_url( $page = null, $utm_content = null, $urm_source = 'wordpress.org' ) {
109
+
110
+ $args = [ 'utm_source' => $urm_source ];
111
+
112
  if ( ! empty( $plugin_name ) ) {
113
  $args['utm_campaign'] = $plugin_name;
114
  }
115
+
116
  if ( ! empty( $utm_content ) ) {
117
  $args['utm_content'] = $utm_content;
118
  }
119
+
120
  $raw_url = add_query_arg( $args, $this->get_site_url() . '/' . $page . '/' );
121
+
122
  return esc_url( $raw_url );
123
  }
124
  }
libs/factory/core/includes/functions.php CHANGED
@@ -2,11 +2,11 @@
2
  /**
3
  * Factory Function Library
4
  *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
- * @copyright (c) 2018, Webcraftic Ltd
7
  *
8
- * @package factory-core
9
- * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
@@ -19,18 +19,18 @@ if ( ! function_exists( 'get_user_locale' ) ) {
19
  $user = false;
20
  if ( 0 === $user_id && function_exists( 'wp_get_current_user' ) ) {
21
  $user = wp_get_current_user();
22
- } elseif ( $user_id instanceof WP_User ) {
23
  $user = $user_id;
24
- } elseif ( $user_id && is_numeric( $user_id ) ) {
25
  $user = get_user_by( 'id', $user_id );
26
  }
27
-
28
  if ( ! $user ) {
29
  return get_locale();
30
  }
31
-
32
  $locale = $user->locale;
33
-
34
  return $locale ? $locale : get_locale();
35
  }
36
  }
@@ -46,25 +46,25 @@ if ( ! function_exists( 'get_user_locale' ) ) {
46
  *
47
  * @since 1.0.0
48
  *
49
- * @see wbcr_factory_412_deprecated_hook()
50
- *
51
- * @param string $tag The name of the filter hook.
52
- * @param array $args Array of additional function arguments to be passed to apply_filters().
53
- * @param string $version The version of BP Block Users that deprecated the hook.
54
- * @param string $replacement Optional. The hook that should have been used.
55
- * @param string $message Optional. A message regarding the change.
56
  *
57
  * @return mixed
 
 
58
  */
59
- function wbcr_factory_412_apply_filters_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
60
  if ( function_exists( 'apply_filters_deprecated' ) ) {
61
  return apply_filters_deprecated( $tag, $args, $version, $replacement, $message );
62
  }
63
  if ( ! has_filter( $tag ) ) {
64
  return $args[0];
65
  }
66
- wbcr_factory_412_deprecated_hook( $tag, $version, $replacement, $message );
67
-
68
  return apply_filters_ref_array( $tag, $args );
69
  }
70
 
@@ -79,33 +79,33 @@ function wbcr_factory_412_apply_filters_deprecated( $tag, $args, $version, $repl
79
  *
80
  * @since 1.0.0
81
  *
82
- * @see _deprecated_hook()
83
- *
84
- * @param string $tag The name of the action hook.
85
- * @param array $args Array of additional function arguments to be passed to do_action().
86
- * @param string $version The version of BP Block Users that deprecated the hook.
87
- * @param string $replacement Optional. The hook that should have been used.
88
- * @param string $message Optional. A message regarding the change.
89
  *
90
  * @return void
 
 
91
  */
92
- function wbcr_factory_412_do_action_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
93
  if ( function_exists( 'do_action_deprecated' ) ) {
94
  do_action_deprecated( $tag, $args, $version, $replacement, $message );
95
-
96
  return;
97
  }
98
  if ( ! has_action( $tag ) ) {
99
  return;
100
  }
101
- wbcr_factory_412_deprecated_hook( $tag, $version, $replacement, $message );
102
  do_action_ref_array( $tag, $args );
103
  }
104
 
105
  /**
106
  * Marks a deprecated action or filter hook as deprecated and throws a notice.
107
  *
108
- * Use the 'wbcr_factory_412_deprecated_hook_run' action to get the backtrace describing where the
109
  * deprecated hook was called.
110
  *
111
  * Default behavior is to trigger a user error if WP_DEBUG is true.
@@ -115,34 +115,34 @@ function wbcr_factory_412_do_action_deprecated( $tag, $args, $version, $replacem
115
  *
116
  * This is a copy of `_deprecated_hook` introduced in WP 4.6.
117
  *
118
- * @since 1.0.0
119
  * @access private
120
  *
121
- * @param string $hook The hook that was used.
122
- * @param string $version The version of WordPress that deprecated the hook.
123
- * @param string $replacement Optional. The hook that should have been used.
124
- * @param string $message Optional. A message regarding the change.
125
  */
126
- function wbcr_factory_412_deprecated_hook( $hook, $version, $replacement = null, $message = null ) {
127
  /**
128
  * Fires when a deprecated hook is called.
129
  *
130
  * @since 1.0.0
131
  *
132
- * @param string $hook The hook that was called.
133
- * @param string $replacement The hook that should be used as a replacement.
134
- * @param string $version The version of BP Block Users that deprecated the argument used.
135
- * @param string $message A message regarding the change.
136
  */
137
  do_action( 'deprecated_hook_run', $hook, $replacement, $version, $message );
138
-
139
  /**
140
  * Filter whether to trigger deprecated hook errors.
141
  *
142
  * @since 1.0.0
143
  *
144
- * @param bool $trigger Whether to trigger deprecated hook errors. Requires
145
- * `WP_DEBUG` to be defined true.
146
  */
147
  if ( WP_DEBUG && apply_filters( 'deprecated_hook_trigger_error', true ) ) {
148
  $message = empty( $message ) ? '' : ' ' . $message;
@@ -157,33 +157,33 @@ function wbcr_factory_412_deprecated_hook( $hook, $version, $replacement = null,
157
  if ( ! function_exists( '_sanitize_text_fields' ) ) {
158
  function _sanitize_text_fields( $str, $keep_newlines = false ) {
159
  $filtered = wp_check_invalid_utf8( $str );
160
-
161
  if ( strpos( $filtered, '<' ) !== false ) {
162
  $filtered = wp_pre_kses_less_than( $filtered );
163
  // This will strip extra whitespace for us.
164
  $filtered = wp_strip_all_tags( $filtered, false );
165
-
166
  // Use html entities in a special case to make sure no later
167
  // newline stripping stage could lead to a functional tag
168
  $filtered = str_replace( "<\n", "&lt;\n", $filtered );
169
  }
170
-
171
  if ( ! $keep_newlines ) {
172
  $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
173
  }
174
  $filtered = trim( $filtered );
175
-
176
  $found = false;
177
  while( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
178
  $filtered = str_replace( $match[0], '', $filtered );
179
  $found = true;
180
  }
181
-
182
  if ( $found ) {
183
  // Strip out the whitespace that may now exist after removing the octets.
184
  $filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
185
  }
186
-
187
  return $filtered;
188
  }
189
  }
@@ -191,14 +191,14 @@ if ( ! function_exists( '_sanitize_text_fields' ) ) {
191
  if ( ! function_exists( 'sanitize_textarea_field' ) ) {
192
  function sanitize_textarea_field( $str ) {
193
  $filtered = _sanitize_text_fields( $str, true );
194
-
195
  /**
196
  * Filters a sanitized textarea field string.
197
  *
198
  * @since 4.7.0
199
  *
200
- * @param string $filtered The sanitized string.
201
- * @param string $str The string prior to being sanitized.
202
  */
203
  return apply_filters( 'sanitize_textarea_field', $filtered, $str );
204
  }
2
  /**
3
  * Factory Function Library
4
  *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
6
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
7
  *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
19
  $user = false;
20
  if ( 0 === $user_id && function_exists( 'wp_get_current_user' ) ) {
21
  $user = wp_get_current_user();
22
+ } else if ( $user_id instanceof WP_User ) {
23
  $user = $user_id;
24
+ } else if ( $user_id && is_numeric( $user_id ) ) {
25
  $user = get_user_by( 'id', $user_id );
26
  }
27
+
28
  if ( ! $user ) {
29
  return get_locale();
30
  }
31
+
32
  $locale = $user->locale;
33
+
34
  return $locale ? $locale : get_locale();
35
  }
36
  }
46
  *
47
  * @since 1.0.0
48
  *
49
+ * @param string $tag The name of the filter hook.
50
+ * @param array $args Array of additional function arguments to be passed to apply_filters().
51
+ * @param string $version The version of BP Block Users that deprecated the hook.
52
+ * @param string $replacement Optional. The hook that should have been used.
53
+ * @param string $message Optional. A message regarding the change.
 
 
54
  *
55
  * @return mixed
56
+ * @see wbcr_factory_424_deprecated_hook()
57
+ *
58
  */
59
+ function wbcr_factory_424_apply_filters_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
60
  if ( function_exists( 'apply_filters_deprecated' ) ) {
61
  return apply_filters_deprecated( $tag, $args, $version, $replacement, $message );
62
  }
63
  if ( ! has_filter( $tag ) ) {
64
  return $args[0];
65
  }
66
+ wbcr_factory_424_deprecated_hook( $tag, $version, $replacement, $message );
67
+
68
  return apply_filters_ref_array( $tag, $args );
69
  }
70
 
79
  *
80
  * @since 1.0.0
81
  *
82
+ * @param string $tag The name of the action hook.
83
+ * @param array $args Array of additional function arguments to be passed to do_action().
84
+ * @param string $version The version of BP Block Users that deprecated the hook.
85
+ * @param string $replacement Optional. The hook that should have been used.
86
+ * @param string $message Optional. A message regarding the change.
 
 
87
  *
88
  * @return void
89
+ * @see _deprecated_hook()
90
+ *
91
  */
92
+ function wbcr_factory_424_do_action_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
93
  if ( function_exists( 'do_action_deprecated' ) ) {
94
  do_action_deprecated( $tag, $args, $version, $replacement, $message );
95
+
96
  return;
97
  }
98
  if ( ! has_action( $tag ) ) {
99
  return;
100
  }
101
+ wbcr_factory_424_deprecated_hook( $tag, $version, $replacement, $message );
102
  do_action_ref_array( $tag, $args );
103
  }
104
 
105
  /**
106
  * Marks a deprecated action or filter hook as deprecated and throws a notice.
107
  *
108
+ * Use the 'wbcr_factory_424_deprecated_hook_run' action to get the backtrace describing where the
109
  * deprecated hook was called.
110
  *
111
  * Default behavior is to trigger a user error if WP_DEBUG is true.
115
  *
116
  * This is a copy of `_deprecated_hook` introduced in WP 4.6.
117
  *
118
+ * @since 1.0.0
119
  * @access private
120
  *
121
+ * @param string $hook The hook that was used.
122
+ * @param string $version The version of WordPress that deprecated the hook.
123
+ * @param string $replacement Optional. The hook that should have been used.
124
+ * @param string $message Optional. A message regarding the change.
125
  */
126
+ function wbcr_factory_424_deprecated_hook( $hook, $version, $replacement = null, $message = null ) {
127
  /**
128
  * Fires when a deprecated hook is called.
129
  *
130
  * @since 1.0.0
131
  *
132
+ * @param string $hook The hook that was called.
133
+ * @param string $replacement The hook that should be used as a replacement.
134
+ * @param string $version The version of BP Block Users that deprecated the argument used.
135
+ * @param string $message A message regarding the change.
136
  */
137
  do_action( 'deprecated_hook_run', $hook, $replacement, $version, $message );
138
+
139
  /**
140
  * Filter whether to trigger deprecated hook errors.
141
  *
142
  * @since 1.0.0
143
  *
144
+ * @param bool $trigger Whether to trigger deprecated hook errors. Requires
145
+ * `WP_DEBUG` to be defined true.
146
  */
147
  if ( WP_DEBUG && apply_filters( 'deprecated_hook_trigger_error', true ) ) {
148
  $message = empty( $message ) ? '' : ' ' . $message;
157
  if ( ! function_exists( '_sanitize_text_fields' ) ) {
158
  function _sanitize_text_fields( $str, $keep_newlines = false ) {
159
  $filtered = wp_check_invalid_utf8( $str );
160
+
161
  if ( strpos( $filtered, '<' ) !== false ) {
162
  $filtered = wp_pre_kses_less_than( $filtered );
163
  // This will strip extra whitespace for us.
164
  $filtered = wp_strip_all_tags( $filtered, false );
165
+
166
  // Use html entities in a special case to make sure no later
167
  // newline stripping stage could lead to a functional tag
168
  $filtered = str_replace( "<\n", "&lt;\n", $filtered );
169
  }
170
+
171
  if ( ! $keep_newlines ) {
172
  $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
173
  }
174
  $filtered = trim( $filtered );
175
+
176
  $found = false;
177
  while( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
178
  $filtered = str_replace( $match[0], '', $filtered );
179
  $found = true;
180
  }
181
+
182
  if ( $found ) {
183
  // Strip out the whitespace that may now exist after removing the octets.
184
  $filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
185
  }
186
+
187
  return $filtered;
188
  }
189
  }
191
  if ( ! function_exists( 'sanitize_textarea_field' ) ) {
192
  function sanitize_textarea_field( $str ) {
193
  $filtered = _sanitize_text_fields( $str, true );
194
+
195
  /**
196
  * Filters a sanitized textarea field string.
197
  *
198
  * @since 4.7.0
199
  *
200
+ * @param string $filtered The sanitized string.
201
+ * @param string $str The string prior to being sanitized.
202
  */
203
  return apply_filters( 'sanitize_textarea_field', $filtered, $str );
204
  }
libs/factory/core/includes/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/core/includes/premium/class-factory-license-interface.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412\Premium\Interfaces;
4
 
5
  // Exit if accessed directly
6
  if ( ! defined( 'ABSPATH' ) ) {
@@ -8,25 +8,25 @@ if ( ! defined( 'ABSPATH' ) ) {
8
  }
9
 
10
  /**
11
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
12
- * @link https://webcraftic.com
13
  * @copyright (c) 2018 Webraftic Ltd
14
- * @version 1.0
15
  */
16
  interface License {
17
-
18
  public function get_key();
19
-
20
  public function get_hidden_key();
21
-
22
  public function get_expiration_time( $format = 'time' );
23
-
24
  public function get_sites_quota();
25
-
26
  public function get_count_active_sites();
27
-
28
  public function is_valid();
29
-
30
  public function is_lifetime();
31
-
32
  }
1
  <?php
2
 
3
+ namespace WBCR\Factory_424\Premium\Interfaces;
4
 
5
  // Exit if accessed directly
6
  if ( ! defined( 'ABSPATH' ) ) {
8
  }
9
 
10
  /**
11
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
12
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
13
  * @copyright (c) 2018 Webraftic Ltd
14
+ * @version 1.0
15
  */
16
  interface License {
17
+
18
  public function get_key();
19
+
20
  public function get_hidden_key();
21
+
22
  public function get_expiration_time( $format = 'time' );
23
+
24
  public function get_sites_quota();
25
+
26
  public function get_count_active_sites();
27
+
28
  public function is_valid();
29
+
30
  public function is_lifetime();
31
+
32
  }
libs/factory/core/includes/premium/class-factory-manager.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412\Premium;
4
 
5
  use Exception;
6
- use Wbcr_Factory412_Plugin;
7
 
8
  // Exit if accessed directly
9
  if ( ! defined( 'ABSPATH' ) ) {
@@ -11,77 +11,79 @@ if ( ! defined( 'ABSPATH' ) ) {
11
  }
12
 
13
  /**
14
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
15
- * @link https://webcraftic.com
16
- * @copyright (c) 2018 Webraftic Ltd
17
- * @version 1.0
18
  */
19
  class Manager {
20
-
21
  /**
22
- * @var Wbcr_Factory412_Plugin
 
 
23
  */
24
- protected $plugin;
25
-
26
  /**
27
- * @var \WBCR\Factory_412\Premium\Provider
28
  */
29
- protected $provider;
30
-
31
  /**
32
  * @var array
33
  */
34
  protected $settings;
35
-
36
  /**
37
  * Manager constructor.
38
  *
39
- * @param Wbcr_Factory412_Plugin $plugin
40
- * @param array $settings
41
  *
42
  * @throws Exception
43
  */
44
- public function __construct( Wbcr_Factory412_Plugin $plugin, array $settings ) {
45
  $this->plugin = $plugin;
46
  $this->settings = $settings;
47
- //Plugin_Updates_Manager( $this->plugin, $this->updates['premium'], true );
48
  }
49
-
50
  /**
51
- * @param Wbcr_Factory412_Plugin $plugin
52
- * @param array $settings
53
  *
54
- * @return \WBCR\Factory_Freemius_101\Premium\Provider
55
  * @throws Exception
56
  */
57
- public static function instance( Wbcr_Factory412_Plugin $plugin, array $settings ) {
58
  $premium_manager = new Manager( $plugin, $settings );
59
-
60
  return $premium_manager->instance_provider();
61
  }
62
-
63
  /**
64
  * @param $provider_name
65
  *
66
- * @return \WBCR\Factory_Freemius_101\Premium\Provider
67
  * @throws Exception
68
  */
69
  public function instance_provider() {
70
  $provider_name = $this->get_setting( 'provider' );
71
-
72
- if ( 'freemius' == $provider_name ) {
73
- return new \WBCR\Factory_Freemius_101\Premium\Provider( $this->plugin, $this->settings );
74
- } else if ( 'codecanyon' == $provider_name ) {
75
- //return new \WBCR\Factory_Codecanyon_000\Licensing\Provider( $this->plugin, $this->settings );
76
- throw new Exception( 'Codecanyon provider is not supported!' );
77
- } else if ( 'templatemonster' == $provider_name ) {
78
- //return new \WBCR\Factory_Themplatemonster_000\Licensing\Provider( $this->plugin, $this->settings );
79
- throw new Exception( 'Templatemonster provider is not supported!' );
80
  }
81
-
82
  throw new Exception( "Provider {$provider_name} is not supported!" );
83
  }
84
-
 
 
 
 
 
85
  protected function get_setting( $name ) {
86
  return isset( $this->settings[ $name ] ) ? $this->settings[ $name ] : null;
87
  }
1
  <?php
2
 
3
+ namespace WBCR\Factory_424\Premium;
4
 
5
  use Exception;
6
+ use Wbcr_Factory424_Plugin;
7
 
8
  // Exit if accessed directly
9
  if ( ! defined( 'ABSPATH' ) ) {
11
  }
12
 
13
  /**
14
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
15
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
 
 
16
  */
17
  class Manager {
18
+
19
  /**
20
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
21
+ * @since 4.1.6
22
+ * @var array
23
  */
24
+ public static $providers;
25
+
26
  /**
27
+ * @var Wbcr_Factory424_Plugin
28
  */
29
+ protected $plugin;
30
+
31
  /**
32
  * @var array
33
  */
34
  protected $settings;
35
+
36
  /**
37
  * Manager constructor.
38
  *
39
+ * @param Wbcr_Factory424_Plugin $plugin
40
+ * @param array $settings
41
  *
42
  * @throws Exception
43
  */
44
+ public function __construct( Wbcr_Factory424_Plugin $plugin, array $settings ) {
45
  $this->plugin = $plugin;
46
  $this->settings = $settings;
 
47
  }
48
+
49
  /**
50
+ * @param Wbcr_Factory424_Plugin $plugin
51
+ * @param array $settings
52
  *
53
+ * @return \WBCR\Factory_Freemius_112\Premium\Provider
54
  * @throws Exception
55
  */
56
+ public static function instance( Wbcr_Factory424_Plugin $plugin, array $settings ) {
57
  $premium_manager = new Manager( $plugin, $settings );
58
+
59
  return $premium_manager->instance_provider();
60
  }
61
+
62
  /**
63
  * @param $provider_name
64
  *
65
+ * @return \WBCR\Factory_Freemius_112\Premium\Provider
66
  * @throws Exception
67
  */
68
  public function instance_provider() {
69
  $provider_name = $this->get_setting( 'provider' );
70
+
71
+ if ( isset( self::$providers[ $provider_name ] ) && class_exists( self::$providers[ $provider_name ] ) ) {
72
+ if ( self::$providers[ $provider_name ] instanceof Provider ) {
73
+ throw new Exception( "Provider {$provider_name} must extend the class WBCR\Factory_424\Premium\Provider interface!" );
74
+ }
75
+
76
+ return new self::$providers[ $provider_name ]( $this->plugin, $this->settings );
 
 
77
  }
78
+
79
  throw new Exception( "Provider {$provider_name} is not supported!" );
80
  }
81
+
82
+ /**
83
+ * @param string $name
84
+ *
85
+ * @return mixed
86
+ */
87
  protected function get_setting( $name ) {
88
  return isset( $this->settings[ $name ] ) ? $this->settings[ $name ] : null;
89
  }
libs/factory/core/includes/premium/class-factory-provider-abstract.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412\Premium;
4
 
5
  use Exception;
6
- use Wbcr_Factory412_Plugin;
7
 
8
  // Exit if accessed directly
9
  if ( ! defined( 'ABSPATH' ) ) {
@@ -13,52 +13,50 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  /**
14
  * Выполняет проверку обновлений, обновления, скачивание плагинов
15
  *
16
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
17
- * @link https://webcraftic.com
18
- * @copyright (c) 2018 Webraftic Ltd
19
- * @version 1.0
20
  */
21
  abstract class Provider {
22
-
23
  /**
24
- * @var Wbcr_Factory412_Plugin
25
  */
26
  protected $plugin;
27
-
28
  /**
29
  * @var array
30
  */
31
  protected $settings;
32
-
33
  /**
34
  * @var bool
35
  */
36
  private $is_install_package;
37
-
38
  /**
39
  * Provider constructor.
40
  *
41
- * @param Wbcr_Factory412_Plugin $plugin
42
- * @param array $settings
43
  */
44
- public function __construct( Wbcr_Factory412_Plugin $plugin, array $settings ) {
45
  $this->plugin = $plugin;
46
  $this->settings = $settings;
47
-
48
- add_action( 'wbcr/factory/license_activate', array( $this, 'register_cron_hooks' ), 10, 2 );
49
- add_action( 'wbcr/factory/license_deactivate', array( $this, 'register_cron_hooks' ), 10, 2 );
50
- add_action( "{$this->plugin->getPluginName()}_license_autosync", array( $this, 'license_cron_sync' ) );
51
  }
52
-
53
  /**
54
  * @return array
55
  */
56
  public function get_settings() {
57
  return $this->settings;
58
  }
59
-
60
  /**
61
- * @param $name
62
  * @param bool $default
63
  *
64
  * @return bool|mixed
@@ -66,46 +64,14 @@ abstract class Provider {
66
  public function get_setting( $name, $default = false ) {
67
  return isset( $this->settings[ $name ] ) && ! empty( $this->settings[ $name ] ) ? $this->settings[ $name ] : $default;
68
  }
69
-
70
  /**
71
  * @return bool|mixed
72
  */
73
  public function get_price() {
74
  return $this->get_setting( 'price' );
75
  }
76
-
77
- /**
78
- * todo: Вынести с лицензионный менеджер
79
- *
80
- * @param array $license_info
81
- * @param string $plugin_name
82
- */
83
- public function register_cron_hooks( $license_info, $plugin_name ) {
84
- if ( $this->plugin->getPluginName() == $plugin_name ) {
85
- if ( ! wp_next_scheduled( "{$plugin_name}_license_autosync" ) ) {
86
- wp_schedule_event( time(), 'twicedaily', "{$plugin_name}_license_autosync" );
87
- }
88
- }
89
- }
90
-
91
- /**
92
- * todo: вынести в лицензионный менеджер
93
- *
94
- * @param array $license_info
95
- * @param string $plugin_name
96
- */
97
- public function clear_cron_hooks( $license_info, $plugin_name ) {
98
- if ( $this->plugin->getPluginName() == $plugin_name ) {
99
- if ( wp_next_scheduled( "{$plugin_name}_license_autosync" ) ) {
100
- wp_clear_scheduled_hook( "{$plugin_name}_license_autosync" );
101
- }
102
- }
103
- }
104
-
105
- public function license_cron_sync() {
106
- $this->sync();
107
- }
108
-
109
  /**
110
  * @return bool
111
  */
@@ -113,123 +79,156 @@ abstract class Provider {
113
  if ( ! is_null( $this->is_install_package ) ) {
114
  return $this->is_install_package;
115
  }
116
-
117
  $premium_package = $this->get_package_data();
118
-
119
  if ( ! empty( $premium_package ) && ! empty( $premium_package['basename'] ) ) {
120
  $basename_part = explode( '/', $premium_package['basename'] );
121
  $is_valid_basename = sizeof( $basename_part ) === 2;
122
-
123
  if ( $is_valid_basename && ! file_exists( WP_PLUGIN_DIR . '/' . $premium_package['basename'] ) ) {
124
  $this->delete_package();
125
  $this->is_install_package = false;
126
-
127
  return false;
128
  }
129
  }
130
-
131
  $this->is_install_package = ! empty( $premium_package );
132
-
133
  return $this->is_install_package;
134
  }
135
-
136
  /**
137
  * @return bool|mixed|null
138
  */
139
  public function get_package_data() {
140
  $premium_package = $this->plugin->getPopulateOption( 'premium_package' );
141
-
142
  if ( ! empty( $premium_package ) ) {
143
- return wp_parse_args( $premium_package, array(
144
  'basename' => null,
145
  'version' => null,
146
  'framework_version' => null
147
- ) );
148
  }
149
-
150
  return null;
151
  }
152
-
153
  /**
154
  * @param $plugin_data
155
  *
156
  * @throws Exception
157
  */
158
  public function update_package_data( array $package ) {
159
- $parsed_args = wp_parse_args( $package, array(
160
  'basename' => null,
161
  'version' => null,
162
  'framework_version' => null
163
- ) );
164
-
165
  if ( empty( $parsed_args['basename'] ) || empty( $parsed_args['version'] ) ) {
166
  throw new Exception( 'You must pass the required attributes (basename, version).' );
167
  }
168
-
169
  $this->plugin->updatePopulateOption( 'premium_package', $parsed_args );
170
  $this->is_install_package = true;
171
  }
172
-
173
  public function delete_package() {
174
  $this->plugin->deletePopulateOption( 'premium_package' );
175
  $this->is_install_package = false;
176
  }
177
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  /**
179
  * @return bool
180
  */
181
  abstract public function is_activate();
182
-
183
  /**
184
  * @return bool
185
  */
186
  abstract public function is_active();
187
-
188
  /**
189
  * @return string|null
190
  */
191
  abstract public function get_plan();
192
-
193
  /**
194
  * @return string|null
195
  */
196
  abstract public function get_billing_cycle();
197
-
198
  /**
199
- * @return \WBCR\Factory_412\Premium\Interfaces\License
200
  */
201
  abstract public function get_license();
202
-
203
  /**
204
  * @return string|null
205
  */
206
  abstract public function get_package_download_url();
207
-
208
  /**
209
  * @param string $key
210
  *
211
  * @return mixed
212
  */
213
  abstract public function activate( $key );
214
-
215
  /**
216
  * @return bool
217
  */
218
  abstract public function deactivate();
219
-
220
  /**
221
  * @return bool
222
  */
223
  abstract public function sync();
224
-
225
  /**
226
  * @return bool
227
  */
228
  abstract public function has_paid_subscription();
229
-
230
  /**
231
  * @return bool
232
  */
233
  abstract public function cancel_paid_subscription();
234
-
235
  }
1
  <?php
2
 
3
+ namespace WBCR\Factory_424\Premium;
4
 
5
  use Exception;
6
+ use Wbcr_Factory424_Plugin;
7
 
8
  // Exit if accessed directly
9
  if ( ! defined( 'ABSPATH' ) ) {
13
  /**
14
  * Выполняет проверку обновлений, обновления, скачивание плагинов
15
  *
16
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
17
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
18
+ *
19
+ * @version 1.0
20
  */
21
  abstract class Provider {
22
+
23
  /**
24
+ * @var Wbcr_Factory424_Plugin
25
  */
26
  protected $plugin;
27
+
28
  /**
29
  * @var array
30
  */
31
  protected $settings;
32
+
33
  /**
34
  * @var bool
35
  */
36
  private $is_install_package;
37
+
38
  /**
39
  * Provider constructor.
40
  *
41
+ * @param Wbcr_Factory424_Plugin $plugin
42
+ * @param array $settings
43
  */
44
+ public function __construct( Wbcr_Factory424_Plugin $plugin, array $settings ) {
45
  $this->plugin = $plugin;
46
  $this->settings = $settings;
47
+
48
+ $this->register_hooks();
 
 
49
  }
50
+
51
  /**
52
  * @return array
53
  */
54
  public function get_settings() {
55
  return $this->settings;
56
  }
57
+
58
  /**
59
+ * @param $name
60
  * @param bool $default
61
  *
62
  * @return bool|mixed
64
  public function get_setting( $name, $default = false ) {
65
  return isset( $this->settings[ $name ] ) && ! empty( $this->settings[ $name ] ) ? $this->settings[ $name ] : $default;
66
  }
67
+
68
  /**
69
  * @return bool|mixed
70
  */
71
  public function get_price() {
72
  return $this->get_setting( 'price' );
73
  }
74
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  /**
76
  * @return bool
77
  */
79
  if ( ! is_null( $this->is_install_package ) ) {
80
  return $this->is_install_package;
81
  }
82
+
83
  $premium_package = $this->get_package_data();
84
+
85
  if ( ! empty( $premium_package ) && ! empty( $premium_package['basename'] ) ) {
86
  $basename_part = explode( '/', $premium_package['basename'] );
87
  $is_valid_basename = sizeof( $basename_part ) === 2;
88
+
89
  if ( $is_valid_basename && ! file_exists( WP_PLUGIN_DIR . '/' . $premium_package['basename'] ) ) {
90
  $this->delete_package();
91
  $this->is_install_package = false;
92
+
93
  return false;
94
  }
95
  }
96
+
97
  $this->is_install_package = ! empty( $premium_package );
98
+
99
  return $this->is_install_package;
100
  }
101
+
102
  /**
103
  * @return bool|mixed|null
104
  */
105
  public function get_package_data() {
106
  $premium_package = $this->plugin->getPopulateOption( 'premium_package' );
107
+
108
  if ( ! empty( $premium_package ) ) {
109
+ return wp_parse_args( $premium_package, [
110
  'basename' => null,
111
  'version' => null,
112
  'framework_version' => null
113
+ ] );
114
  }
115
+
116
  return null;
117
  }
118
+
119
  /**
120
  * @param $plugin_data
121
  *
122
  * @throws Exception
123
  */
124
  public function update_package_data( array $package ) {
125
+ $parsed_args = wp_parse_args( $package, [
126
  'basename' => null,
127
  'version' => null,
128
  'framework_version' => null
129
+ ] );
130
+
131
  if ( empty( $parsed_args['basename'] ) || empty( $parsed_args['version'] ) ) {
132
  throw new Exception( 'You must pass the required attributes (basename, version).' );
133
  }
134
+
135
  $this->plugin->updatePopulateOption( 'premium_package', $parsed_args );
136
  $this->is_install_package = true;
137
  }
138
+
139
  public function delete_package() {
140
  $this->plugin->deletePopulateOption( 'premium_package' );
141
  $this->is_install_package = false;
142
  }
143
+
144
+ protected function register_hooks() {
145
+ /**
146
+ * Добавляет крон задачу на синхронизацию лицензии
147
+ *
148
+ * @param array $license_info
149
+ * @param string $provider
150
+ */
151
+ add_action( "{$this->plugin->getPluginName()}/factory/premium/license_activate", function ( $provider, $license_info ) {
152
+ if ( ! wp_next_scheduled( "{$this->plugin->getPluginName()}_license_autosync" ) ) {
153
+ wp_schedule_event( time(), 'twicedaily', "{$this->plugin->getPluginName()}_license_autosync" );
154
+ }
155
+ }, 10, 2 );
156
+
157
+ /**
158
+ * Удаляет крон задачу на синхронизацию лицензии, когда лицензия деактивирована
159
+ *
160
+ * @param array $license_info
161
+ * @param string $provider
162
+ */
163
+ add_action( "{$this->plugin->getPluginName()}/factory/premium/license_deactivate", function ( $provider, $license_info ) {
164
+ if ( wp_next_scheduled( "{$this->plugin->getPluginName()}_license_autosync" ) ) {
165
+ wp_clear_scheduled_hook( "{$this->plugin->getPluginName()}_license_autosync" );
166
+ }
167
+ }, 10, 2 );
168
+
169
+ /**
170
+ * Обработчик крон задачи на синхронизацию лицензии, выполняется 2 раза в день.
171
+ */
172
+ add_action( "{$this->plugin->getPluginName()}_license_autosync", function () {
173
+ $this->sync();
174
+ } );
175
+ }
176
+
177
  /**
178
  * @return bool
179
  */
180
  abstract public function is_activate();
181
+
182
  /**
183
  * @return bool
184
  */
185
  abstract public function is_active();
186
+
187
  /**
188
  * @return string|null
189
  */
190
  abstract public function get_plan();
191
+
192
  /**
193
  * @return string|null
194
  */
195
  abstract public function get_billing_cycle();
196
+
197
  /**
198
+ * @return \WBCR\Factory_424\Premium\Interfaces\License
199
  */
200
  abstract public function get_license();
201
+
202
  /**
203
  * @return string|null
204
  */
205
  abstract public function get_package_download_url();
206
+
207
  /**
208
  * @param string $key
209
  *
210
  * @return mixed
211
  */
212
  abstract public function activate( $key );
213
+
214
  /**
215
  * @return bool
216
  */
217
  abstract public function deactivate();
218
+
219
  /**
220
  * @return bool
221
  */
222
  abstract public function sync();
223
+
224
  /**
225
  * @return bool
226
  */
227
  abstract public function has_paid_subscription();
228
+
229
  /**
230
  * @return bool
231
  */
232
  abstract public function cancel_paid_subscription();
233
+
234
  }
libs/factory/core/includes/premium/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/core/includes/updates/class-factory-premium-upgrader.php CHANGED
@@ -1,12 +1,12 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412\Updates;
4
 
5
  use Exception;
6
  use Plugin_Installer_Skin;
7
  use Plugin_Upgrader;
8
- use Wbcr_Factory412_Plugin;
9
- use Wbcr_FactoryPages412_ImpressiveThemplate;
10
  use WP_Filesystem_Base;
11
  use WP_Upgrader;
12
  use WP_Upgrader_Skin;
@@ -17,109 +17,114 @@ if ( ! defined( 'ABSPATH' ) ) {
17
  }
18
 
19
  /**
20
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
21
- * @link https://webcraftic.com
22
  * @copyright (c) 2018 Webraftic Ltd
23
- * @version 1.0
24
  */
25
  class Premium_Upgrader extends Upgrader {
26
-
27
  /**
28
  * Тип апгрейдера, может быть default, premium
 
29
  * @var string
30
  */
31
  protected $type = 'premium';
32
-
33
  /**
34
  * Manager constructor.
35
  *
36
- * @param Wbcr_Factory412_Plugin $plugin
37
- * @param $args
38
- * @param bool $is_premium
39
- *
40
- * @throws Exception
41
  * @since 4.1.1
42
  *
 
 
 
 
 
 
43
  */
44
- public function __construct( Wbcr_Factory412_Plugin $plugin ) {
45
  parent::__construct( $plugin );
46
-
47
  $this->plugin_basename = null;
48
  $this->plugin_main_file = null;
49
  $this->plugin_absolute_path = null;
50
-
51
  if ( $this->plugin->premium->is_activate() && $this->plugin->premium->is_install_package() ) {
52
  $premium_package = $this->plugin->premium->get_package_data();
53
-
54
  if ( $premium_package ) {
55
  $this->plugin_basename = $premium_package['basename'];
56
  $this->plugin_main_file = WP_PLUGIN_DIR . '/' . $premium_package['basename'];
57
  $this->plugin_absolute_path = dirname( WP_PLUGIN_DIR . '/' . $premium_package['basename'] );
58
  }
59
  }
60
-
61
  if ( ! $this->repository->is_support_premium() ) {
62
  $settings = $this->get_settings();
63
  throw new Exception( "Repository {$settings['repository']} does not have support premium." );
64
  }
65
  }
66
-
67
  /**
68
  * @throws Exception
69
  */
70
  protected function set_repository() {
71
  $settings = $this->get_settings();
72
  $this->repository = $this->get_repository( $settings['repository'] );
73
-
74
  if ( $this->plugin->premium->is_activate() ) {
75
  $this->repository->init();
76
  }
77
  }
78
-
79
  /**
80
- * @throws Exception
81
  * @since 4.1.1
 
82
  */
83
  protected function init_hooks() {
84
  parent::init_hooks();
85
-
86
  if ( $this->need_intall_or_activate_premium() || $this->need_renew_license() || $this->need_activate_license() ) {
87
  // Показываем уведомление под бесплатным плагином, если требуется установить или активировать премиум пакет
88
  if ( $this->need_intall_or_activate_premium() ) {
89
  $free_plugin_base = $this->plugin->get_paths()->basename;
90
-
91
- add_action( "after_plugin_row_{$free_plugin_base}", array( $this, "notice_in_plugin_row" ), 100, 3 );
92
  }
93
-
94
  // Если установлен премиум пакет, то показываем уведомление под премиум плагином.
95
  if ( ( $this->need_renew_license() || $this->need_activate_license() ) && $this->plugin->premium->is_install_package() ) {
96
  $package = $this->plugin->premium->get_package_data();
97
  $premium_plugin_base = $package['basename'];
98
-
99
- add_action( "after_plugin_row_{$premium_plugin_base}", array( $this, "notice_in_plugin_row" ), 100, 3 );
100
  }
101
-
102
- add_action( "admin_print_styles-plugins.php", array( $this, "print_styles_for_plugin_row" ) );
103
- add_action( "wbcr_factory_notices_000_list", array( $this, "admin_notices_hook" ) );
104
- add_action( 'wbcr/factory/pages/impressive/print_all_notices', array(
105
  $this,
106
  'install_notice_in_plugin_interface'
107
- ), 10, 2 );
108
  }
109
-
110
- add_action( 'admin_init', array( $this, 'init_admin_actions' ) );
111
-
112
- add_action( 'deleted_plugin', array( $this, 'delete_plugin_hook' ), 10, 2 );
113
- add_action( 'upgrader_process_complete', array( $this, 'upgrader_process_complete_hook' ), 10, 2 );
114
  }
115
-
116
  /**
 
117
  * @since 4.1.1
118
  */
119
  public function init_admin_actions() {
120
- if ( isset( $_GET['wbcr_factory_premium_updates_action'] ) ) {
121
- $action = $this->plugin->request->get( 'wbcr_factory_premium_updates_action' );
122
-
 
 
123
  check_admin_referer( "factory_premium_{$action}" );
124
  try {
125
  switch ( $action ) {
@@ -137,7 +142,7 @@ class Premium_Upgrader extends Upgrader {
137
  break;
138
  case 'cancel_license':
139
  $this->plugin->premium->deactivate();
140
-
141
  break;
142
  }
143
  } catch( Exception $e ) {
@@ -145,99 +150,100 @@ class Premium_Upgrader extends Upgrader {
145
  }
146
  }
147
  }
148
-
149
  /**
150
  * Удаляет данные о пакете, если пользовать удалил премиум плагин
151
  *
152
- * @param $plugin_basename
153
- * @param $success
154
- *
155
  * @since 4.1.1
156
  *
 
 
 
157
  */
158
  public function delete_plugin_hook( $plugin_basename, $success ) {
159
  if ( ! $this->plugin->premium->is_install_package() ) {
160
  return;
161
  }
162
-
163
  $package = $this->plugin->premium->get_package_data();
164
-
165
  if ( $package['basename'] == $plugin_basename && $success ) {
166
  $this->plugin->premium->delete_package();
167
  }
168
  }
169
-
170
  /**
171
  * Выводит уведомление на всех страницах админ панели Wordpress
172
  *
 
 
173
  * @param $notices
174
  *
175
  * @return array
176
- * @since 4.1.1
177
- *
178
  */
179
- public function admin_notices_hook( $notices ) {
180
-
181
- if ( ! current_user_can( 'update_plugins' ) ) {
182
  return $notices;
183
  }
184
-
185
  if ( $this->need_intall_or_activate_premium() ) {
186
  $notice_text = $this->get_notice_text( 'please_activate_premium' );
187
-
188
  if ( ! $this->plugin->premium->is_install_package() ) {
189
  $notice_text = $this->get_notice_text( 'please_install_premium' );
190
  }
191
-
192
- $notices[] = array(
193
  'id' => 'please_install_premium_for_' . $this->plugin->getPluginName(),
194
  'type' => 'warning',
195
  'dismissible' => false,
196
  'dismiss_expires' => 0,
197
  'text' => "<p><b>{$this->plugin->getPluginTitle()}:</b> " . $notice_text . '</p>'
198
- );
199
  } else if ( $this->need_activate_license() ) {
200
- $notices[] = array(
201
  'id' => 'need_activate_premium_for_' . $this->plugin->getPluginName(),
202
  'type' => 'warning',
203
  'dismissible' => false,
204
  'dismiss_expires' => 0,
205
  'text' => "<p><b>{$this->plugin->getPluginTitle()}:</b> " . $this->get_notice_text( 'need_activate_license' ) . '</p>'
206
- );
207
  } else if ( $this->need_renew_license() ) {
208
  // todo: может быть перенести уведомление в премиум менеджер?
209
- $notices[] = array(
210
  'id' => 'license_exired_for_' . $this->plugin->getPluginName(),
211
  'type' => 'warning',
212
  'dismissible' => false,
213
  'dismiss_expires' => 0,
214
  'text' => "<p><b>{$this->plugin->getPluginTitle()}:</b> " . $this->get_notice_text( 'need_renew_license' ) . '</p>'
215
- );
216
  }
217
-
218
  return $notices;
219
  }
220
-
221
  /**
222
  * Выводит уведомление внутри интерфейса плагина, на всех страницах плагина.
223
  *
224
- * @param Wbcr_Factory412_Plugin $plugin
225
- * @param Wbcr_FactoryPages412_ImpressiveThemplate $obj
226
- *
227
- * @return void
228
  * @since 4.1.1
229
  *
 
 
 
 
 
230
  */
231
  public function install_notice_in_plugin_interface( $plugin, $obj ) {
232
  if ( $plugin->getPluginName() != $this->plugin->getPluginName() ) {
233
  return;
234
  }
235
-
236
  $notice_text = '';
237
-
238
  if ( $this->need_intall_or_activate_premium() ) {
239
  $notice_text = $this->get_notice_text( 'please_activate_premium' );
240
-
241
  if ( ! $this->plugin->premium->is_install_package() ) {
242
  $notice_text = $this->get_notice_text( 'please_install_premium' );
243
  }
@@ -246,34 +252,36 @@ class Premium_Upgrader extends Upgrader {
246
  } else if ( $this->need_renew_license() ) {
247
  $notice_text = $this->get_notice_text( 'need_renew_license' );
248
  }
249
-
250
  $obj->printWarningNotice( $notice_text );
251
  }
252
-
253
  /**
254
  * Выводит уведомление в строке плагина (на странице плагинов),
255
  * что нужно установить премиум плагин.
256
  *
257
- * @param string $plugin_file
258
- * @param array $plugin_data
 
259
  * @param string $status
260
  *
 
 
261
  * @return void
262
- * @since 4.1.1
263
- * @see WP_Plugins_List_Table
264
  *
265
  */
266
  public function notice_in_plugin_row( $plugin_file, $plugin_data, $status ) {
267
-
268
  if ( ! current_user_can( 'update_plugins' ) ) {
269
  return;
270
  };
271
-
272
  $notice_text = '';
273
-
274
  if ( $this->need_intall_or_activate_premium() ) {
275
  $notice_text = $this->get_notice_text( 'please_activate_premium' );
276
-
277
  if ( ! $this->plugin->premium->is_install_package() ) {
278
  $notice_text = $this->get_notice_text( 'please_install_premium' );
279
  }
@@ -282,7 +290,7 @@ class Premium_Upgrader extends Upgrader {
282
  } else if ( $this->need_renew_license() ) {
283
  $notice_text = $this->get_notice_text( 'need_renew_license' );
284
  }
285
-
286
  ?>
287
  <tr class="plugin-update-tr active update wbcr-factory-updates">
288
  <td colspan="3" class="plugin-update colspanchange">
@@ -295,21 +303,21 @@ class Premium_Upgrader extends Upgrader {
295
  </tr>
296
  <?php
297
  }
298
-
299
  /**
300
  * Печатает стили для уведомления о загрузке премиум версии на странице плагинов.
301
  *
302
- * @return void
303
  * @since 4.1.1
 
304
  */
305
  public function print_styles_for_plugin_row() {
306
-
307
  if ( ! current_user_can( 'update_plugins' ) ) {
308
  return;
309
  }
310
-
311
  $plugin_base = $this->plugin->get_paths()->basename;
312
-
313
  if ( $this->need_intall_or_activate_premium() ) {
314
  $message_background_color = '#f5e9f5';
315
  $message_border_color = '#dab9da';
@@ -321,7 +329,7 @@ class Premium_Upgrader extends Upgrader {
321
  $plugin_base = $package['basename'];
322
  }
323
  }
324
-
325
  ?>
326
  <style>
327
  tr[data-plugin="<?php echo $plugin_base; ?>"] th,
@@ -336,287 +344,302 @@ class Premium_Upgrader extends Upgrader {
336
  </style>
337
  <?php
338
  }
339
-
 
340
  /**
341
  * Обновляет данные о премиум пакете в базе данных, после обновления плагина.
342
  *
343
- * @param WP_Upgrader $upgrader_object
344
- * @param array $options
345
  *
 
346
  * @throws Exception
347
- * @since 4.1.1
348
- *
349
  */
350
- public function upgrader_process_complete_hook( $upgrader_object, $options ) {
351
- if ( ! empty( $options ) && $options['action'] == 'update' && $options['type'] == 'plugin' ) {
352
- if ( is_array( $options['plugins'] ) && in_array( $this->plugin_basename, $options['plugins'] ) ) {
 
 
 
 
 
 
 
 
 
353
  $this->update_package_data();
354
  }
355
  }
356
  }
357
-
358
  /**
359
- * @return array
360
  * @since 4.1.1
 
361
  */
362
  protected function get_settings() {
363
  $settings = $this->plugin->getPluginInfoAttr( 'license_settings' );
364
-
365
- $updates_settings = isset( $settings['updates_settings'] ) ? $settings['updates_settings'] : array();
366
-
367
  if ( is_array( $settings ) ) {
368
  $updates_settings['repository'] = $settings['provider'];
369
  $updates_settings['slug'] = $settings['slug'];
370
  }
371
-
372
- return wp_parse_args( $updates_settings, array(
373
  'repository' => 'wordpress',
374
  'slug' => '',
375
  'maybe_rollback' => false,
376
- 'rollback_settings' => array(
377
  'prev_stable_version' => '0.0.0'
378
- )
379
- ) );
380
  }
381
-
382
  /**
383
- * @return string
384
  * @since 4.1.1
 
385
  */
386
  protected function get_plugin_version() {
387
  if ( ! $this->plugin->premium->is_install_package() ) {
388
  return '0.0.0';
389
  }
390
-
391
  $package = $this->plugin->premium->get_package_data();
392
-
393
  return $package['version'];
394
  }
395
-
396
  /**
 
 
397
  * @param $args
398
  *
399
  * @return string
400
- * @since 4.1.1
401
- *
402
  */
403
  protected function get_admin_url( $args ) {
404
  $url = admin_url( 'plugins.php', $args );
405
-
406
  if ( $this->plugin->isNetworkActive() ) {
407
  $url = network_admin_url( 'plugins.php', $args );
408
  }
409
-
410
  return add_query_arg( $args, $url );
411
  }
412
-
413
  /**
 
 
414
  * @param string $action
415
  *
416
  * @return string
417
- * @since 4.1.1
418
- *
419
  */
420
  protected function get_action_url( $action ) {
421
- $args = array( 'wbcr_factory_premium_updates_action' => $action );
422
-
 
 
 
423
  return wp_nonce_url( $this->get_admin_url( $args ), "factory_premium_{$action}" );
424
  }
425
-
426
  /**
427
- * @return string
428
  * @since 4.1.1
 
429
  */
430
  protected function get_activate_premium_url() {
431
- $args = array(
432
  'action' => 'activate',
433
  'plugin' => $this->plugin_basename,
434
- );
435
-
436
  return wp_nonce_url( $this->get_admin_url( $args ), "activate-plugin_{$this->plugin_basename}" );
437
  }
438
-
439
  /**
440
  * Нужно установить или обновить премиум?
441
  *
442
- * @return bool
443
  * @since 4.1.1
 
444
  */
445
  protected function need_intall_or_activate_premium() {
446
  if ( $this->plugin->premium->is_activate() && $this->plugin->premium->is_active() ) {
447
  if ( $this->plugin->premium->is_install_package() && is_plugin_active( $this->plugin_basename ) ) {
448
  return false;
449
  }
450
-
451
  return true;
452
  }
453
-
454
  return false;
455
  }
456
-
457
  /**
458
  * Требуется активировать лицензию?
459
  *
460
- * @return bool
461
  * @since 4.1.1
 
462
  */
463
  protected function need_activate_license() {
464
  return ! $this->plugin->premium->is_activate() && $this->plugin->premium->is_install_package();
465
  }
466
-
467
  /**
468
  * Нужно продлить лицензию?
469
  *
470
- * @return bool
471
  * @since 4.1.1
 
472
  */
473
  protected function need_renew_license() {
474
  return $this->plugin->premium->is_activate() && ! $this->plugin->premium->is_active();
475
  }
476
-
477
  /**
478
- * @throws Exception
479
  * @since 4.1.1
 
480
  */
481
  protected function install() {
482
  global $wp_filesystem;
483
-
484
  if ( ! current_user_can( 'install_plugins' ) ) {
485
  throw new Exception( 'Sorry, you are not allowed to install plugins on this site.', 'not_allowed_install_plugin' );
486
  }
487
-
488
  if ( $this->plugin->premium->is_install_package() ) {
489
  return;
490
  }
491
-
492
  if ( ! $wp_filesystem ) {
493
  if ( ! function_exists( 'WP_Filesystem' ) ) {
494
  require_once( ABSPATH . 'wp-admin/includes/file.php' );
495
  }
496
  WP_Filesystem();
497
  }
498
-
499
  if ( ! WP_Filesystem( false, WP_PLUGIN_DIR ) ) {
500
  throw new Exception( 'You are not allowed to edt folders/files on this site', 'not_allowed_edit_filesystem' );
501
  } else {
502
-
503
  $download_url = $this->repository->get_download_url();
504
-
505
  /**
506
- * @param string $package Дополнительная информация о лицензии
507
- * @param string $plugin_name Имя плагина
508
- *
509
  * @since 4.1.1
 
 
 
 
510
  */
511
  do_action( 'wbcr/factory/premium/install_package', $download_url, $this->plugin->getPluginName() );
512
-
513
  // If plugin is installed before we update the premium package in database.
514
  // ------------------------------------------------------------------------
515
  $plugins = get_plugins( $plugin_folder = '' );
516
-
517
  if ( ! empty( $plugins ) ) {
518
  foreach ( (array) $plugins as $plugin_base => $plugin ) {
519
  $basename_parts = explode( '/', $plugin_base );
520
  if ( sizeof( $basename_parts ) == 2 && $basename_parts[0] == $this->plugin_slug ) {
521
-
522
  $this->plugin_basename = $plugin_base;
523
  $this->plugin_main_file = WP_PLUGIN_DIR . '/' . $plugin_base;
524
  $this->plugin_absolute_path = dirname( WP_PLUGIN_DIR . '/' . $plugin_base );
525
-
526
  $this->update_package_data();
527
-
528
  $package = $this->plugin->premium->get_package_data();
529
-
530
  /**
531
- * @param string $package Дополнительная информация о лицензии
532
- * @param string $plugin_name Имя плагина
533
- *
534
  * @since 4.1.1
 
 
 
 
535
  */
536
  do_action( 'wbcr/factory/premium/installed_package', $package, $this->plugin->getPluginName() );
537
-
538
  return;
539
  }
540
  }
541
  }
542
  // ------------------------------------------------------------------------
543
-
544
  require_once( ABSPATH . 'wp-admin/includes/file.php' );
545
  require_once( ABSPATH . 'wp-admin/includes/misc.php' );
546
-
547
  if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
548
  // Include required resources for the installation.
549
  require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
550
  }
551
-
552
- $skin_args = array(
553
  'type' => 'web',
554
  'title' => sprintf( 'Installing plugin: %s', $this->plugin->getPluginTitle() . ' Premium' ),
555
  'url' => esc_url_raw( $download_url ),
556
  'nonce' => 'install-plugin_' . $this->plugin_slug,
557
  'plugin' => '',
558
  'api' => null,
559
- 'extra' => array(
560
  'slug' => $this->plugin_slug
561
- ),
562
- );
563
-
564
  require_once( ABSPATH . 'wp-admin/admin-header.php' );
565
-
566
  if ( ! $this->plugin->premium->is_install_package() ) {
567
  $skin = new Plugin_Installer_Skin( $skin_args );
568
  } else {
569
  $skin = new WP_Upgrader_Skin( $skin_args );
570
  }
571
-
572
  $upgrader = new Plugin_Upgrader( $skin );
573
-
574
  if ( empty( $download_url ) ) {
575
  throw new Exception( 'You must pass the download url to upgrade up premium package.', "not_passed_download_url" );
576
  }
577
-
578
  $install_result = $upgrader->install( $download_url );
579
-
580
  include( ABSPATH . 'wp-admin/admin-footer.php' );
581
-
582
  if ( is_wp_error( $install_result ) ) {
583
  throw new Exception( $install_result->get_error_message(), $install_result->get_error_code() );
584
- } elseif ( is_wp_error( $skin->result ) ) {
585
  throw new Exception( $skin->result->get_error_message(), $skin->result->get_error_code() );
586
- } elseif ( is_null( $install_result ) ) {
587
  global $wp_filesystem;
588
-
589
  $error_code = 'unable_to_connect_to_filesystem';
590
  $error_message = 'Unable to connect to the filesystem. Please confirm your credentials.';
591
-
592
  // Pass through the error from WP_Filesystem if one was raised.
593
  if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
594
  $error_message = $wp_filesystem->errors->get_error_message();
595
  }
596
-
597
  throw new Exception( $error_message, $error_code );
598
  }
599
-
600
  $this->plugin_basename = $upgrader->plugin_info();
601
  $this->plugin_main_file = WP_PLUGIN_DIR . '/' . $this->plugin_basename;
602
  $this->plugin_absolute_path = dirname( WP_PLUGIN_DIR . '/' . $this->plugin_basename );
603
-
604
  $this->update_package_data();
605
-
606
  $package = $this->plugin->premium->get_package_data();
607
-
608
  /**
609
- * @param string $package Дополнительная информация о лицензии
610
- * @param string $plugin_name Имя плагина
611
- *
612
  * @since 4.1.1
 
 
 
 
613
  */
614
  do_action( 'wbcr/factory/premium/installed_package', $package, $this->plugin->getPluginName() );
615
-
616
  die();
617
  }
618
  }
619
-
620
  /**
621
  * @return bool
622
  * @throws Exception
@@ -625,17 +648,18 @@ class Premium_Upgrader extends Upgrader {
625
  if ( ! $this->plugin->premium->is_install_package() ) {
626
  return false;
627
  }
628
-
629
  $package = $this->plugin->premium->get_package_data();
630
-
631
  /**
632
- * @param string $package Дополнительная информация о лицензии
633
- * @param string $plugin_name Имя плагина
634
- *
635
  * @since 4.1.1
 
 
 
 
636
  */
637
  do_action( 'wbcr/factory/premium/delete_package', $package, $this->plugin->getPluginName() );
638
-
639
  if ( is_plugin_active( $package['basename'] ) ) {
640
  if ( is_multisite() && is_plugin_active_for_network( $package['basename'] ) ) {
641
  deactivate_plugins( $package['basename'], false, true );
@@ -643,122 +667,126 @@ class Premium_Upgrader extends Upgrader {
643
  deactivate_plugins( $package['basename'] );
644
  }
645
  }
646
-
647
- $result = delete_plugins( array( $package['basename'] ) );
648
-
649
  if ( is_wp_error( $result ) ) {
650
  throw new Exception( $result->get_error_message(), $result->get_error_code() );
651
  }
652
-
653
  $this->plugin->premium->delete_package();
654
-
655
  /**
656
- * @param string $package Дополнительная информация о лицензии
657
- * @param string $plugin_name Имя плагина
658
- *
659
  * @since 4.1.1
 
 
 
 
660
  */
661
  do_action( 'wbcr/factory/premium/deleted_package', $package, $this->plugin->getPluginName() );
662
-
663
  return true;
664
  }
665
-
666
  /**
667
- * @return bool
668
  * @since 4.1.1
 
669
  */
670
  protected function deactivate() {
671
  if ( ! $this->plugin->premium->is_install_package() || ! is_plugin_active( $this->plugin_basename ) ) {
672
  return false;
673
  }
674
-
675
  $package = $this->plugin->premium->get_package_data();
676
-
677
  /**
678
- * @param string $package Дополнительная информация о лицензии
679
- * @param string $plugin_name Имя плагина
680
- *
681
  * @since 4.1.1
 
 
 
 
682
  */
683
  do_action( 'wbcr/factory/premium/deactivate_package', $package, $this->plugin->getPluginName() );
684
-
685
  if ( is_multisite() && is_plugin_active_for_network( $this->plugin_basename ) ) {
686
  deactivate_plugins( $this->plugin_basename, false, true );
687
  } else {
688
  deactivate_plugins( $this->plugin_basename );
689
  }
690
-
691
  /**
692
- * @param string $package Дополнительная информация о лицензии
693
- * @param string $plugin_name Имя плагина
694
- *
695
  * @since 4.1.1
 
 
 
 
696
  */
697
  do_action( 'wbcr/factory/premium/deactivated_package', $package, $this->plugin->getPluginName() );
698
-
699
  return true;
700
  }
701
-
702
  /**
 
 
703
  * @param array $plugin_data
704
  *
705
  * @throws Exception
706
- * @since 4.1.1
707
- *
708
  */
709
  protected function update_package_data() {
710
-
711
  if ( ! $this->plugin_main_file ) {
712
  return;
713
  }
714
-
715
- $default_headers = array(
716
  'Version' => 'Version',
717
  'FrameworkVersion' => 'Framework Version'
718
- );
719
-
720
  $plugin_data = get_file_data( $this->plugin_main_file, $default_headers, 'plugin' );
721
-
722
- $this->plugin->premium->update_package_data( array(
723
  'basename' => $this->plugin_basename,
724
  'version' => $plugin_data['Version'],
725
  'framework_version' => isset( $plugin_data['FrameworkVersion'] ) ? $plugin_data['FrameworkVersion'] : null,
726
- ) );
727
  }
728
-
729
  /**
 
 
730
  * @param string $type
731
  *
732
  * @return string|null
733
- * @since 4.1.1
734
- *
735
  */
736
  private function get_notice_text( $type ) {
737
  $upgrade_url = $this->get_action_url( 'install' );
738
  $activate_plugin_url = $this->get_activate_premium_url();
739
  $cancel_license_url = $this->get_action_url( 'cancel_license' );
740
-
741
- $texts = array(
742
- 'need_activate_license' => __( 'License activation required. A license is required to get premium plugin updates, as well as to get additional services.', 'wbcr_factory_412' ),
743
- 'need_renew_license' => __( 'Your license has expired. You can no longer get premium plugin updates, premium support and your access to Webcraftic services has been suspended.', 'wbcr_factory_412' ),
744
  'please_install_premium' => sprintf( __( 'Congratulations, you have activated a premium license! Please install premium add-on to use pro features now.
745
- <a href="%s">Install</a> premium add-on or <a href="%s">cancel</a> license.', 'wbcr_factory_412' ), $upgrade_url, $cancel_license_url ),
746
  'please_activate_premium' => sprintf( __( 'Congratulations, you have activated a premium license! Please activate premium add-on to use pro features now.
747
- <a href="%s">Activate</a> premium add-on or <a href="%s">cancel</a> license.', 'wbcr_factory_412' ), $activate_plugin_url, $cancel_license_url )
748
- );
749
-
750
  if ( isset( $texts[ $type ] ) ) {
751
-
752
  /**
753
- * @param array $messages
 
754
  * @param string $type
755
  * @param string $plugin_name
756
  *
757
- * @since 4.1.1
758
  */
759
  return apply_filters( 'wbcr/factory/premium/notice_text', $texts[ $type ], $type, $this->plugin->getPluginName() );
760
  }
761
-
762
  return null;
763
  }
764
  }
1
  <?php
2
 
3
+ namespace WBCR\Factory_424\Updates;
4
 
5
  use Exception;
6
  use Plugin_Installer_Skin;
7
  use Plugin_Upgrader;
8
+ use Wbcr_Factory424_Plugin;
9
+ use Wbcr_FactoryPages424_ImpressiveThemplate;
10
  use WP_Filesystem_Base;
11
  use WP_Upgrader;
12
  use WP_Upgrader_Skin;
17
  }
18
 
19
  /**
20
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
21
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
22
  * @copyright (c) 2018 Webraftic Ltd
23
+ * @version 1.0
24
  */
25
  class Premium_Upgrader extends Upgrader {
26
+
27
  /**
28
  * Тип апгрейдера, может быть default, premium
29
+ *
30
  * @var string
31
  */
32
  protected $type = 'premium';
33
+
34
  /**
35
  * Manager constructor.
36
  *
 
 
 
 
 
37
  * @since 4.1.1
38
  *
39
+ * @param $args
40
+ * @param bool $is_premium
41
+ *
42
+ * @param Wbcr_Factory424_Plugin $plugin
43
+ *
44
+ * @throws Exception
45
  */
46
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
47
  parent::__construct( $plugin );
48
+
49
  $this->plugin_basename = null;
50
  $this->plugin_main_file = null;
51
  $this->plugin_absolute_path = null;
52
+
53
  if ( $this->plugin->premium->is_activate() && $this->plugin->premium->is_install_package() ) {
54
  $premium_package = $this->plugin->premium->get_package_data();
55
+
56
  if ( $premium_package ) {
57
  $this->plugin_basename = $premium_package['basename'];
58
  $this->plugin_main_file = WP_PLUGIN_DIR . '/' . $premium_package['basename'];
59
  $this->plugin_absolute_path = dirname( WP_PLUGIN_DIR . '/' . $premium_package['basename'] );
60
  }
61
  }
62
+
63
  if ( ! $this->repository->is_support_premium() ) {
64
  $settings = $this->get_settings();
65
  throw new Exception( "Repository {$settings['repository']} does not have support premium." );
66
  }
67
  }
68
+
69
  /**
70
  * @throws Exception
71
  */
72
  protected function set_repository() {
73
  $settings = $this->get_settings();
74
  $this->repository = $this->get_repository( $settings['repository'] );
75
+
76
  if ( $this->plugin->premium->is_activate() ) {
77
  $this->repository->init();
78
  }
79
  }
80
+
81
  /**
 
82
  * @since 4.1.1
83
+ * @throws Exception
84
  */
85
  protected function init_hooks() {
86
  parent::init_hooks();
87
+
88
  if ( $this->need_intall_or_activate_premium() || $this->need_renew_license() || $this->need_activate_license() ) {
89
  // Показываем уведомление под бесплатным плагином, если требуется установить или активировать премиум пакет
90
  if ( $this->need_intall_or_activate_premium() ) {
91
  $free_plugin_base = $this->plugin->get_paths()->basename;
92
+
93
+ add_action( "after_plugin_row_{$free_plugin_base}", [ $this, "notice_in_plugin_row" ], 100, 3 );
94
  }
95
+
96
  // Если установлен премиум пакет, то показываем уведомление под премиум плагином.
97
  if ( ( $this->need_renew_license() || $this->need_activate_license() ) && $this->plugin->premium->is_install_package() ) {
98
  $package = $this->plugin->premium->get_package_data();
99
  $premium_plugin_base = $package['basename'];
100
+
101
+ add_action( "after_plugin_row_{$premium_plugin_base}", [ $this, "notice_in_plugin_row" ], 100, 3 );
102
  }
103
+
104
+ add_action( "admin_print_styles-plugins.php", [ $this, "print_styles_for_plugin_row" ] );
105
+ add_action( "wbcr/factory/admin_notices", [ $this, "admin_notices_hook" ], 10, 2 );
106
+ add_action( 'wbcr/factory/pages/impressive/print_all_notices', [
107
  $this,
108
  'install_notice_in_plugin_interface'
109
+ ], 10, 2 );
110
  }
111
+
112
+ add_action( 'admin_init', [ $this, 'init_admin_actions' ] );
113
+
114
+ add_action( 'deleted_plugin', [ $this, 'delete_plugin_hook' ], 10, 2 );
115
+ add_action( 'upgrader_process_complete', [ $this, 'upgrader_process_complete_hook' ], 10, 2 );
116
  }
117
+
118
  /**
119
+ * @since 4.2.2 Fixed bug with plugins namespace (ISW-4)
120
  * @since 4.1.1
121
  */
122
  public function init_admin_actions() {
123
+ $plugin_slug = $this->plugin->request->get( 'wfactory_premium_updates_plugin', null );
124
+
125
+ if ( isset( $_GET['wfactory_premium_updates_action'] ) && $this->plugin_slug === $plugin_slug ) {
126
+ $action = $this->plugin->request->get( 'wfactory_premium_updates_action' );
127
+
128
  check_admin_referer( "factory_premium_{$action}" );
129
  try {
130
  switch ( $action ) {
142
  break;
143
  case 'cancel_license':
144
  $this->plugin->premium->deactivate();
145
+
146
  break;
147
  }
148
  } catch( Exception $e ) {
150
  }
151
  }
152
  }
153
+
154
  /**
155
  * Удаляет данные о пакете, если пользовать удалил премиум плагин
156
  *
 
 
 
157
  * @since 4.1.1
158
  *
159
+ * @param $success
160
+ *
161
+ * @param $plugin_basename
162
  */
163
  public function delete_plugin_hook( $plugin_basename, $success ) {
164
  if ( ! $this->plugin->premium->is_install_package() ) {
165
  return;
166
  }
167
+
168
  $package = $this->plugin->premium->get_package_data();
169
+
170
  if ( $package['basename'] == $plugin_basename && $success ) {
171
  $this->plugin->premium->delete_package();
172
  }
173
  }
174
+
175
  /**
176
  * Выводит уведомление на всех страницах админ панели Wordpress
177
  *
178
+ * @since 4.1.1
179
+ *
180
  * @param $notices
181
  *
182
  * @return array
 
 
183
  */
184
+ public function admin_notices_hook( $notices, $plugin_name ) {
185
+
186
+ if ( $plugin_name !== $this->plugin->getPluginName() || ! current_user_can( 'update_plugins' ) ) {
187
  return $notices;
188
  }
189
+
190
  if ( $this->need_intall_or_activate_premium() ) {
191
  $notice_text = $this->get_notice_text( 'please_activate_premium' );
192
+
193
  if ( ! $this->plugin->premium->is_install_package() ) {
194
  $notice_text = $this->get_notice_text( 'please_install_premium' );
195
  }
196
+
197
+ $notices[] = [
198
  'id' => 'please_install_premium_for_' . $this->plugin->getPluginName(),
199
  'type' => 'warning',
200
  'dismissible' => false,
201
  'dismiss_expires' => 0,
202
  'text' => "<p><b>{$this->plugin->getPluginTitle()}:</b> " . $notice_text . '</p>'
203
+ ];
204
  } else if ( $this->need_activate_license() ) {
205
+ $notices[] = [
206
  'id' => 'need_activate_premium_for_' . $this->plugin->getPluginName(),
207
  'type' => 'warning',
208
  'dismissible' => false,
209
  'dismiss_expires' => 0,
210
  'text' => "<p><b>{$this->plugin->getPluginTitle()}:</b> " . $this->get_notice_text( 'need_activate_license' ) . '</p>'
211
+ ];
212
  } else if ( $this->need_renew_license() ) {
213
  // todo: может быть перенести уведомление в премиум менеджер?
214
+ $notices[] = [
215
  'id' => 'license_exired_for_' . $this->plugin->getPluginName(),
216
  'type' => 'warning',
217
  'dismissible' => false,
218
  'dismiss_expires' => 0,
219
  'text' => "<p><b>{$this->plugin->getPluginTitle()}:</b> " . $this->get_notice_text( 'need_renew_license' ) . '</p>'
220
+ ];
221
  }
222
+
223
  return $notices;
224
  }
225
+
226
  /**
227
  * Выводит уведомление внутри интерфейса плагина, на всех страницах плагина.
228
  *
 
 
 
 
229
  * @since 4.1.1
230
  *
231
+ * @param Wbcr_FactoryPages424_ImpressiveThemplate $obj
232
+ *
233
+ * @param Wbcr_Factory424_Plugin $plugin
234
+ *
235
+ * @return void
236
  */
237
  public function install_notice_in_plugin_interface( $plugin, $obj ) {
238
  if ( $plugin->getPluginName() != $this->plugin->getPluginName() ) {
239
  return;
240
  }
241
+
242
  $notice_text = '';
243
+
244
  if ( $this->need_intall_or_activate_premium() ) {
245
  $notice_text = $this->get_notice_text( 'please_activate_premium' );
246
+
247
  if ( ! $this->plugin->premium->is_install_package() ) {
248
  $notice_text = $this->get_notice_text( 'please_install_premium' );
249
  }
252
  } else if ( $this->need_renew_license() ) {
253
  $notice_text = $this->get_notice_text( 'need_renew_license' );
254
  }
255
+
256
  $obj->printWarningNotice( $notice_text );
257
  }
258
+
259
  /**
260
  * Выводит уведомление в строке плагина (на странице плагинов),
261
  * что нужно установить премиум плагин.
262
  *
263
+ * @since 4.1.1
264
+ *
265
+ * @param array $plugin_data
266
  * @param string $status
267
  *
268
+ * @param string $plugin_file
269
+ *
270
  * @return void
271
+ * @see WP_Plugins_List_Table
 
272
  *
273
  */
274
  public function notice_in_plugin_row( $plugin_file, $plugin_data, $status ) {
275
+
276
  if ( ! current_user_can( 'update_plugins' ) ) {
277
  return;
278
  };
279
+
280
  $notice_text = '';
281
+
282
  if ( $this->need_intall_or_activate_premium() ) {
283
  $notice_text = $this->get_notice_text( 'please_activate_premium' );
284
+
285
  if ( ! $this->plugin->premium->is_install_package() ) {
286
  $notice_text = $this->get_notice_text( 'please_install_premium' );
287
  }
290
  } else if ( $this->need_renew_license() ) {
291
  $notice_text = $this->get_notice_text( 'need_renew_license' );
292
  }
293
+
294
  ?>
295
  <tr class="plugin-update-tr active update wbcr-factory-updates">
296
  <td colspan="3" class="plugin-update colspanchange">
303
  </tr>
304
  <?php
305
  }
306
+
307
  /**
308
  * Печатает стили для уведомления о загрузке премиум версии на странице плагинов.
309
  *
 
310
  * @since 4.1.1
311
+ * @return void
312
  */
313
  public function print_styles_for_plugin_row() {
314
+
315
  if ( ! current_user_can( 'update_plugins' ) ) {
316
  return;
317
  }
318
+
319
  $plugin_base = $this->plugin->get_paths()->basename;
320
+
321
  if ( $this->need_intall_or_activate_premium() ) {
322
  $message_background_color = '#f5e9f5';
323
  $message_border_color = '#dab9da';
329
  $plugin_base = $package['basename'];
330
  }
331
  }
332
+
333
  ?>
334
  <style>
335
  tr[data-plugin="<?php echo $plugin_base; ?>"] th,
344
  </style>
345
  <?php
346
  }
347
+
348
+
349
  /**
350
  * Обновляет данные о премиум пакете в базе данных, после обновления плагина.
351
  *
352
+ * @param WP_Upgrader $wp_upgrader WP_Upgrader instance.
353
+ * @param array $hook_extra Array of bulk item update data.
354
  *
355
+ * @return void
356
  * @throws Exception
 
 
357
  */
358
+ public function upgrader_process_complete_hook( $upgrader_object, $hook_extra ) {
359
+ if ( ! empty( $hook_extra ) && $hook_extra['action'] == 'update' && $hook_extra['type'] == 'plugin' ) {
360
+
361
+ # if it isn't bulk upgrade
362
+ if ( isset( $hook_extra['plugin'] ) && $this->plugin_basename === $hook_extra['plugin'] ) {
363
+ $this->update_package_data();
364
+
365
+ return;
366
+ }
367
+
368
+ # if it is bulk upgrade
369
+ if ( is_array( $hook_extra['plugins'] ) && in_array( $this->plugin_basename, $hook_extra['plugins'] ) ) {
370
  $this->update_package_data();
371
  }
372
  }
373
  }
374
+
375
  /**
 
376
  * @since 4.1.1
377
+ * @return array
378
  */
379
  protected function get_settings() {
380
  $settings = $this->plugin->getPluginInfoAttr( 'license_settings' );
381
+
382
+ $updates_settings = isset( $settings['updates_settings'] ) ? $settings['updates_settings'] : [];
383
+
384
  if ( is_array( $settings ) ) {
385
  $updates_settings['repository'] = $settings['provider'];
386
  $updates_settings['slug'] = $settings['slug'];
387
  }
388
+
389
+ return wp_parse_args( $updates_settings, [
390
  'repository' => 'wordpress',
391
  'slug' => '',
392
  'maybe_rollback' => false,
393
+ 'rollback_settings' => [
394
  'prev_stable_version' => '0.0.0'
395
+ ]
396
+ ] );
397
  }
398
+
399
  /**
 
400
  * @since 4.1.1
401
+ * @return string
402
  */
403
  protected function get_plugin_version() {
404
  if ( ! $this->plugin->premium->is_install_package() ) {
405
  return '0.0.0';
406
  }
407
+
408
  $package = $this->plugin->premium->get_package_data();
409
+
410
  return $package['version'];
411
  }
412
+
413
  /**
414
+ * @since 4.1.1
415
+ *
416
  * @param $args
417
  *
418
  * @return string
 
 
419
  */
420
  protected function get_admin_url( $args ) {
421
  $url = admin_url( 'plugins.php', $args );
422
+
423
  if ( $this->plugin->isNetworkActive() ) {
424
  $url = network_admin_url( 'plugins.php', $args );
425
  }
426
+
427
  return add_query_arg( $args, $url );
428
  }
429
+
430
  /**
431
+ * @since 4.1.1
432
+ *
433
  * @param string $action
434
  *
435
  * @return string
 
 
436
  */
437
  protected function get_action_url( $action ) {
438
+ $args = [
439
+ 'wfactory_premium_updates_action' => $action,
440
+ 'wfactory_premium_updates_plugin' => $this->plugin_slug
441
+ ];
442
+
443
  return wp_nonce_url( $this->get_admin_url( $args ), "factory_premium_{$action}" );
444
  }
445
+
446
  /**
 
447
  * @since 4.1.1
448
+ * @return string
449
  */
450
  protected function get_activate_premium_url() {
451
+ $args = [
452
  'action' => 'activate',
453
  'plugin' => $this->plugin_basename,
454
+ ];
455
+
456
  return wp_nonce_url( $this->get_admin_url( $args ), "activate-plugin_{$this->plugin_basename}" );
457
  }
458
+
459
  /**
460
  * Нужно установить или обновить премиум?
461
  *
 
462
  * @since 4.1.1
463
+ * @return bool
464
  */
465
  protected function need_intall_or_activate_premium() {
466
  if ( $this->plugin->premium->is_activate() && $this->plugin->premium->is_active() ) {
467
  if ( $this->plugin->premium->is_install_package() && is_plugin_active( $this->plugin_basename ) ) {
468
  return false;
469
  }
470
+
471
  return true;
472
  }
473
+
474
  return false;
475
  }
476
+
477
  /**
478
  * Требуется активировать лицензию?
479
  *
 
480
  * @since 4.1.1
481
+ * @return bool
482
  */
483
  protected function need_activate_license() {
484
  return ! $this->plugin->premium->is_activate() && $this->plugin->premium->is_install_package();
485
  }
486
+
487
  /**
488
  * Нужно продлить лицензию?
489
  *
 
490
  * @since 4.1.1
491
+ * @return bool
492
  */
493
  protected function need_renew_license() {
494
  return $this->plugin->premium->is_activate() && ! $this->plugin->premium->is_active();
495
  }
496
+
497
  /**
 
498
  * @since 4.1.1
499
+ * @throws Exception
500
  */
501
  protected function install() {
502
  global $wp_filesystem;
503
+
504
  if ( ! current_user_can( 'install_plugins' ) ) {
505
  throw new Exception( 'Sorry, you are not allowed to install plugins on this site.', 'not_allowed_install_plugin' );
506
  }
507
+
508
  if ( $this->plugin->premium->is_install_package() ) {
509
  return;
510
  }
511
+
512
  if ( ! $wp_filesystem ) {
513
  if ( ! function_exists( 'WP_Filesystem' ) ) {
514
  require_once( ABSPATH . 'wp-admin/includes/file.php' );
515
  }
516
  WP_Filesystem();
517
  }
518
+
519
  if ( ! WP_Filesystem( false, WP_PLUGIN_DIR ) ) {
520
  throw new Exception( 'You are not allowed to edt folders/files on this site', 'not_allowed_edit_filesystem' );
521
  } else {
522
+
523
  $download_url = $this->repository->get_download_url();
524
+
525
  /**
 
 
 
526
  * @since 4.1.1
527
+ *
528
+ * @param string $plugin_name Имя плагина
529
+ *
530
+ * @param string $package Дополнительная информация о лицензии
531
  */
532
  do_action( 'wbcr/factory/premium/install_package', $download_url, $this->plugin->getPluginName() );
533
+
534
  // If plugin is installed before we update the premium package in database.
535
  // ------------------------------------------------------------------------
536
  $plugins = get_plugins( $plugin_folder = '' );
537
+
538
  if ( ! empty( $plugins ) ) {
539
  foreach ( (array) $plugins as $plugin_base => $plugin ) {
540
  $basename_parts = explode( '/', $plugin_base );
541
  if ( sizeof( $basename_parts ) == 2 && $basename_parts[0] == $this->plugin_slug ) {
542
+
543
  $this->plugin_basename = $plugin_base;
544
  $this->plugin_main_file = WP_PLUGIN_DIR . '/' . $plugin_base;
545
  $this->plugin_absolute_path = dirname( WP_PLUGIN_DIR . '/' . $plugin_base );
546
+
547
  $this->update_package_data();
548
+
549
  $package = $this->plugin->premium->get_package_data();
550
+
551
  /**
 
 
 
552
  * @since 4.1.1
553
+ *
554
+ * @param string $plugin_name Имя плагина
555
+ *
556
+ * @param string $package Дополнительная информация о лицензии
557
  */
558
  do_action( 'wbcr/factory/premium/installed_package', $package, $this->plugin->getPluginName() );
559
+
560
  return;
561
  }
562
  }
563
  }
564
  // ------------------------------------------------------------------------
565
+
566
  require_once( ABSPATH . 'wp-admin/includes/file.php' );
567
  require_once( ABSPATH . 'wp-admin/includes/misc.php' );
568
+
569
  if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
570
  // Include required resources for the installation.
571
  require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
572
  }
573
+
574
+ $skin_args = [
575
  'type' => 'web',
576
  'title' => sprintf( 'Installing plugin: %s', $this->plugin->getPluginTitle() . ' Premium' ),
577
  'url' => esc_url_raw( $download_url ),
578
  'nonce' => 'install-plugin_' . $this->plugin_slug,
579
  'plugin' => '',
580
  'api' => null,
581
+ 'extra' => [
582
  'slug' => $this->plugin_slug
583
+ ],
584
+ ];
585
+
586
  require_once( ABSPATH . 'wp-admin/admin-header.php' );
587
+
588
  if ( ! $this->plugin->premium->is_install_package() ) {
589
  $skin = new Plugin_Installer_Skin( $skin_args );
590
  } else {
591
  $skin = new WP_Upgrader_Skin( $skin_args );
592
  }
593
+
594
  $upgrader = new Plugin_Upgrader( $skin );
595
+
596
  if ( empty( $download_url ) ) {
597
  throw new Exception( 'You must pass the download url to upgrade up premium package.', "not_passed_download_url" );
598
  }
599
+
600
  $install_result = $upgrader->install( $download_url );
601
+
602
  include( ABSPATH . 'wp-admin/admin-footer.php' );
603
+
604
  if ( is_wp_error( $install_result ) ) {
605
  throw new Exception( $install_result->get_error_message(), $install_result->get_error_code() );
606
+ } else if ( is_wp_error( $skin->result ) ) {
607
  throw new Exception( $skin->result->get_error_message(), $skin->result->get_error_code() );
608
+ } else if ( is_null( $install_result ) ) {
609
  global $wp_filesystem;
610
+
611
  $error_code = 'unable_to_connect_to_filesystem';
612
  $error_message = 'Unable to connect to the filesystem. Please confirm your credentials.';
613
+
614
  // Pass through the error from WP_Filesystem if one was raised.
615
  if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
616
  $error_message = $wp_filesystem->errors->get_error_message();
617
  }
618
+
619
  throw new Exception( $error_message, $error_code );
620
  }
621
+
622
  $this->plugin_basename = $upgrader->plugin_info();
623
  $this->plugin_main_file = WP_PLUGIN_DIR . '/' . $this->plugin_basename;
624
  $this->plugin_absolute_path = dirname( WP_PLUGIN_DIR . '/' . $this->plugin_basename );
625
+
626
  $this->update_package_data();
627
+
628
  $package = $this->plugin->premium->get_package_data();
629
+
630
  /**
 
 
 
631
  * @since 4.1.1
632
+ *
633
+ * @param string $plugin_name Имя плагина
634
+ *
635
+ * @param string $package Дополнительная информация о лицензии
636
  */
637
  do_action( 'wbcr/factory/premium/installed_package', $package, $this->plugin->getPluginName() );
638
+
639
  die();
640
  }
641
  }
642
+
643
  /**
644
  * @return bool
645
  * @throws Exception
648
  if ( ! $this->plugin->premium->is_install_package() ) {
649
  return false;
650
  }
651
+
652
  $package = $this->plugin->premium->get_package_data();
653
+
654
  /**
 
 
 
655
  * @since 4.1.1
656
+ *
657
+ * @param string $plugin_name Имя плагина
658
+ *
659
+ * @param string $package Дополнительная информация о лицензии
660
  */
661
  do_action( 'wbcr/factory/premium/delete_package', $package, $this->plugin->getPluginName() );
662
+
663
  if ( is_plugin_active( $package['basename'] ) ) {
664
  if ( is_multisite() && is_plugin_active_for_network( $package['basename'] ) ) {
665
  deactivate_plugins( $package['basename'], false, true );
667
  deactivate_plugins( $package['basename'] );
668
  }
669
  }
670
+
671
+ $result = delete_plugins( [ $package['basename'] ] );
672
+
673
  if ( is_wp_error( $result ) ) {
674
  throw new Exception( $result->get_error_message(), $result->get_error_code() );
675
  }
676
+
677
  $this->plugin->premium->delete_package();
678
+
679
  /**
 
 
 
680
  * @since 4.1.1
681
+ *
682
+ * @param string $plugin_name Имя плагина
683
+ *
684
+ * @param string $package Дополнительная информация о лицензии
685
  */
686
  do_action( 'wbcr/factory/premium/deleted_package', $package, $this->plugin->getPluginName() );
687
+
688
  return true;
689
  }
690
+
691
  /**
 
692
  * @since 4.1.1
693
+ * @return bool
694
  */
695
  protected function deactivate() {
696
  if ( ! $this->plugin->premium->is_install_package() || ! is_plugin_active( $this->plugin_basename ) ) {
697
  return false;
698
  }
699
+
700
  $package = $this->plugin->premium->get_package_data();
701
+
702
  /**
 
 
 
703
  * @since 4.1.1
704
+ *
705
+ * @param string $plugin_name Имя плагина
706
+ *
707
+ * @param string $package Дополнительная информация о лицензии
708
  */
709
  do_action( 'wbcr/factory/premium/deactivate_package', $package, $this->plugin->getPluginName() );
710
+
711
  if ( is_multisite() && is_plugin_active_for_network( $this->plugin_basename ) ) {
712
  deactivate_plugins( $this->plugin_basename, false, true );
713
  } else {
714
  deactivate_plugins( $this->plugin_basename );
715
  }
716
+
717
  /**
 
 
 
718
  * @since 4.1.1
719
+ *
720
+ * @param string $plugin_name Имя плагина
721
+ *
722
+ * @param string $package Дополнительная информация о лицензии
723
  */
724
  do_action( 'wbcr/factory/premium/deactivated_package', $package, $this->plugin->getPluginName() );
725
+
726
  return true;
727
  }
728
+
729
  /**
730
+ * @since 4.1.1
731
+ *
732
  * @param array $plugin_data
733
  *
734
  * @throws Exception
 
 
735
  */
736
  protected function update_package_data() {
737
+
738
  if ( ! $this->plugin_main_file ) {
739
  return;
740
  }
741
+
742
+ $default_headers = [
743
  'Version' => 'Version',
744
  'FrameworkVersion' => 'Framework Version'
745
+ ];
746
+
747
  $plugin_data = get_file_data( $this->plugin_main_file, $default_headers, 'plugin' );
748
+
749
+ $this->plugin->premium->update_package_data( [
750
  'basename' => $this->plugin_basename,
751
  'version' => $plugin_data['Version'],
752
  'framework_version' => isset( $plugin_data['FrameworkVersion'] ) ? $plugin_data['FrameworkVersion'] : null,
753
+ ] );
754
  }
755
+
756
  /**
757
+ * @since 4.1.1
758
+ *
759
  * @param string $type
760
  *
761
  * @return string|null
 
 
762
  */
763
  private function get_notice_text( $type ) {
764
  $upgrade_url = $this->get_action_url( 'install' );
765
  $activate_plugin_url = $this->get_activate_premium_url();
766
  $cancel_license_url = $this->get_action_url( 'cancel_license' );
767
+
768
+ $texts = [
769
+ 'need_activate_license' => __( 'License activation required. A license is required to get premium plugin updates, as well as to get additional services.', 'wbcr_factory_424' ),
770
+ 'need_renew_license' => __( 'Your license has expired. You can no longer get premium plugin updates, premium support and your access to Webcraftic services has been suspended.', 'wbcr_factory_424' ),
771
  'please_install_premium' => sprintf( __( 'Congratulations, you have activated a premium license! Please install premium add-on to use pro features now.
772
+ <a href="%s">Install</a> premium add-on or <a href="%s">cancel</a> license.', 'wbcr_factory_424' ), $upgrade_url, $cancel_license_url ),
773
  'please_activate_premium' => sprintf( __( 'Congratulations, you have activated a premium license! Please activate premium add-on to use pro features now.
774
+ <a href="%s">Activate</a> premium add-on or <a href="%s">cancel</a> license.', 'wbcr_factory_424' ), $activate_plugin_url, $cancel_license_url )
775
+ ];
776
+
777
  if ( isset( $texts[ $type ] ) ) {
778
+
779
  /**
780
+ * @since 4.1.1
781
+ *
782
  * @param string $type
783
  * @param string $plugin_name
784
  *
785
+ * @param array $messages
786
  */
787
  return apply_filters( 'wbcr/factory/premium/notice_text', $texts[ $type ], $type, $this->plugin->getPluginName() );
788
  }
789
+
790
  return null;
791
  }
792
  }
libs/factory/core/includes/updates/class-factory-upgrader.php CHANGED
@@ -1,11 +1,10 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412\Updates;
4
 
5
  use Exception;
6
  use stdClass;
7
- use Wbcr_Factory412_Plugin;
8
- use WBCR\Factory_Freemius_101\Updates\Freemius_Repository;
9
 
10
  // Exit if accessed directly
11
  if ( ! defined( 'ABSPATH' ) ) {
@@ -13,8 +12,8 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  }
14
 
15
  /**
16
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
17
- * @link https://webcraftic.com
18
  * @copyright (c) 2018 Webraftic Ltd
19
  * @version 1.0
20
  */
@@ -22,6 +21,19 @@ class Upgrader {
22
 
23
  const CHECK_UPDATES_INTERVAL = "43200";
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  /**
26
  * Тип апгрейдера, может быть default, premium
27
  *
@@ -30,7 +42,7 @@ class Upgrader {
30
  protected $type = 'default';
31
 
32
  /**
33
- * @var Wbcr_Factory412_Plugin
34
  */
35
  protected $plugin;
36
 
@@ -78,13 +90,13 @@ class Upgrader {
78
  *
79
  * @since 4.1.1
80
  *
81
- * @param Wbcr_Factory412_Plugin $plugin
82
  * @param $args
83
  * @param bool $is_premium
84
  *
85
  * @throws Exception
86
  */
87
- public function __construct( Wbcr_Factory412_Plugin $plugin ) {
88
 
89
  $this->plugin = $plugin;
90
 
@@ -93,6 +105,9 @@ class Upgrader {
93
  $this->plugin_absolute_path = $plugin->get_paths()->absolute;
94
  $this->is_debug = defined( 'FACTORY_UPDATES_DEBUG' ) && FACTORY_UPDATES_DEBUG;
95
 
 
 
 
96
  $settings = $this->get_settings();
97
 
98
  $this->plugin_slug = $settings['slug'];
@@ -269,62 +284,16 @@ class Upgrader {
269
  * @throws Exception
270
  */
271
  protected function get_repository( $repository_name ) {
272
- switch ( $repository_name ) {
273
- case 'wordpress':
274
- return new Wordpress_Repository( $this->plugin );
275
- break;
276
- case 'freemius':
277
- if ( ! defined( 'FACTORY_FREEMIUS_101_LOADED' ) ) {
278
- throw new Exception( 'If you have to get updates from the Freemius repository, you need to install the freemius module.' );
279
- }
280
-
281
- return new Freemius_Repository( $this->plugin );
282
- break;
283
- default:
284
- return $this->instance_other_repository( $repository_name );
285
- break;
286
- }
287
- }
288
-
289
- /**
290
- * @since 4.1.1
291
- *
292
- * @param string $name
293
- * @param bool $is_premium
294
- *
295
- * @return Repository
296
- * @throws Exception
297
- */
298
- protected function instance_other_repository( $name ) {
299
- $other_repositories = [];
300
-
301
- /**
302
- * @since 4.1.1
303
- * @type array $other_repositories
304
- */
305
- $other_repositories = apply_filters( 'wbcr/factory/updates/repositories', $other_repositories );
306
-
307
- if ( ! isset( $other_repositories[ $name ] ) ) {
308
- return null;
309
- }
310
 
311
- $repository_data = $other_repositories[ $name ];
312
-
313
- if ( ! isset( $repository_data['name'] ) || ! isset( $repository_data['class_path'] ) || ! isset( $repository_data['class_name'] ) ) {
314
- throw new Exception( 'Repository data must contain the required attributes name, class_path, class_name!' );
315
- }
316
-
317
- if ( ! file_exists( $repository_data['class_path'] ) ) {
318
- throw new Exception( 'File with new repository class not found. Please check the correctness of used path: ' . $repository_data['class_path'] );
319
- }
320
 
321
- if ( ! class_exists( $repository_data['class_name'] ) ) {
322
- throw new Exception( 'Class ' . $repository_data['class_name'] . ' is not found. Please check if class name is filled out correctly.' );
323
  }
324
 
325
- require_once $repository_data['class_path'];
326
-
327
- return new $repository_data['class_name']( $this->plugin );
328
  }
329
 
330
  /**
1
  <?php
2
 
3
+ namespace WBCR\Factory_424\Updates;
4
 
5
  use Exception;
6
  use stdClass;
7
+ use Wbcr_Factory424_Plugin;
 
8
 
9
  // Exit if accessed directly
10
  if ( ! defined( 'ABSPATH' ) ) {
12
  }
13
 
14
  /**
15
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
16
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
17
  * @copyright (c) 2018 Webraftic Ltd
18
  * @version 1.0
19
  */
21
 
22
  const CHECK_UPDATES_INTERVAL = "43200";
23
 
24
+ /**
25
+ * Список доступных классов для работы с репозиториями
26
+ *
27
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
28
+ * @since 4.1.7
29
+ * @var array хранит имя репозитория и его имя класса
30
+ * [
31
+ * 'wordpress' => 'WBCR\Factory_Freemius_112\Updates\Freemius_Repository',
32
+ * 'freemius' => '\WBCR\Factory_424\Updates\Wordpress_Repository'
33
+ * ]
34
+ */
35
+ public static $repositories = [];
36
+
37
  /**
38
  * Тип апгрейдера, может быть default, premium
39
  *
42
  protected $type = 'default';
43
 
44
  /**
45
+ * @var Wbcr_Factory424_Plugin
46
  */
47
  protected $plugin;
48
 
90
  *
91
  * @since 4.1.1
92
  *
93
+ * @param Wbcr_Factory424_Plugin $plugin
94
  * @param $args
95
  * @param bool $is_premium
96
  *
97
  * @throws Exception
98
  */
99
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
100
 
101
  $this->plugin = $plugin;
102
 
105
  $this->plugin_absolute_path = $plugin->get_paths()->absolute;
106
  $this->is_debug = defined( 'FACTORY_UPDATES_DEBUG' ) && FACTORY_UPDATES_DEBUG;
107
 
108
+ # Добавляем Wordpress репозиторий в список доступных репозиториев по умолчанию
109
+ self::$repositories['wordpress'] = '\WBCR\Factory_424\Updates\Wordpress_Repository';
110
+
111
  $settings = $this->get_settings();
112
 
113
  $this->plugin_slug = $settings['slug'];
284
  * @throws Exception
285
  */
286
  protected function get_repository( $repository_name ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
 
288
+ if ( isset( self::$repositories[ $repository_name ] ) && class_exists( self::$repositories[ $repository_name ] ) ) {
289
+ if ( self::$repositories[ $repository_name ] instanceof Repository ) {
290
+ throw new Exception( "Repository {$repository_name} must extend the class WBCR\Factory_424\Updates\Repository interface!" );
291
+ }
 
 
 
 
 
292
 
293
+ return new self::$repositories[ $repository_name ]( $this->plugin );
 
294
  }
295
 
296
+ throw new Exception( "Repository {$repository_name} is not supported!" );
 
 
297
  }
298
 
299
  /**
libs/factory/core/includes/updates/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/core/includes/updates/repositories/class-factory-repository-abstract.php CHANGED
@@ -1,60 +1,60 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412\Updates;
4
 
5
  // Exit if accessed directly
6
- use Wbcr_Factory412_Plugin;
7
 
8
  if ( ! defined( 'ABSPATH' ) ) {
9
  exit;
10
  }
11
 
12
  /**
13
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
14
- * @link https://webcraftic.com
15
  * @copyright (c) 2018 Webraftic Ltd
16
- * @version 1.0
17
  */
18
  abstract class Repository {
19
-
20
  /**
21
  * @var bool
22
  */
23
  protected $initialized = false;
24
-
25
  /**
26
- * @var Wbcr_Factory412_Plugin
27
  */
28
  protected $plugin;
29
-
30
  /**
31
  * Repository constructor.
32
  *
33
- * @param Wbcr_Factory412_Plugin $plugin
34
- * @param bool $is_premium
35
  */
36
- abstract public function __construct( Wbcr_Factory412_Plugin $plugin );
37
-
38
  /**
39
  * @return void
40
  */
41
  abstract public function init();
42
-
43
  /**
44
  * @return bool
45
  */
46
  abstract public function need_check_updates();
47
-
48
  /**
49
  * @return mixed
50
  */
51
  abstract public function is_support_premium();
52
-
53
  /**
54
  * @return string
55
  */
56
  abstract public function get_download_url();
57
-
58
  /**
59
  * @return string
60
  */
1
  <?php
2
 
3
+ namespace WBCR\Factory_424\Updates;
4
 
5
  // Exit if accessed directly
6
+ use Wbcr_Factory424_Plugin;
7
 
8
  if ( ! defined( 'ABSPATH' ) ) {
9
  exit;
10
  }
11
 
12
  /**
13
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
14
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
15
  * @copyright (c) 2018 Webraftic Ltd
16
+ * @version 1.0
17
  */
18
  abstract class Repository {
19
+
20
  /**
21
  * @var bool
22
  */
23
  protected $initialized = false;
24
+
25
  /**
26
+ * @var Wbcr_Factory424_Plugin
27
  */
28
  protected $plugin;
29
+
30
  /**
31
  * Repository constructor.
32
  *
33
+ * @param Wbcr_Factory424_Plugin $plugin
34
+ * @param bool $is_premium
35
  */
36
+ abstract public function __construct( Wbcr_Factory424_Plugin $plugin );
37
+
38
  /**
39
  * @return void
40
  */
41
  abstract public function init();
42
+
43
  /**
44
  * @return bool
45
  */
46
  abstract public function need_check_updates();
47
+
48
  /**
49
  * @return mixed
50
  */
51
  abstract public function is_support_premium();
52
+
53
  /**
54
  * @return string
55
  */
56
  abstract public function get_download_url();
57
+
58
  /**
59
  * @return string
60
  */
libs/factory/core/includes/updates/repositories/class-factory-wordpress.php CHANGED
@@ -1,68 +1,68 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_412\Updates;
4
 
5
  // Exit if accessed directly
6
- use Wbcr_Factory412_Plugin;
7
 
8
  if ( ! defined( 'ABSPATH' ) ) {
9
  exit;
10
  }
11
 
12
  /**
13
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
14
- * @link https://webcraftic.com
15
  * @copyright (c) 2018 Webraftic Ltd
16
- * @version 1.0
17
  */
18
  class Wordpress_Repository extends Repository {
19
-
20
  /**
21
  * Wordpress constructor.
22
  *
23
- * @param Wbcr_Factory412_Plugin $plugin
24
- * @param bool $is_premium
25
  */
26
- public function __construct( Wbcr_Factory412_Plugin $plugin ) {
27
  $this->plugin = $plugin;
28
  }
29
-
30
  public function init() {
31
  // TODO: Implement init() method.
32
  }
33
-
34
  /**
35
  * @return bool
36
  */
37
  public function need_check_updates() {
38
  return false;
39
  }
40
-
41
  /**
42
  * @return bool
43
  */
44
  public function is_support_premium() {
45
  return false;
46
  }
47
-
48
  /**
49
  * @return string
50
  */
51
  public function get_download_url() {
52
  return '';
53
  }
54
-
55
  /**
56
  * @return string
57
  */
58
  public function get_last_version() {
59
  return '0.0.0';
60
  }
61
-
62
  public function check_updates() {
63
-
64
  }
65
-
66
  /**
67
  * @return bool
68
  */
1
  <?php
2
 
3
+ namespace WBCR\Factory_424\Updates;
4
 
5
  // Exit if accessed directly
6
+ use Wbcr_Factory424_Plugin;
7
 
8
  if ( ! defined( 'ABSPATH' ) ) {
9
  exit;
10
  }
11
 
12
  /**
13
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
14
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
15
  * @copyright (c) 2018 Webraftic Ltd
16
+ * @version 1.0
17
  */
18
  class Wordpress_Repository extends Repository {
19
+
20
  /**
21
  * Wordpress constructor.
22
  *
23
+ * @param Wbcr_Factory424_Plugin $plugin
24
+ * @param bool $is_premium
25
  */
26
+ public function __construct( Wbcr_Factory424_Plugin $plugin ) {
27
  $this->plugin = $plugin;
28
  }
29
+
30
  public function init() {
31
  // TODO: Implement init() method.
32
  }
33
+
34
  /**
35
  * @return bool
36
  */
37
  public function need_check_updates() {
38
  return false;
39
  }
40
+
41
  /**
42
  * @return bool
43
  */
44
  public function is_support_premium() {
45
  return false;
46
  }
47
+
48
  /**
49
  * @return string
50
  */
51
  public function get_download_url() {
52
  return '';
53
  }
54
+
55
  /**
56
  * @return string
57
  */
58
  public function get_last_version() {
59
  return '0.0.0';
60
  }
61
+
62
  public function check_updates() {
63
+
64
  }
65
+
66
  /**
67
  * @return bool
68
  */
libs/factory/core/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/core/langs/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/core/langs/wbcr_factory_424-ru_RU.mo ADDED
Binary file
libs/factory/core/langs/{wbcr_factory_412-ru_RU.po → wbcr_factory_424-ru_RU.po} RENAMED
File without changes
libs/factory/forms/assets/css/index.php DELETED
File without changes
libs/factory/forms/assets/index.php DELETED
File without changes
libs/factory/forms/boot.php CHANGED
@@ -1,273 +1,273 @@
1
  <?php
2
- /**
3
- * Factory Forms
4
- *
5
- * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
- * @copyright (c) 2018, Webcraftic Ltd
7
- *
8
- * @package factory-forms
9
- * @since 1.0.1
10
- */
11
 
12
- // Exit if accessed directly
13
- if( !defined('ABSPATH') ) {
14
- exit;
15
- }
16
 
17
- // the module provides function for the admin area only
18
 
19
- if( !is_admin() ) {
20
- return;
21
- }
22
 
23
- // checks if the module is already loaded in order to
24
- // prevent loading the same version of the module twice.
25
- if( defined('FACTORY_FORMS_412_LOADED') ) {
26
- return;
27
- }
28
 
29
- define('FACTORY_FORMS_412_LOADED', true);
30
 
31
- define('FACTORY_FORMS_412_VERSION', '4.1.0');
32
 
33
- // absolute path and URL to the files and resources of the module.
34
- define('FACTORY_FORMS_412_DIR', dirname(__FILE__));
35
- define('FACTORY_FORMS_412_URL', plugins_url(null, __FILE__));
36
 
37
- #comp merge
38
- require_once(FACTORY_FORMS_412_DIR . '/includes/providers/value-provider.interface.php');
39
- require_once(FACTORY_FORMS_412_DIR . '/includes/providers/meta-value-provider.class.php');
40
- require_once(FACTORY_FORMS_412_DIR . '/includes/providers/options-value-provider.class.php');
41
 
42
- require_once(FACTORY_FORMS_412_DIR . '/includes/form.class.php');
43
- #endcomp
44
 
45
- load_plugin_textdomain('wbcr_factory_forms_412', false, dirname(plugin_basename(__FILE__)) . '/langs');
 
 
 
 
 
 
 
 
 
 
46
 
47
  /**
48
- * We add this code into the hook because all these controls quite heavy. So in order to get better perfomance,
49
- * we load the form controls only on pages where the forms are created.
50
- *
51
- * @see the 'wbcr_factory_forms_412_register_controls' hook
52
  *
53
- * @since 3.0.7
54
  */
55
- if( !function_exists('wbcr_factory_forms_412_register_default_controls') ) {
56
-
57
- /**
58
- * @param Wbcr_Factory412_Plugin $plugin
59
- * @throws Exception
60
- */
61
- function wbcr_factory_forms_412_register_default_controls(Wbcr_Factory412_Plugin $plugin)
62
- {
63
 
64
- if( $plugin && !isset($plugin->forms) ) {
65
- throw new Exception("The module Factory Forms is not loaded for the plugin '{$plugin->getPluginName()}'.");
66
- }
67
 
68
- require_once(FACTORY_FORMS_412_DIR . '/includes/html-builder.class.php');
69
- require_once(FACTORY_FORMS_412_DIR . '/includes/form-element.class.php');
70
- require_once(FACTORY_FORMS_412_DIR . '/includes/control.class.php');
71
- require_once(FACTORY_FORMS_412_DIR . '/includes/complex-control.class.php');
72
- require_once(FACTORY_FORMS_412_DIR . '/includes/holder.class.php');
73
- require_once(FACTORY_FORMS_412_DIR . '/includes/control-holder.class.php');
74
- require_once(FACTORY_FORMS_412_DIR . '/includes/custom-element.class.php');
75
- require_once(FACTORY_FORMS_412_DIR . '/includes/form-layout.class.php');
76
 
77
- // registration of controls
78
- $plugin->forms->registerControls(array(
79
- array(
80
- 'type' => 'checkbox',
81
- 'class' => 'Wbcr_FactoryForms412_CheckboxControl',
82
- 'include' => FACTORY_FORMS_412_DIR . '/controls/checkbox.php'
83
- ),
84
- array(
85
- 'type' => 'list',
86
- 'class' => 'Wbcr_FactoryForms412_ListControl',
87
- 'include' => FACTORY_FORMS_412_DIR . '/controls/list.php'
88
- ),
89
- array(
90
- 'type' => 'dropdown',
91
- 'class' => 'Wbcr_FactoryForms412_DropdownControl',
92
- 'include' => FACTORY_FORMS_412_DIR . '/controls/dropdown.php'
93
- ),
94
- array(
95
- 'type' => 'dropdown-and-colors',
96
- 'class' => 'Wbcr_FactoryForms412_DropdownAndColorsControl',
97
- 'include' => FACTORY_FORMS_412_DIR . '/controls/dropdown-and-colors.php'
98
- ),
99
- array(
100
- 'type' => 'hidden',
101
- 'class' => 'Wbcr_FactoryForms412_HiddenControl',
102
- 'include' => FACTORY_FORMS_412_DIR . '/controls/hidden.php'
103
- ),
104
- array(
105
- 'type' => 'hidden',
106
- 'class' => 'Wbcr_FactoryForms412_HiddenControl',
107
- 'include' => FACTORY_FORMS_412_DIR . '/controls/hidden.php'
108
- ),
109
- array(
110
- 'type' => 'radio',
111
- 'class' => 'Wbcr_FactoryForms412_RadioControl',
112
- 'include' => FACTORY_FORMS_412_DIR . '/controls/radio.php'
113
- ),
114
- array(
115
- 'type' => 'radio-colors',
116
- 'class' => 'Wbcr_FactoryForms412_RadioColorsControl',
117
- 'include' => FACTORY_FORMS_412_DIR . '/controls/radio-colors.php'
118
- ),
119
- array(
120
- 'type' => 'textarea',
121
- 'class' => 'Wbcr_FactoryForms412_TextareaControl',
122
- 'include' => FACTORY_FORMS_412_DIR . '/controls/textarea.php'
123
- ),
124
- array(
125
- 'type' => 'textbox',
126
- 'class' => 'Wbcr_FactoryForms412_TextboxControl',
127
- 'include' => FACTORY_FORMS_412_DIR . '/controls/textbox.php'
128
- ),
129
- array(
130
- 'type' => 'multiple-textbox',
131
- 'class' => 'Wbcr_FactoryForms412_MultipleTextboxControl',
132
- 'include' => FACTORY_FORMS_412_DIR . '/controls/multiple-textbox.php'
133
- ),
134
- array(
135
- 'type' => 'datetimepicker-range',
136
- 'class' => 'Wbcr_FactoryForms412_DatepickerRangeControl',
137
- 'include' => FACTORY_FORMS_412_DIR . '/controls/datepicker-range.php'
138
- ),
139
- array(
140
- 'type' => 'url',
141
- 'class' => 'Wbcr_FactoryForms412_UrlControl',
142
- 'include' => FACTORY_FORMS_412_DIR . '/controls/url.php'
143
- ),
144
- array(
145
- 'type' => 'wp-editor',
146
- 'class' => 'Wbcr_FactoryForms412_WpEditorControl',
147
- 'include' => FACTORY_FORMS_412_DIR . '/controls/wp-editor.php'
148
- ),
149
- array(
150
- 'type' => 'color',
151
- 'class' => 'Wbcr_FactoryForms412_ColorControl',
152
- 'include' => FACTORY_FORMS_412_DIR . '/controls/color.php'
153
- ),
154
- array(
155
- 'type' => 'color-and-opacity',
156
- 'class' => 'Wbcr_FactoryForms412_ColorAndOpacityControl',
157
- 'include' => FACTORY_FORMS_412_DIR . '/controls/color-and-opacity.php'
158
- ),
159
- array(
160
- 'type' => 'gradient',
161
- 'class' => 'Wbcr_FactoryForms412_GradientControl',
162
- 'include' => FACTORY_FORMS_412_DIR . '/controls/gradient.php'
163
- ),
164
- array(
165
- 'type' => 'font',
166
- 'class' => 'Wbcr_FactoryForms412_FontControl',
167
- 'include' => FACTORY_FORMS_412_DIR . '/controls/font.php'
168
- ),
169
- array(
170
- 'type' => 'google-font',
171
- 'class' => 'Wbcr_FactoryForms412_GoogleFontControl',
172
- 'include' => FACTORY_FORMS_412_DIR . '/controls/google-font.php'
173
- ),
174
- array(
175
- 'type' => 'pattern',
176
- 'class' => 'Wbcr_FactoryForms412_PatternControl',
177
- 'include' => FACTORY_FORMS_412_DIR . '/controls/pattern.php'
178
- ),
179
- array(
180
- 'type' => 'integer',
181
- 'class' => 'Wbcr_FactoryForms412_IntegerControl',
182
- 'include' => FACTORY_FORMS_412_DIR . '/controls/integer.php'
183
- ),
184
- array(
185
- 'type' => 'control-group',
186
- 'class' => 'Wbcr_FactoryForms412_ControlGroupHolder',
187
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/control-group.php'
188
- ),
189
- array(
190
- 'type' => 'paddings-editor',
191
- 'class' => 'Wbcr_FactoryForms412_PaddingsEditorControl',
192
- 'include' => FACTORY_FORMS_412_DIR . '/controls/paddings-editor.php'
193
- ),
194
- ));
195
 
196
- // registration of control holders
197
- $plugin->forms->registerHolders(array(
198
- array(
199
- 'type' => 'tab',
200
- 'class' => 'Wbcr_FactoryForms412_TabHolder',
201
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/tab.php'
202
- ),
203
- array(
204
- 'type' => 'tab-item',
205
- 'class' => 'Wbcr_FactoryForms412_TabItemHolder',
206
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/tab-item.php'
207
- ),
208
- array(
209
- 'type' => 'accordion',
210
- 'class' => 'Wbcr_FactoryForms412_AccordionHolder',
211
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/accordion.php'
212
- ),
213
- array(
214
- 'type' => 'accordion-item',
215
- 'class' => 'Wbcr_FactoryForms412_AccordionItemHolder',
216
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/accordion-item.php'
217
- ),
218
- array(
219
- 'type' => 'control-group',
220
- 'class' => 'Wbcr_FactoryForms412_ControlGroupHolder',
221
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/control-group.php'
222
- ),
223
- array(
224
- 'type' => 'control-group-item',
225
- 'class' => 'Wbcr_FactoryForms412_ControlGroupItem',
226
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/control-group-item.php'
227
- ),
228
- array(
229
- 'type' => 'form-group',
230
- 'class' => 'Wbcr_FactoryForms412_FormGroupHolder',
231
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/form-group.php'
232
- ),
233
- array(
234
- 'type' => 'more-link',
235
- 'class' => 'Wbcr_FactoryForms412_MoreLinkHolder',
236
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/more-link.php'
237
- ),
238
- array(
239
- 'type' => 'div',
240
- 'class' => 'Wbcr_FactoryForms412_DivHolder',
241
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/div.php'
242
- ),
243
- array(
244
- 'type' => 'columns',
245
- 'class' => 'Wbcr_FactoryForms412_ColumnsHolder',
246
- 'include' => FACTORY_FORMS_412_DIR . '/controls/holders/columns.php'
247
- )
248
- ));
249
 
250
- // registration custom form elements
251
- $plugin->forms->registerCustomElements(array(
252
- array(
253
- 'type' => 'html',
254
- 'class' => 'Wbcr_FactoryForms412_Html',
255
- 'include' => FACTORY_FORMS_412_DIR . '/controls/customs/html.php',
256
- ),
257
- array(
258
- 'type' => 'separator',
259
- 'class' => 'Wbcr_FactoryForms412_Separator',
260
- 'include' => FACTORY_FORMS_412_DIR . '/controls/customs/separator.php',
261
- ),
262
- ));
263
 
264
- // registration of form layouts
265
- $plugin->forms->registerFormLayout(array(
266
- 'name' => 'bootstrap-3',
267
- 'class' => 'Wbcr_FactoryForms412_Bootstrap3FormLayout',
268
- 'include' => FACTORY_FORMS_412_DIR . '/layouts/bootstrap-3/bootstrap-3.php'
269
- ));
270
- }
271
 
272
- add_action('wbcr_factory_forms_412_register_controls', 'wbcr_factory_forms_412_register_default_controls');
273
- }
1
  <?php
2
+ /**
3
+ * Factory Forms
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @since 1.0.1
7
+ * @package factory-forms
8
+ * @copyright (c) 2018, Webcraftic Ltd
9
+ *
10
+ */
11
 
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
 
17
+ // the module provides function for the admin area only
18
 
19
+ if ( ! is_admin() ) {
20
+ return;
21
+ }
22
 
23
+ // checks if the module is already loaded in order to
24
+ // prevent loading the same version of the module twice.
25
+ if ( defined( 'FACTORY_FORMS_422_LOADED' ) ) {
26
+ return;
27
+ }
28
 
29
+ define( 'FACTORY_FORMS_422_LOADED', true );
30
 
31
+ define( 'FACTORY_FORMS_422_VERSION', '4.2.2' );
32
 
33
+ // absolute path and URL to the files and resources of the module.
34
+ define( 'FACTORY_FORMS_422_DIR', dirname( __FILE__ ) );
35
+ define( 'FACTORY_FORMS_422_URL', plugins_url( null, __FILE__ ) );
36
 
37
+ #comp merge
38
+ require_once( FACTORY_FORMS_422_DIR . '/includes/providers/value-provider.interface.php' );
39
+ require_once( FACTORY_FORMS_422_DIR . '/includes/providers/meta-value-provider.class.php' );
40
+ require_once( FACTORY_FORMS_422_DIR . '/includes/providers/options-value-provider.class.php' );
41
 
42
+ require_once( FACTORY_FORMS_422_DIR . '/includes/form.class.php' );
43
+ #endcomp
44
 
45
+ load_plugin_textdomain( 'wbcr_factory_forms_422', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
46
+
47
+ /**
48
+ * We add this code into the hook because all these controls quite heavy. So in order to get better perfomance,
49
+ * we load the form controls only on pages where the forms are created.
50
+ *
51
+ * @since 3.0.7
52
+ * @see the 'wbcr_factory_forms_422_register_controls' hook
53
+ *
54
+ */
55
+ if ( ! function_exists( 'wbcr_factory_forms_422_register_default_controls' ) ) {
56
 
57
  /**
58
+ * @param Wbcr_Factory424_Plugin $plugin
 
 
 
59
  *
60
+ * @throws Exception
61
  */
62
+ function wbcr_factory_forms_422_register_default_controls( Wbcr_Factory424_Plugin $plugin ) {
 
 
 
 
 
 
 
63
 
64
+ if ( $plugin && ! isset( $plugin->forms ) ) {
65
+ throw new Exception( "The module Factory Forms is not loaded for the plugin '{$plugin->getPluginName()}'." );
66
+ }
67
 
68
+ require_once( FACTORY_FORMS_422_DIR . '/includes/html-builder.class.php' );
69
+ require_once( FACTORY_FORMS_422_DIR . '/includes/form-element.class.php' );
70
+ require_once( FACTORY_FORMS_422_DIR . '/includes/control.class.php' );
71
+ require_once( FACTORY_FORMS_422_DIR . '/includes/complex-control.class.php' );
72
+ require_once( FACTORY_FORMS_422_DIR . '/includes/holder.class.php' );
73
+ require_once( FACTORY_FORMS_422_DIR . '/includes/control-holder.class.php' );
74
+ require_once( FACTORY_FORMS_422_DIR . '/includes/custom-element.class.php' );
75
+ require_once( FACTORY_FORMS_422_DIR . '/includes/form-layout.class.php' );
76
 
77
+ // registration of controls
78
+ $plugin->forms->registerControls( [
79
+ [
80
+ 'type' => 'checkbox',
81
+ 'class' => 'Wbcr_FactoryForms422_CheckboxControl',
82
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/checkbox.php'
83
+ ],
84
+ [
85
+ 'type' => 'list',
86
+ 'class' => 'Wbcr_FactoryForms422_ListControl',
87
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/list.php'
88
+ ],
89
+ [
90
+ 'type' => 'dropdown',
91
+ 'class' => 'Wbcr_FactoryForms422_DropdownControl',
92
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/dropdown.php'
93
+ ],
94
+ [
95
+ 'type' => 'dropdown-and-colors',
96
+ 'class' => 'Wbcr_FactoryForms422_DropdownAndColorsControl',
97
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/dropdown-and-colors.php'
98
+ ],
99
+ [
100
+ 'type' => 'hidden',
101
+ 'class' => 'Wbcr_FactoryForms422_HiddenControl',
102
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/hidden.php'
103
+ ],
104
+ [
105
+ 'type' => 'hidden',
106
+ 'class' => 'Wbcr_FactoryForms422_HiddenControl',
107
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/hidden.php'
108
+ ],
109
+ [
110
+ 'type' => 'radio',
111
+ 'class' => 'Wbcr_FactoryForms422_RadioControl',
112
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/radio.php'
113
+ ],
114
+ [
115
+ 'type' => 'radio-colors',
116
+ 'class' => 'Wbcr_FactoryForms422_RadioColorsControl',
117
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/radio-colors.php'
118
+ ],
119
+ [
120
+ 'type' => 'textarea',
121
+ 'class' => 'Wbcr_FactoryForms422_TextareaControl',
122
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/textarea.php'
123
+ ],
124
+ [
125
+ 'type' => 'textbox',
126
+ 'class' => 'Wbcr_FactoryForms422_TextboxControl',
127
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/textbox.php'
128
+ ],
129
+ [
130
+ 'type' => 'multiple-textbox',
131
+ 'class' => 'Wbcr_FactoryForms422_MultipleTextboxControl',
132
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/multiple-textbox.php'
133
+ ],
134
+ [
135
+ 'type' => 'datetimepicker-range',
136
+ 'class' => 'Wbcr_FactoryForms422_DatepickerRangeControl',
137
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/datepicker-range.php'
138
+ ],
139
+ [
140
+ 'type' => 'url',
141
+ 'class' => 'Wbcr_FactoryForms422_UrlControl',
142
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/url.php'
143
+ ],
144
+ [
145
+ 'type' => 'wp-editor',
146
+ 'class' => 'Wbcr_FactoryForms422_WpEditorControl',
147
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/wp-editor.php'
148
+ ],
149
+ [
150
+ 'type' => 'color',
151
+ 'class' => 'Wbcr_FactoryForms422_ColorControl',
152
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/color.php'
153
+ ],
154
+ [
155
+ 'type' => 'color-and-opacity',
156
+ 'class' => 'Wbcr_FactoryForms422_ColorAndOpacityControl',
157
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/color-and-opacity.php'
158
+ ],
159
+ [
160
+ 'type' => 'gradient',
161
+ 'class' => 'Wbcr_FactoryForms422_GradientControl',
162
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/gradient.php'
163
+ ],
164
+ [
165
+ 'type' => 'font',
166
+ 'class' => 'Wbcr_FactoryForms422_FontControl',
167
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/font.php'
168
+ ],
169
+ [
170
+ 'type' => 'google-font',
171
+ 'class' => 'Wbcr_FactoryForms422_GoogleFontControl',
172
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/google-font.php'
173
+ ],
174
+ [
175
+ 'type' => 'pattern',
176
+ 'class' => 'Wbcr_FactoryForms422_PatternControl',
177
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/pattern.php'
178
+ ],
179
+ [
180
+ 'type' => 'integer',
181
+ 'class' => 'Wbcr_FactoryForms422_IntegerControl',
182
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/integer.php'
183
+ ],
184
+ [
185
+ 'type' => 'control-group',
186
+ 'class' => 'Wbcr_FactoryForms422_ControlGroupHolder',
187
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/control-group.php'
188
+ ],
189
+ [
190
+ 'type' => 'paddings-editor',
191
+ 'class' => 'Wbcr_FactoryForms422_PaddingsEditorControl',
192
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/paddings-editor.php'
193
+ ],
194
+ ] );
195
 
196
+ // registration of control holders
197
+ $plugin->forms->registerHolders( [
198
+ [
199
+ 'type' => 'tab',
200
+ 'class' => 'Wbcr_FactoryForms422_TabHolder',
201
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/tab.php'
202
+ ],
203
+ [
204
+ 'type' => 'tab-item',
205
+ 'class' => 'Wbcr_FactoryForms422_TabItemHolder',
206
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/tab-item.php'
207
+ ],
208
+ [
209
+ 'type' => 'accordion',
210
+ 'class' => 'Wbcr_FactoryForms422_AccordionHolder',
211
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/accordion.php'
212
+ ],
213
+ [
214
+ 'type' => 'accordion-item',
215
+ 'class' => 'Wbcr_FactoryForms422_AccordionItemHolder',
216
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/accordion-item.php'
217
+ ],
218
+ [
219
+ 'type' => 'control-group',
220
+ 'class' => 'Wbcr_FactoryForms422_ControlGroupHolder',
221
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/control-group.php'
222
+ ],
223
+ [
224
+ 'type' => 'control-group-item',
225
+ 'class' => 'Wbcr_FactoryForms422_ControlGroupItem',
226
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/control-group-item.php'
227
+ ],
228
+ [
229
+ 'type' => 'form-group',
230
+ 'class' => 'Wbcr_FactoryForms422_FormGroupHolder',
231
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/form-group.php'
232
+ ],
233
+ [
234
+ 'type' => 'more-link',
235
+ 'class' => 'Wbcr_FactoryForms422_MoreLinkHolder',
236
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/more-link.php'
237
+ ],
238
+ [
239
+ 'type' => 'div',
240
+ 'class' => 'Wbcr_FactoryForms422_DivHolder',
241
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/div.php'
242
+ ],
243
+ [
244
+ 'type' => 'columns',
245
+ 'class' => 'Wbcr_FactoryForms422_ColumnsHolder',
246
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/holders/columns.php'
247
+ ]
248
+ ] );
249
 
250
+ // registration custom form elements
251
+ $plugin->forms->registerCustomElements( [
252
+ [
253
+ 'type' => 'html',
254
+ 'class' => 'Wbcr_FactoryForms422_Html',
255
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/customs/html.php',
256
+ ],
257
+ [
258
+ 'type' => 'separator',
259
+ 'class' => 'Wbcr_FactoryForms422_Separator',
260
+ 'include' => FACTORY_FORMS_422_DIR . '/controls/customs/separator.php',
261
+ ],
262
+ ] );
263
 
264
+ // registration of form layouts
265
+ $plugin->forms->registerFormLayout( [
266
+ 'name' => 'bootstrap-3',
267
+ 'class' => 'Wbcr_FactoryForms422_Bootstrap3FormLayout',
268
+ 'include' => FACTORY_FORMS_422_DIR . '/layouts/bootstrap-3/bootstrap-3.php'
269
+ ] );
270
+ }
271
 
272
+ add_action( 'wbcr_factory_forms_422_register_controls', 'wbcr_factory_forms_422_register_default_controls' );
273
+ }
libs/factory/forms/controls/checkbox.php CHANGED
@@ -20,9 +20,9 @@
20
  exit;
21
  }
22
 
23
- if( !class_exists('Wbcr_FactoryForms412_CheckboxControl') ) {
24
 
25
- class Wbcr_FactoryForms412_CheckboxControl extends Wbcr_FactoryForms412_Control {
26
 
27
  public $type = 'checkbox';
28
 
@@ -130,10 +130,10 @@
130
  <div <?php $this->attrs() ?>>
131
  <button type="button" class="btn btn-default btn-small btn-sm factory-on <?php if( $value ) {
132
  echo 'active';
133
- } ?>"><?php _e('On', 'wbcr_factory_forms_412') ?></button>
134
  <button type="button" class="btn btn-default btn-small btn-sm factory-off <?php if( !$value ) {
135
  echo 'active';
136
- } ?>" data-value="0"><?php _e('Off', 'wbcr_factory_forms_412') ?></button>
137
  <input type="checkbox" style="display: none" id="<?php echo $name_on_form ?>" class="factory-result" name="<?php echo $name_on_form ?>" value="<?= $value ?>" <?php if( $value ) {
138
  echo 'checked="checked"';
139
  } ?>" />
20
  exit;
21
  }
22
 
23
+ if( !class_exists('Wbcr_FactoryForms422_CheckboxControl') ) {
24
 
25
+ class Wbcr_FactoryForms422_CheckboxControl extends Wbcr_FactoryForms422_Control {
26
 
27
  public $type = 'checkbox';
28
 
130
  <div <?php $this->attrs() ?>>
131
  <button type="button" class="btn btn-default btn-small btn-sm factory-on <?php if( $value ) {
132
  echo 'active';
133
+ } ?>"><?php _e('On', 'wbcr_factory_forms_422') ?></button>
134
  <button type="button" class="btn btn-default btn-small btn-sm factory-off <?php if( !$value ) {
135
  echo 'active';
136
+ } ?>" data-value="0"><?php _e('Off', 'wbcr_factory_forms_422') ?></button>
137
  <input type="checkbox" style="display: none" id="<?php echo $name_on_form ?>" class="factory-result" name="<?php echo $name_on_form ?>" value="<?= $value ?>" <?php if( $value ) {
138
  echo 'checked="checked"';
139
  } ?>" />
libs/factory/forms/controls/color-and-opacity.php CHANGED
@@ -20,10 +20,10 @@
20
  exit;
21
  }
22
 
23
- if( !class_exists('Wbcr_FactoryForms412_ColorAndOpacityControl') ) {
24
  }
25
 
26
- class Wbcr_FactoryForms412_ColorAndOpacityControl extends Wbcr_FactoryForms412_ComplexControl {
27
 
28
  public $type = 'color-and-opacity';
29
 
@@ -57,8 +57,8 @@
57
  'way' => 'slider'
58
  ));
59
 
60
- $this->color = new Wbcr_FactoryForms412_ColorControl($options['color'], $form, $provider);
61
- $this->opacity = new Wbcr_FactoryForms412_IntegerControl($options['opacity'], $form, $provider);
62
 
63
  $this->innerControls = array($this->color, $this->opacity);
64
  }
20
  exit;
21
  }
22
 
23
+ if( !class_exists('Wbcr_FactoryForms422_ColorAndOpacityControl') ) {
24
  }
25
 
26
+ class Wbcr_FactoryForms422_ColorAndOpacityControl extends Wbcr_FactoryForms422_ComplexControl {
27
 
28
  public $type = 'color-and-opacity';
29
 
57
  'way' => 'slider'
58
  ));
59
 
60
+ $this->color = new Wbcr_FactoryForms422_ColorControl($options['color'], $form, $provider);
61
+ $this->opacity = new Wbcr_FactoryForms422_IntegerControl($options['opacity'], $form, $provider);
62
 
63
  $this->innerControls = array($this->color, $this->opacity);
64
  }
libs/factory/forms/controls/color.php CHANGED
@@ -20,9 +20,9 @@
20
  exit;
21
  }
22
 
23
- if( !class_exists('Wbcr_FactoryForms412_ColorControl') ) {
24
 
25
- class Wbcr_FactoryForms412_ColorControl extends Wbcr_FactoryForms412_Control {
26
 
27
  public $type = 'color';
28
 
20
  exit;
21
  }
22
 
23
+ if( !class_exists('Wbcr_FactoryForms422_ColorControl') ) {
24
 
25
+ class Wbcr_FactoryForms422_ColorControl extends Wbcr_FactoryForms422_Control {
26
 
27
  public $type = 'color';
28
 
libs/factory/forms/controls/customs/html.php CHANGED
@@ -14,9 +14,9 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_Html') ) {
18
 
19
- class Wbcr_FactoryForms412_Html extends Wbcr_FactoryForms412_CustomElement {
20
 
21
  public $type = 'html';
22
 
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_Html') ) {
18
 
19
+ class Wbcr_FactoryForms422_Html extends Wbcr_FactoryForms422_CustomElement {
20
 
21
  public $type = 'html';
22
 
libs/factory/forms/controls/customs/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/forms/controls/customs/separator.php CHANGED
@@ -14,8 +14,8 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_Separator') ) {
18
- class Wbcr_FactoryForms412_Separator extends Wbcr_FactoryForms412_CustomElement {
19
 
20
  public $type = 'separator';
21
 
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_Separator') ) {
18
+ class Wbcr_FactoryForms422_Separator extends Wbcr_FactoryForms422_CustomElement {
19
 
20
  public $type = 'separator';
21
 
libs/factory/forms/controls/datepicker-range.php CHANGED
@@ -29,9 +29,9 @@
29
  exit;
30
  }
31
 
32
- if( !class_exists('Wbcr_FactoryForms412_DatepickerRangeControl') ) {
33
 
34
- class Wbcr_FactoryForms412_DatepickerRangeControl extends Wbcr_FactoryForms412_ComplexControl {
35
 
36
  public $type = 'datetimepicker-range';
37
 
@@ -65,8 +65,8 @@
65
  'default' => date('Y/m/d H:i', strtotime("+1 month"))
66
  ), $options['range_2']);
67
 
68
- $this->range_1 = new Wbcr_FactoryForms412_TextboxControl($options['range_1'], $form, $provider);
69
- $this->range_2 = new Wbcr_FactoryForms412_TextboxControl($options['range_2'], $form, $provider);
70
  $this->inner_controls = array($this->range_1, $this->range_2);
71
 
72
  foreach($this->inner_controls as $key => $control) {
29
  exit;
30
  }
31
 
32
+ if( !class_exists('Wbcr_FactoryForms422_DatepickerRangeControl') ) {
33
 
34
+ class Wbcr_FactoryForms422_DatepickerRangeControl extends Wbcr_FactoryForms422_ComplexControl {
35
 
36
  public $type = 'datetimepicker-range';
37
 
65
  'default' => date('Y/m/d H:i', strtotime("+1 month"))
66
  ), $options['range_2']);
67
 
68
+ $this->range_1 = new Wbcr_FactoryForms422_TextboxControl($options['range_1'], $form, $provider);
69
+ $this->range_2 = new Wbcr_FactoryForms422_TextboxControl($options['range_2'], $form, $provider);
70
  $this->inner_controls = array($this->range_1, $this->range_2);
71
 
72
  foreach($this->inner_controls as $key => $control) {
libs/factory/forms/controls/dropdown-and-colors.php CHANGED
@@ -5,14 +5,14 @@
5
  *
6
  * Main options:
7
  * name => a name of the control
8
- * // see FactoryForms412_DropdownControl
9
  * 'dropdown' => array(
10
  * // a callback to return items or an array of items to select
11
  * 'data' => OPanda_ThemeManager::getThemes(OPanda_Items::getCurrentItemName(), 'dropdown'),
12
  * 'default' => 'default',
13
  * 'value' => 'value' // a value to show in the control
14
  * ),
15
- * // see FactoryForms412_RadioColorsControl
16
  * 'colors' => array(
17
  * // a callback to return items or an array of items to select
18
  * 'data' => array(
@@ -37,9 +37,9 @@
37
  exit;
38
  }
39
 
40
- if( !class_exists('Wbcr_FactoryForms412_DropdownAndColorsControl') ) {
41
 
42
- class Wbcr_FactoryForms412_DropdownAndColorsControl extends Wbcr_FactoryForms412_ComplexControl {
43
 
44
  public $type = 'dropdown-and-colors';
45
 
@@ -69,8 +69,8 @@
69
  'name' => $this->options['name'] . '__colors',
70
  ));
71
 
72
- $this->dropdown = new Wbcr_FactoryForms412_DropdownControl($options['dropdown'], $form, $provider);
73
- $this->colors = new Wbcr_FactoryForms412_RadioColorsControl($options['colors'], $form, $provider);
74
  $this->inner_controls = array($this->dropdown, $this->colors);
75
 
76
  $colors = $this->colors->getOption('data');
5
  *
6
  * Main options:
7
  * name => a name of the control
8
+ * // see FactoryForms422_DropdownControl
9
  * 'dropdown' => array(
10
  * // a callback to return items or an array of items to select
11
  * 'data' => OPanda_ThemeManager::getThemes(OPanda_Items::getCurrentItemName(), 'dropdown'),
12
  * 'default' => 'default',
13
  * 'value' => 'value' // a value to show in the control
14
  * ),
15
+ * // see FactoryForms422_RadioColorsControl
16
  * 'colors' => array(
17
  * // a callback to return items or an array of items to select
18
  * 'data' => array(
37
  exit;
38
  }
39
 
40
+ if( !class_exists('Wbcr_FactoryForms422_DropdownAndColorsControl') ) {
41
 
42
+ class Wbcr_FactoryForms422_DropdownAndColorsControl extends Wbcr_FactoryForms422_ComplexControl {
43
 
44
  public $type = 'dropdown-and-colors';
45
 
69
  'name' => $this->options['name'] . '__colors',
70
  ));
71
 
72
+ $this->dropdown = new Wbcr_FactoryForms422_DropdownControl($options['dropdown'], $form, $provider);
73
+ $this->colors = new Wbcr_FactoryForms422_RadioColorsControl($options['colors'], $form, $provider);
74
  $this->inner_controls = array($this->dropdown, $this->colors);
75
 
76
  $colors = $this->colors->getOption('data');
libs/factory/forms/controls/dropdown.php CHANGED
@@ -21,9 +21,9 @@
21
  exit;
22
  }
23
 
24
- if ( ! class_exists( 'Wbcr_FactoryForms412_DropdownControl' ) ) {
25
 
26
- class Wbcr_FactoryForms412_DropdownControl extends Wbcr_FactoryForms412_Control {
27
 
28
  public $type = 'dropdown';
29
 
@@ -123,7 +123,7 @@
123
  'url': '<?php echo $data['url'] ?>',
124
  'data': <?php echo json_encode( $data['data'] ) ?>,
125
  'selected': '<?php echo $value ?>',
126
- 'empty_list': '<?php echo $this->getOption( 'empty', __( 'The list is empty.', 'wbcr_factory_forms_412' ) ) ?>'
127
  };
128
  </script>
129
  <?php
@@ -268,7 +268,7 @@
268
  }
269
 
270
  $is_empty = $this->isAjax() || empty( $items );
271
- $empty_list = $this->getOption( 'empty', __( '- empty -', 'wbcr_factory_forms_412' ) );
272
 
273
  ?>
274
  <select <?php $this->attrs() ?>>
@@ -349,7 +349,7 @@
349
  }
350
 
351
  $value = isset( $item['value'] ) ? $item['value'] : '';
352
- $title = isset( $item['title'] ) ? $item['title'] : __( '- empty -', 'wbcr_factory_forms_412' );
353
 
354
  $data = isset( $item['data'] ) ? $item['data'] : null;
355
  } else {
21
  exit;
22
  }
23
 
24
+ if ( ! class_exists( 'Wbcr_FactoryForms422_DropdownControl' ) ) {
25
 
26
+ class Wbcr_FactoryForms422_DropdownControl extends Wbcr_FactoryForms422_Control {
27
 
28
  public $type = 'dropdown';
29
 
123
  'url': '<?php echo $data['url'] ?>',
124
  'data': <?php echo json_encode( $data['data'] ) ?>,
125
  'selected': '<?php echo $value ?>',
126
+ 'empty_list': '<?php echo $this->getOption( 'empty', __( 'The list is empty.', 'wbcr_factory_forms_422' ) ) ?>'
127
  };
128
  </script>
129
  <?php
268
  }
269
 
270
  $is_empty = $this->isAjax() || empty( $items );
271
+ $empty_list = $this->getOption( 'empty', __( '- empty -', 'wbcr_factory_forms_422' ) );
272
 
273
  ?>
274
  <select <?php $this->attrs() ?>>
349
  }
350
 
351
  $value = isset( $item['value'] ) ? $item['value'] : '';
352
+ $title = isset( $item['title'] ) ? $item['title'] : __( '- empty -', 'wbcr_factory_forms_422' );
353
 
354
  $data = isset( $item['data'] ) ? $item['data'] : null;
355
  } else {
libs/factory/forms/controls/font.php CHANGED
@@ -20,9 +20,9 @@
20
  exit;
21
  }
22
 
23
- if( !class_exists('Wbcr_FactoryForms412_FontControl') ) {
24
 
25
- class Wbcr_FactoryForms412_FontControl extends Wbcr_FactoryForms412_ComplexControl {
26
 
27
  public $type = 'font';
28
 
@@ -54,9 +54,9 @@
54
  'pickerTarget' => '.factory-control-' . $this->options['name'] . ' .factory-picker-target'
55
  );
56
 
57
- $this->size = new Wbcr_FactoryForms412_IntegerControl($option_font_size, $form, $provider);
58
- $this->family = new Wbcr_FactoryForms412_DropdownControl($option_font_family, $form, $provider);
59
- $this->color = new Wbcr_FactoryForms412_ColorControl($optionFontColor, $form, $provider);
60
 
61
  $this->innerControls = array($this->family, $this->size, $this->color);
62
  }
@@ -66,8 +66,8 @@
66
 
67
  $fonts = $this->getDefaultFonts();
68
 
69
- $fonts = apply_filters('wbcr_factory_forms_412_fonts', $fonts);
70
- $fonts = apply_filters('wbcr_factory_forms_412_fonts-' . $this->options['name'], $fonts);
71
 
72
  return $fonts;
73
  }
@@ -77,10 +77,10 @@
77
 
78
  $fonts = array(
79
 
80
- array('inherit', __('(use default website font)', 'wbcr_factory_forms_412')),
81
  array(
82
  'group',
83
- __('Sans Serif:', 'wbcr_factory_forms_412'),
84
  array(
85
  array('Arial, "Helvetica Neue", Helvetica, sans-serif', 'Arial'),
86
  array('"Arial Black", "Arial Bold", Gadget, sans-serif', 'Arial Black'),
@@ -131,7 +131,7 @@
131
  ),
132
  array(
133
  'group',
134
- __('Serif:', 'wbcr_factory_forms_412'),
135
  array(
136
  array(
137
  'Baskerville, "Baskerville Old Face", "Hoefler Text", Garamond, "Times New Roman", serif',
@@ -187,7 +187,7 @@
187
  ),
188
  array(
189
  'group',
190
- __('Monospaced:', 'wbcr_factory_forms_412'),
191
  array(
192
  array('"Andale Mono", AndaleMono, monospace', 'Andale Mono'),
193
  array('Consolas, monaco, monospace', 'Consolas'),
20
  exit;
21
  }
22
 
23
+ if( !class_exists('Wbcr_FactoryForms422_FontControl') ) {
24
 
25
+ class Wbcr_FactoryForms422_FontControl extends Wbcr_FactoryForms422_ComplexControl {
26
 
27
  public $type = 'font';
28
 
54
  'pickerTarget' => '.factory-control-' . $this->options['name'] . ' .factory-picker-target'
55
  );
56
 
57
+ $this->size = new Wbcr_FactoryForms422_IntegerControl($option_font_size, $form, $provider);
58
+ $this->family = new Wbcr_FactoryForms422_DropdownControl($option_font_family, $form, $provider);
59
+ $this->color = new Wbcr_FactoryForms422_ColorControl($optionFontColor, $form, $provider);
60
 
61
  $this->innerControls = array($this->family, $this->size, $this->color);
62
  }
66
 
67
  $fonts = $this->getDefaultFonts();
68
 
69
+ $fonts = apply_filters('wbcr_factory_forms_422_fonts', $fonts);
70
+ $fonts = apply_filters('wbcr_factory_forms_422_fonts-' . $this->options['name'], $fonts);
71
 
72
  return $fonts;
73
  }
77
 
78
  $fonts = array(
79
 
80
+ array('inherit', __('(use default website font)', 'wbcr_factory_forms_422')),
81
  array(
82
  'group',
83
+ __('Sans Serif:', 'wbcr_factory_forms_422'),
84
  array(
85
  array('Arial, "Helvetica Neue", Helvetica, sans-serif', 'Arial'),
86
  array('"Arial Black", "Arial Bold", Gadget, sans-serif', 'Arial Black'),
131
  ),
132
  array(
133
  'group',
134
+ __('Serif:', 'wbcr_factory_forms_422'),
135
  array(
136
  array(
137
  'Baskerville, "Baskerville Old Face", "Hoefler Text", Garamond, "Times New Roman", serif',
187
  ),
188
  array(
189
  'group',
190
+ __('Monospaced:', 'wbcr_factory_forms_422'),
191
  array(
192
  array('"Andale Mono", AndaleMono, monospace', 'Andale Mono'),
193
  array('Consolas, monaco, monospace', 'Consolas'),
libs/factory/forms/controls/google-font.php CHANGED
@@ -15,7 +15,7 @@
15
  * @package core
16
  * @since 1.0.0
17
  */
18
- class Wbcr_FactoryForms412_GoogleFontControl extends Wbcr_FactoryForms412_FontControl {
19
 
20
  public $type = 'google-font';
21
  const APIKEY = 'AIzaSyB-3vazYv7Q-5QZA04bmSKFrWcw_VhC40w';
@@ -30,7 +30,7 @@
30
  'cssClass' => 'factory-google-font-data'
31
  );
32
 
33
- $this->google_font_data = new Wbcr_FactoryForms412_HiddenControl($option_google_font_data, $form, $provider);
34
  $this->inner_controls[] = $this->google_font_data;
35
  }
36
 
@@ -49,12 +49,12 @@
49
  $google_fonts = $this->getGoogleFonts();
50
 
51
  $fonts = array(
52
- array('inherit', __('(use default website font)', 'wbcr_factory_forms_412'))
53
  );
54
 
55
  $fontsCommon = array(
56
  'group',
57
- __('Standard:', 'wbcr_factory_forms_412'),
58
  array(
59
 
60
  array('Arial, "Helvetica Neue", Helvetica, sans-serif', 'Arial'),
@@ -65,7 +65,7 @@
65
  )
66
  );
67
 
68
- $fontsGoogleFonts = array('group', __('Google Fonts:', 'wbcr_factory_forms_412'), array());
69
 
70
  foreach($google_fonts->items as $item) {
71
 
@@ -115,7 +115,7 @@
115
 
116
  if( is_wp_error($response) ) {
117
 
118
- $this->error = __('Unable to retrieve the list of Google Fonts.', 'wbcr_factory_forms_412');
119
  $this->defailed_error = $response->get_error_message();
120
 
121
  return $body;
@@ -123,7 +123,7 @@
123
 
124
  if( !isset($response['body']) ) {
125
 
126
- $this->error = __('Invalide response from the Google Fonts API.', 'wbcr_factory_forms_412');
127
  $this->defailed_error = $response['body'];
128
 
129
  return $body;
@@ -133,7 +133,7 @@
133
 
134
  if( empty($body->items) ) {
135
 
136
- $this->error = __('Unexpected error. The list of Google Fonts are empty.', 'wbcr_factory_forms_412');
137
 
138
  return $body;
139
  }
15
  * @package core
16
  * @since 1.0.0
17
  */
18
+ class Wbcr_FactoryForms422_GoogleFontControl extends Wbcr_FactoryForms422_FontControl {
19
 
20
  public $type = 'google-font';
21
  const APIKEY = 'AIzaSyB-3vazYv7Q-5QZA04bmSKFrWcw_VhC40w';
30
  'cssClass' => 'factory-google-font-data'
31
  );
32
 
33
+ $this->google_font_data = new Wbcr_FactoryForms422_HiddenControl($option_google_font_data, $form, $provider);
34
  $this->inner_controls[] = $this->google_font_data;
35
  }
36
 
49
  $google_fonts = $this->getGoogleFonts();
50
 
51
  $fonts = array(
52
+ array('inherit', __('(use default website font)', 'wbcr_factory_forms_422'))
53
  );
54
 
55
  $fontsCommon = array(
56
  'group',
57
+ __('Standard:', 'wbcr_factory_forms_422'),
58
  array(
59
 
60
  array('Arial, "Helvetica Neue", Helvetica, sans-serif', 'Arial'),
65
  )
66
  );
67
 
68
+ $fontsGoogleFonts = array('group', __('Google Fonts:', 'wbcr_factory_forms_422'), array());
69
 
70
  foreach($google_fonts->items as $item) {
71
 
115
 
116
  if( is_wp_error($response) ) {
117
 
118
+ $this->error = __('Unable to retrieve the list of Google Fonts.', 'wbcr_factory_forms_422');
119
  $this->defailed_error = $response->get_error_message();
120
 
121
  return $body;
123
 
124
  if( !isset($response['body']) ) {
125
 
126
+ $this->error = __('Invalide response from the Google Fonts API.', 'wbcr_factory_forms_422');
127
  $this->defailed_error = $response['body'];
128
 
129
  return $body;
133
 
134
  if( empty($body->items) ) {
135
 
136
+ $this->error = __('Unexpected error. The list of Google Fonts are empty.', 'wbcr_factory_forms_422');
137
 
138
  return $body;
139
  }
libs/factory/forms/controls/gradient.php CHANGED
@@ -25,8 +25,8 @@
25
  exit;
26
  }
27
 
28
- if( !class_exists('Wbcr_FactoryForms412_GradientControl') ) {
29
- class Wbcr_FactoryForms412_GradientControl extends Wbcr_FactoryForms412_Control {
30
 
31
  public $type = 'gradient';
32
 
@@ -66,8 +66,8 @@
66
  if( !window.factory.res ) {
67
  window.factory.res = {};
68
  }
69
- factory.res.resVertical = '<?php _e( 'vertical', 'wbcr_factory_forms_412' ) ?>';
70
- factory.res.resHorizontal = '<?php _e( 'horizontal', 'wbcr_factory_forms_412' ) ?>';
71
  </script>
72
  <div <?php $this->attrs() ?>>
73
  <div class="factory-gradient-picker">
25
  exit;
26
  }
27
 
28
+ if( !class_exists('Wbcr_FactoryForms422_GradientControl') ) {
29
+ class Wbcr_FactoryForms422_GradientControl extends Wbcr_FactoryForms422_Control {
30
 
31
  public $type = 'gradient';
32
 
66
  if( !window.factory.res ) {
67
  window.factory.res = {};
68
  }
69
+ factory.res.resVertical = '<?php _e( 'vertical', 'wbcr_factory_forms_422' ) ?>';
70
+ factory.res.resHorizontal = '<?php _e( 'horizontal', 'wbcr_factory_forms_422' ) ?>';
71
  </script>
72
  <div <?php $this->attrs() ?>>
73
  <div class="factory-gradient-picker">
libs/factory/forms/controls/hidden.php CHANGED
@@ -20,9 +20,9 @@
20
  exit;
21
  }
22
 
23
- if( !class_exists('Wbcr_FactoryForms412_HiddenControl') ) {
24
 
25
- class Wbcr_FactoryForms412_HiddenControl extends Wbcr_FactoryForms412_Control {
26
 
27
  public $type = 'hidden';
28
 
20
  exit;
21
  }
22
 
23
+ if( !class_exists('Wbcr_FactoryForms422_HiddenControl') ) {
24
 
25
+ class Wbcr_FactoryForms422_HiddenControl extends Wbcr_FactoryForms422_Control {
26
 
27
  public $type = 'hidden';
28
 
libs/factory/forms/controls/holders/accordion-item.php CHANGED
@@ -14,14 +14,14 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_AccordionItemHolder') ) {
18
 
19
  /**
20
  * Tab Control Holder
21
  *
22
  * @since 1.0.0
23
  */
24
- class Wbcr_FactoryForms412_AccordionItemHolder extends Wbcr_FactoryForms412_Holder {
25
 
26
  /**
27
  * A holder type.
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_AccordionItemHolder') ) {
18
 
19
  /**
20
  * Tab Control Holder
21
  *
22
  * @since 1.0.0
23
  */
24
+ class Wbcr_FactoryForms422_AccordionItemHolder extends Wbcr_FactoryForms422_Holder {
25
 
26
  /**
27
  * A holder type.
libs/factory/forms/controls/holders/accordion.php CHANGED
@@ -13,13 +13,13 @@
13
  if( !defined('ABSPATH') ) {
14
  exit;
15
  }
16
- if( !class_exists('Wbcr_FactoryForms412_AccordionHolder') ) {
17
  /**
18
  * Tab Control Holder
19
  *
20
  * @since 1.0.0
21
  */
22
- class Wbcr_FactoryForms412_AccordionHolder extends Wbcr_FactoryForms412_Holder {
23
 
24
  /**
25
  * A holder type.
13
  if( !defined('ABSPATH') ) {
14
  exit;
15
  }
16
+ if( !class_exists('Wbcr_FactoryForms422_AccordionHolder') ) {
17
  /**
18
  * Tab Control Holder
19
  *
20
  * @since 1.0.0
21
  */
22
+ class Wbcr_FactoryForms422_AccordionHolder extends Wbcr_FactoryForms422_Holder {
23
 
24
  /**
25
  * A holder type.
libs/factory/forms/controls/holders/columns.php CHANGED
@@ -14,13 +14,13 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_ColumnsHolder') ) {
18
  /**
19
  * Columns Holder
20
  *
21
  * @since 1.0.0
22
  */
23
- class Wbcr_FactoryForms412_ColumnsHolder extends Wbcr_FactoryForms412_Holder {
24
 
25
  /**
26
  * A holder type.
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_ColumnsHolder') ) {
18
  /**
19
  * Columns Holder
20
  *
21
  * @since 1.0.0
22
  */
23
+ class Wbcr_FactoryForms422_ColumnsHolder extends Wbcr_FactoryForms422_Holder {
24
 
25
  /**
26
  * A holder type.
libs/factory/forms/controls/holders/control-group-item.php CHANGED
@@ -14,14 +14,14 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_ControlGroupItem') ) {
18
 
19
  /**
20
  * Tab Control Holder
21
  *
22
  * @since 1.0.0
23
  */
24
- class Wbcr_FactoryForms412_ControlGroupItem extends Wbcr_FactoryForms412_Holder {
25
 
26
  /**
27
  * A holder type.
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_ControlGroupItem') ) {
18
 
19
  /**
20
  * Tab Control Holder
21
  *
22
  * @since 1.0.0
23
  */
24
+ class Wbcr_FactoryForms422_ControlGroupItem extends Wbcr_FactoryForms422_Holder {
25
 
26
  /**
27
  * A holder type.
libs/factory/forms/controls/holders/control-group.php CHANGED
@@ -14,14 +14,14 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_ControlGroupHolder') ) {
18
 
19
  /**
20
  * Tab Control Holder
21
  *
22
  * @since 1.0.0
23
  */
24
- class Wbcr_FactoryForms412_ControlGroupHolder extends Wbcr_FactoryForms412_ControlHolder {
25
 
26
  /**
27
  * A holder type.
@@ -61,7 +61,7 @@
61
  continue;
62
  }
63
 
64
- $builder = new Wbcr_FactoryForms412_HtmlAttributeBuilder();
65
 
66
  $builder->addCssClass('factory-control-group-nav-label');
67
  $builder->addCssClass('factory-control-group-nav-label-' . $element->getOption('name'));
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_ControlGroupHolder') ) {
18
 
19
  /**
20
  * Tab Control Holder
21
  *
22
  * @since 1.0.0
23
  */
24
+ class Wbcr_FactoryForms422_ControlGroupHolder extends Wbcr_FactoryForms422_ControlHolder {
25
 
26
  /**
27
  * A holder type.
61
  continue;
62
  }
63
 
64
+ $builder = new Wbcr_FactoryForms422_HtmlAttributeBuilder();
65
 
66
  $builder->addCssClass('factory-control-group-nav-label');
67
  $builder->addCssClass('factory-control-group-nav-label-' . $element->getOption('name'));
libs/factory/forms/controls/holders/div.php CHANGED
@@ -14,13 +14,13 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_DivHolder') ) {
18
  /**
19
  * Div Control Holder
20
  *
21
  * @since 1.0.0
22
  */
23
- class Wbcr_FactoryForms412_DivHolder extends Wbcr_FactoryForms412_Holder {
24
 
25
  /**
26
  * A holder type.
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_DivHolder') ) {
18
  /**
19
  * Div Control Holder
20
  *
21
  * @since 1.0.0
22
  */
23
+ class Wbcr_FactoryForms422_DivHolder extends Wbcr_FactoryForms422_Holder {
24
 
25
  /**
26
  * A holder type.
libs/factory/forms/controls/holders/form-group.php CHANGED
@@ -14,13 +14,13 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_FormGroupHolder') ) {
18
  /**
19
  * Group Holder
20
  *
21
  * @since 1.0.0
22
  */
23
- class Wbcr_FactoryForms412_FormGroupHolder extends Wbcr_FactoryForms412_Holder {
24
 
25
  /**
26
  * A holder type.
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_FormGroupHolder') ) {
18
  /**
19
  * Group Holder
20
  *
21
  * @since 1.0.0
22
  */
23
+ class Wbcr_FactoryForms422_FormGroupHolder extends Wbcr_FactoryForms422_Holder {
24
 
25
  /**
26
  * A holder type.
libs/factory/forms/controls/holders/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/forms/controls/holders/more-link.php CHANGED
@@ -14,14 +14,14 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_MoreLinkHolder') ) {
18
 
19
  /**
20
  * Collapsed Group Holder
21
  *
22
  * @since 1.0.0
23
  */
24
- class Wbcr_FactoryForms412_MoreLinkHolder extends Wbcr_FactoryForms412_Holder {
25
 
26
  /**
27
  * A holder type.
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_MoreLinkHolder') ) {
18
 
19
  /**
20
  * Collapsed Group Holder
21
  *
22
  * @since 1.0.0
23
  */
24
+ class Wbcr_FactoryForms422_MoreLinkHolder extends Wbcr_FactoryForms422_Holder {
25
 
26
  /**
27
  * A holder type.
libs/factory/forms/controls/holders/tab-item.php CHANGED
@@ -13,13 +13,13 @@
13
  exit;
14
  }
15
 
16
- if( !class_exists('Wbcr_FactoryForms412_TabItemHolder') ) {
17
  /**
18
  * Tab Item Control Holder
19
  *
20
  * @since 1.0.0
21
  */
22
- class Wbcr_FactoryForms412_TabItemHolder extends Wbcr_FactoryForms412_Holder {
23
 
24
  /**
25
  * A holder type.
13
  exit;
14
  }
15
 
16
+ if( !class_exists('Wbcr_FactoryForms422_TabItemHolder') ) {
17
  /**
18
  * Tab Item Control Holder
19
  *
20
  * @since 1.0.0
21
  */
22
+ class Wbcr_FactoryForms422_TabItemHolder extends Wbcr_FactoryForms422_Holder {
23
 
24
  /**
25
  * A holder type.
libs/factory/forms/controls/holders/tab.php CHANGED
@@ -14,14 +14,14 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_TabHolder') ) {
18
 
19
  /**
20
  * Tab Control Holder
21
  *
22
  * @since 1.0.0
23
  */
24
- class Wbcr_FactoryForms412_TabHolder extends Wbcr_FactoryForms412_Holder {
25
 
26
  /**
27
  * A holder type.
@@ -44,7 +44,7 @@
44
  *
45
  * @since 1.0.0
46
  * @param mixed[] $options A holder options.
47
- * @param FactoryForms412_Form $form A parent form.
48
  */
49
  public function __construct($options, $form)
50
  {
@@ -88,7 +88,7 @@
88
  $tab_icon = $element->options['icon'];
89
  }
90
 
91
- $builder = new Wbcr_FactoryForms412_HtmlAttributeBuilder();
92
 
93
  $builder->addCssClass('factory-tab-item-header');
94
  $builder->addCssClass('factory-tab-item-header-' . $element->getName());
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_TabHolder') ) {
18
 
19
  /**
20
  * Tab Control Holder
21
  *
22
  * @since 1.0.0
23
  */
24
+ class Wbcr_FactoryForms422_TabHolder extends Wbcr_FactoryForms422_Holder {
25
 
26
  /**
27
  * A holder type.
44
  *
45
  * @since 1.0.0
46
  * @param mixed[] $options A holder options.
47
+ * @param FactoryForms422_Form $form A parent form.
48
  */
49
  public function __construct($options, $form)
50
  {
88
  $tab_icon = $element->options['icon'];
89
  }
90
 
91
+ $builder = new Wbcr_FactoryForms422_HtmlAttributeBuilder();
92
 
93
  $builder->addCssClass('factory-tab-item-header');
94
  $builder->addCssClass('factory-tab-item-header-' . $element->getName());
libs/factory/forms/controls/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/forms/controls/integer.php CHANGED
@@ -32,9 +32,9 @@
32
  exit;
33
  }
34
 
35
- if( !class_exists('Wbcr_FactoryForms412_IntegerControl') ) {
36
 
37
- class Wbcr_FactoryForms412_IntegerControl extends Wbcr_FactoryForms412_Control {
38
 
39
  public $type = 'integer';
40
 
32
  exit;
33
  }
34
 
35
+ if( !class_exists('Wbcr_FactoryForms422_IntegerControl') ) {
36
 
37
+ class Wbcr_FactoryForms422_IntegerControl extends Wbcr_FactoryForms422_Control {
38
 
39
  public $type = 'integer';
40
 
libs/factory/forms/controls/list.php CHANGED
@@ -21,9 +21,9 @@
21
  exit;
22
  }
23
 
24
- if( !class_exists('Wbcr_FactoryForms412_ListControl') ) {
25
 
26
- class Wbcr_FactoryForms412_ListControl extends Wbcr_FactoryForms412_Control {
27
 
28
  public $type = 'list';
29
 
@@ -93,7 +93,7 @@
93
  'url': '<?php echo $data['url'] ?>',
94
  'data': <?php echo json_encode( $data['data'] ) ?>,
95
  'selected': <?php echo json_encode( $value ) ?>,
96
- 'emptyList': '<?php echo $this->getOption('empty', __('The list is empty.', 'wbcr_factory_forms_412') ) ?>'
97
  };
98
  </script>
99
  <?php
@@ -136,7 +136,7 @@
136
  : array();
137
 
138
  $is_empty = $this->isAjax() || empty($items);
139
- $emptyList = $this->getOption('empty', __('The list is empty.', 'wbcr_factory_forms_412'));
140
 
141
  if( $is_empty ) {
142
  $this->addCssClass('factory-empty');
21
  exit;
22
  }
23
 
24
+ if( !class_exists('Wbcr_FactoryForms422_ListControl') ) {
25
 
26
+ class Wbcr_FactoryForms422_ListControl extends Wbcr_FactoryForms422_Control {
27
 
28
  public $type = 'list';
29
 
93
  'url': '<?php echo $data['url'] ?>',
94
  'data': <?php echo json_encode( $data['data'] ) ?>,
95
  'selected': <?php echo json_encode( $value ) ?>,
96
+ 'emptyList': '<?php echo $this->getOption('empty', __('The list is empty.', 'wbcr_factory_forms_422') ) ?>'
97
  };
98
  </script>
99
  <?php
136
  : array();
137
 
138
  $is_empty = $this->isAjax() || empty($items);
139
+ $emptyList = $this->getOption('empty', __('The list is empty.', 'wbcr_factory_forms_422'));
140
 
141
  if( $is_empty ) {
142
  $this->addCssClass('factory-empty');
libs/factory/forms/controls/multiple-textbox.php CHANGED
@@ -15,9 +15,9 @@
15
  exit;
16
  }
17
 
18
- if( !class_exists('Wbcr_FactoryForms412_MultipleTextboxControl') ) {
19
 
20
- class Wbcr_FactoryForms412_MultipleTextboxControl extends Wbcr_FactoryForms412_Control {
21
 
22
  public $type = 'multiple-textbox';
23
 
@@ -86,7 +86,7 @@
86
  <?php endif; ?>
87
  </div>
88
  <button class="btn btn-default btn-small factory-mtextbox-add-item">
89
- <i class="fa fa-plus" aria-hidden="true"></i> <?php _e('Add new', 'wbcr_factory_forms_412') ?>
90
  </button>
91
  </div>
92
 
15
  exit;
16
  }
17
 
18
+ if( !class_exists('Wbcr_FactoryForms422_MultipleTextboxControl') ) {
19
 
20
+ class Wbcr_FactoryForms422_MultipleTextboxControl extends Wbcr_FactoryForms422_Control {
21
 
22
  public $type = 'multiple-textbox';
23
 
86
  <?php endif; ?>
87
  </div>
88
  <button class="btn btn-default btn-small factory-mtextbox-add-item">
89
+ <i class="fa fa-plus" aria-hidden="true"></i> <?php _e('Add new', 'wbcr_factory_forms_422') ?>
90
  </button>
91
  </div>
92
 
libs/factory/forms/controls/paddings-editor.php CHANGED
@@ -14,9 +14,9 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_PaddingsEditorControl') ) {
18
 
19
- class Wbcr_FactoryForms412_PaddingsEditorControl extends Wbcr_FactoryForms412_Control {
20
 
21
  public $type = 'paddings-editor';
22
 
@@ -67,7 +67,7 @@
67
  </div>
68
  <div class="factory-slider-container">
69
  <label class="factory-title">
70
- <?php _e('Select a side and move the slider to set up:', 'wbcr_factory_forms_412') ?>
71
  </label>
72
 
73
  <div class="factory-slider">
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_PaddingsEditorControl') ) {
18
 
19
+ class Wbcr_FactoryForms422_PaddingsEditorControl extends Wbcr_FactoryForms422_Control {
20
 
21
  public $type = 'paddings-editor';
22
 
67
  </div>
68
  <div class="factory-slider-container">
69
  <label class="factory-title">
70
+ <?php _e('Select a side and move the slider to set up:', 'wbcr_factory_forms_422') ?>
71
  </label>
72
 
73
  <div class="factory-slider">
libs/factory/forms/controls/pattern.php CHANGED
@@ -15,9 +15,9 @@
15
  exit;
16
  }
17
 
18
- if( !class_exists('Wbcr_FactoryForms412_PatternControl') ) {
19
 
20
- class Wbcr_FactoryForms412_PatternControl extends Wbcr_FactoryForms412_Control {
21
 
22
  public $type = 'pattern';
23
 
@@ -52,12 +52,12 @@
52
  $name = $this->getOption('name');
53
 
54
  // filters to get available patterns for the given background contols
55
- $this->patterns = apply_filters('wbcr_factory_forms_412_patterns', array());
56
- $this->patterns = apply_filters('wbcr_factory_forms_412_patterns-' . $name, $this->patterns);
57
 
58
  $this->custom_patterns = $this->getOption('patterns', array());
59
 
60
- $this->color = new Wbcr_FactoryForms412_ColorControl($options['color'], $form, $provider);
61
  }
62
 
63
  /**
@@ -102,19 +102,19 @@
102
  </div>
103
  <a href="#" class="button button-default factory-button factory-change-color-btn <?php if( $hasColor ) {
104
  echo 'button-active';
105
- } ?>" title="<?php _e('Change color', 'wbcr_factory_forms_412') ?>">
106
  <i class="fa fa-flask"></i>
107
- <span><?php _e('re-color', 'wbcr_factory_forms_412') ?></span>
108
  </a>
109
  <input type="hidden" id="<?php echo $name[0]; ?>" name="<?php echo $name[0]; ?>" value="<?php echo esc_url($values['url']); ?>" class="factory-pattern-result">
110
  <input type="hidden" id="<?php echo $name[1]; ?>" name="<?php echo $name[1]; ?>" value="<?php echo esc_attr($values['color']); ?>" class="factory-color-result">
111
  </div>
112
  <div class="factory-color-panel">
113
  <div class="factory-color-wrap">
114
- <span class="factory-color-label"><?php _e('Select color:', 'wbcr_factory_forms_412') ?></span>
115
  <?php $this->color->html() ?>
116
  <div class="factory-hint">
117
- <i><?php _e('Changing the color may takes a minute or more. Please be patient.', 'wbcr_factory_forms_412') ?></i>
118
  </div>
119
  </div>
120
  <div class="factory-picker-target"></div>
15
  exit;
16
  }
17
 
18
+ if( !class_exists('Wbcr_FactoryForms422_PatternControl') ) {
19
 
20
+ class Wbcr_FactoryForms422_PatternControl extends Wbcr_FactoryForms422_Control {
21
 
22
  public $type = 'pattern';
23
 
52
  $name = $this->getOption('name');
53
 
54
  // filters to get available patterns for the given background contols
55
+ $this->patterns = apply_filters('wbcr_factory_forms_422_patterns', array());
56
+ $this->patterns = apply_filters('wbcr_factory_forms_422_patterns-' . $name, $this->patterns);
57
 
58
  $this->custom_patterns = $this->getOption('patterns', array());
59
 
60
+ $this->color = new Wbcr_FactoryForms422_ColorControl($options['color'], $form, $provider);
61
  }
62
 
63
  /**
102
  </div>
103
  <a href="#" class="button button-default factory-button factory-change-color-btn <?php if( $hasColor ) {
104
  echo 'button-active';
105
+ } ?>" title="<?php _e('Change color', 'wbcr_factory_forms_422') ?>">
106
  <i class="fa fa-flask"></i>
107
+ <span><?php _e('re-color', 'wbcr_factory_forms_422') ?></span>
108
  </a>
109
  <input type="hidden" id="<?php echo $name[0]; ?>" name="<?php echo $name[0]; ?>" value="<?php echo esc_url($values['url']); ?>" class="factory-pattern-result">
110
  <input type="hidden" id="<?php echo $name[1]; ?>" name="<?php echo $name[1]; ?>" value="<?php echo esc_attr($values['color']); ?>" class="factory-color-result">
111
  </div>
112
  <div class="factory-color-panel">
113
  <div class="factory-color-wrap">
114
+ <span class="factory-color-label"><?php _e('Select color:', 'wbcr_factory_forms_422') ?></span>
115
  <?php $this->color->html() ?>
116
  <div class="factory-hint">
117
+ <i><?php _e('Changing the color may takes a minute or more. Please be patient.', 'wbcr_factory_forms_422') ?></i>
118
  </div>
119
  </div>
120
  <div class="factory-picker-target"></div>
libs/factory/forms/controls/radio-colors.php CHANGED
@@ -27,9 +27,9 @@
27
  exit;
28
  }
29
 
30
- if( !class_exists('Wbcr_FactoryForms412_RadioColorsControl') ) {
31
 
32
- class Wbcr_FactoryForms412_RadioColorsControl extends Wbcr_FactoryForms412_Control {
33
 
34
  public $type = 'radio-color';
35
 
27
  exit;
28
  }
29
 
30
+ if( !class_exists('Wbcr_FactoryForms422_RadioColorsControl') ) {
31
 
32
+ class Wbcr_FactoryForms422_RadioColorsControl extends Wbcr_FactoryForms422_Control {
33
 
34
  public $type = 'radio-color';
35
 
libs/factory/forms/controls/radio.php CHANGED
@@ -21,9 +21,9 @@
21
  exit;
22
  }
23
 
24
- if( !class_exists('Wbcr_FactoryForms412_RadioControl') ) {
25
 
26
- class Wbcr_FactoryForms412_RadioControl extends Wbcr_FactoryForms412_Control {
27
 
28
  public $type = 'radio';
29
 
21
  exit;
22
  }
23
 
24
+ if( !class_exists('Wbcr_FactoryForms422_RadioControl') ) {
25
 
26
+ class Wbcr_FactoryForms422_RadioControl extends Wbcr_FactoryForms422_Control {
27
 
28
  public $type = 'radio';
29
 
libs/factory/forms/controls/textarea.php CHANGED
@@ -20,9 +20,9 @@
20
  exit;
21
  }
22
 
23
- if( !class_exists('Wbcr_FactoryForms412_TextareaControl') ) {
24
 
25
- class Wbcr_FactoryForms412_TextareaControl extends Wbcr_FactoryForms412_Control {
26
 
27
  public $type = 'textarea';
28
 
20
  exit;
21
  }
22
 
23
+ if( !class_exists('Wbcr_FactoryForms422_TextareaControl') ) {
24
 
25
+ class Wbcr_FactoryForms422_TextareaControl extends Wbcr_FactoryForms422_Control {
26
 
27
  public $type = 'textarea';
28
 
libs/factory/forms/controls/textbox.php CHANGED
@@ -29,9 +29,9 @@
29
  exit;
30
  }
31
 
32
- if( !class_exists('Wbcr_FactoryForms412_TextboxControl') ) {
33
 
34
- class Wbcr_FactoryForms412_TextboxControl extends Wbcr_FactoryForms412_Control {
35
 
36
  public $type = 'textbox';
37
 
29
  exit;
30
  }
31
 
32
+ if( !class_exists('Wbcr_FactoryForms422_TextboxControl') ) {
33
 
34
+ class Wbcr_FactoryForms422_TextboxControl extends Wbcr_FactoryForms422_Control {
35
 
36
  public $type = 'textbox';
37
 
libs/factory/forms/controls/url.php CHANGED
@@ -4,7 +4,7 @@
4
  * Url Control
5
  *
6
  * Main options:
7
- * @see FactoryForms412_TextboxControl
8
  *
9
  * @author Alex Kovalev <alex.kovalevv@gmail.com>
10
  * @copyright (c) 2018, Webcraftic Ltd
@@ -18,9 +18,9 @@
18
  exit;
19
  }
20
 
21
- if( !class_exists('Wbcr_FactoryForms412_UrlControl') ) {
22
 
23
- class Wbcr_FactoryForms412_UrlControl extends Wbcr_FactoryForms412_TextboxControl {
24
 
25
  public $type = 'url';
26
 
4
  * Url Control
5
  *
6
  * Main options:
7
+ * @see FactoryForms422_TextboxControl
8
  *
9
  * @author Alex Kovalev <alex.kovalevv@gmail.com>
10
  * @copyright (c) 2018, Webcraftic Ltd
18
  exit;
19
  }
20
 
21
+ if( !class_exists('Wbcr_FactoryForms422_UrlControl') ) {
22
 
23
+ class Wbcr_FactoryForms422_UrlControl extends Wbcr_FactoryForms422_TextboxControl {
24
 
25
  public $type = 'url';
26
 
libs/factory/forms/controls/wp-editor.php CHANGED
@@ -22,9 +22,9 @@
22
  exit;
23
  }
24
 
25
- if( !class_exists('Wbcr_FactoryForms412_WpEditorControl') ) {
26
 
27
- class Wbcr_FactoryForms412_WpEditorControl extends Wbcr_FactoryForms412_Control {
28
 
29
  public $type = 'wp-editor';
30
 
@@ -42,7 +42,7 @@
42
  }
43
 
44
  if( !isset($this->options['tinymce']['content_css']) ) {
45
- $this->options['tinymce']['content_css'] = FACTORY_FORMS_412_URL . '/assets/css/editor.css';
46
  }
47
  }
48
 
22
  exit;
23
  }
24
 
25
+ if( !class_exists('Wbcr_FactoryForms422_WpEditorControl') ) {
26
 
27
+ class Wbcr_FactoryForms422_WpEditorControl extends Wbcr_FactoryForms422_Control {
28
 
29
  public $type = 'wp-editor';
30
 
42
  }
43
 
44
  if( !isset($this->options['tinymce']['content_css']) ) {
45
+ $this->options['tinymce']['content_css'] = FACTORY_FORMS_422_URL . '/assets/css/editor.css';
46
  }
47
  }
48
 
libs/factory/forms/includes/complex-control.class.php CHANGED
@@ -13,13 +13,13 @@
13
  if( !defined('ABSPATH') ) {
14
  exit;
15
  }
16
- if( !class_exists('Wbcr_FactoryForms412_ComplexControl') ) {
17
  /**
18
  * The base class for all controls.
19
  *
20
  * @since 1.0.0
21
  */
22
- abstract class Wbcr_FactoryForms412_ComplexControl extends Wbcr_FactoryForms412_Control {
23
 
24
  /**
25
  * Is this element a complex control?
@@ -33,7 +33,7 @@
33
  * Contains a set of internal controls.
34
  *
35
  * @since 1.0.0
36
- * @var Wbcr_FactoryForms412_Control[]
37
  */
38
  public $inner_controls = array();
39
 
@@ -41,7 +41,7 @@
41
  * Sets a provider for the control.
42
  *
43
  * @since 1.0.0
44
- * @param Wbcr_IFactoryForms412_ValueProvider $provider
45
  * @return void
46
  */
47
  public function setProvider($provider)
13
  if( !defined('ABSPATH') ) {
14
  exit;
15
  }
16
+ if( !class_exists('Wbcr_FactoryForms422_ComplexControl') ) {
17
  /**
18
  * The base class for all controls.
19
  *
20
  * @since 1.0.0
21
  */
22
+ abstract class Wbcr_FactoryForms422_ComplexControl extends Wbcr_FactoryForms422_Control {
23
 
24
  /**
25
  * Is this element a complex control?
33
  * Contains a set of internal controls.
34
  *
35
  * @since 1.0.0
36
+ * @var Wbcr_FactoryForms422_Control[]
37
  */
38
  public $inner_controls = array();
39
 
41
  * Sets a provider for the control.
42
  *
43
  * @since 1.0.0
44
+ * @param Wbcr_IFactoryForms422_ValueProvider $provider
45
  * @return void
46
  */
47
  public function setProvider($provider)
libs/factory/forms/includes/control-holder.class.php CHANGED
@@ -14,19 +14,19 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_ControlHolder') ) {
18
  /**
19
  * The base class for control holders.
20
  *
21
  * @since 1.0.0
22
  */
23
- abstract class Wbcr_FactoryForms412_ControlHolder extends Wbcr_FactoryForms412_Control {
24
 
25
  /**
26
  * Holder Elements.
27
  *
28
  * @since 1.0.0
29
- * @var Wbcr_FactoryForms412_Control[]
30
  */
31
  protected $elements = array();
32
 
@@ -43,7 +43,7 @@
43
  *
44
  * @since 1.0.0
45
  * @param mixed[] $options A holder options.
46
- * @param Wbcr_FactoryForms412_Form $form A parent form.
47
  */
48
  public function __construct($options, $form)
49
  {
@@ -60,7 +60,7 @@
60
  * Returns holder elements.
61
  *
62
  * @since 1.0.0
63
- * @return Wbcr_FactoryForms412_FormElement[].
64
  */
65
  public function getElements()
66
  {
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_ControlHolder') ) {
18
  /**
19
  * The base class for control holders.
20
  *
21
  * @since 1.0.0
22
  */
23
+ abstract class Wbcr_FactoryForms422_ControlHolder extends Wbcr_FactoryForms422_Control {
24
 
25
  /**
26
  * Holder Elements.
27
  *
28
  * @since 1.0.0
29
+ * @var Wbcr_FactoryForms422_Control[]
30
  */
31
  protected $elements = array();
32
 
43
  *
44
  * @since 1.0.0
45
  * @param mixed[] $options A holder options.
46
+ * @param Wbcr_FactoryForms422_Form $form A parent form.
47
  */
48
  public function __construct($options, $form)
49
  {
60
  * Returns holder elements.
61
  *
62
  * @since 1.0.0
63
+ * @return Wbcr_FactoryForms422_FormElement[].
64
  */
65
  public function getElements()
66
  {
libs/factory/forms/includes/control.class.php CHANGED
@@ -14,14 +14,14 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_Control') ) {
18
 
19
  /**
20
  * The base class for all controls.
21
  *
22
  * @since 1.0.0
23
  */
24
- abstract class Wbcr_FactoryForms412_Control extends Wbcr_FactoryForms412_FormElement {
25
 
26
  /**
27
  * Is this element a control?
@@ -43,7 +43,7 @@
43
  * A provider that is used to get values.
44
  *
45
  * @since 1.0.0
46
- * @var Wbcr_IFactoryForms412_ValueProvider
47
  */
48
  protected $provider = null;
49
 
@@ -51,7 +51,7 @@
51
  * Create a new instance of the control.
52
  *
53
  * @param mixed[] $options
54
- * @param FactoryForms412_Form $form
55
  * @param null $provider
56
  * @since 1.0.0
57
  * @return void
@@ -66,7 +66,7 @@
66
  * Sets a provider for the control.
67
  *
68
  * @since 1.0.0
69
- * @param IFactoryForms412_ValueProvider $provider
70
  * @return void
71
  */
72
  public function setProvider($provider)
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_Control') ) {
18
 
19
  /**
20
  * The base class for all controls.
21
  *
22
  * @since 1.0.0
23
  */
24
+ abstract class Wbcr_FactoryForms422_Control extends Wbcr_FactoryForms422_FormElement {
25
 
26
  /**
27
  * Is this element a control?
43
  * A provider that is used to get values.
44
  *
45
  * @since 1.0.0
46
+ * @var Wbcr_IFactoryForms422_ValueProvider
47
  */
48
  protected $provider = null;
49
 
51
  * Create a new instance of the control.
52
  *
53
  * @param mixed[] $options
54
+ * @param FactoryForms422_Form $form
55
  * @param null $provider
56
  * @since 1.0.0
57
  * @return void
66
  * Sets a provider for the control.
67
  *
68
  * @since 1.0.0
69
+ * @param IFactoryForms422_ValueProvider $provider
70
  * @return void
71
  */
72
  public function setProvider($provider)
libs/factory/forms/includes/custom-element.class.php CHANGED
@@ -14,13 +14,13 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_CustomElement') ) {
18
  /**
19
  * The base class for all controls.
20
  *
21
  * @since 1.0.0
22
  */
23
- abstract class Wbcr_FactoryForms412_CustomElement extends Wbcr_FactoryForms412_FormElement {
24
 
25
  /**
26
  * Is this element a custom form element?
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_CustomElement') ) {
18
  /**
19
  * The base class for all controls.
20
  *
21
  * @since 1.0.0
22
  */
23
+ abstract class Wbcr_FactoryForms422_CustomElement extends Wbcr_FactoryForms422_FormElement {
24
 
25
  /**
26
  * Is this element a custom form element?
libs/factory/forms/includes/form-element.class.php CHANGED
@@ -14,7 +14,7 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_FormElement') ) {
18
 
19
  /**
20
  * The base class for all form element (controls, holders).
@@ -23,7 +23,7 @@
23
  *
24
  * @since 1.0.0
25
  */
26
- abstract class Wbcr_FactoryForms412_FormElement {
27
 
28
  /**
29
  * A type of an elemnt.
@@ -37,7 +37,7 @@
37
  * An html attribute builder.
38
  *
39
  * @since 1.0.0
40
- * @var Wbcr_FactoryForms412_HtmlAttributeBuilder
41
  */
42
  private $html_builder;
43
 
@@ -53,7 +53,7 @@
53
  * A parent form.
54
  *
55
  * @since 1.0.0
56
- * @var Wbcr_FactoryForms412_Form
57
  */
58
  protected $form;
59
 
@@ -61,7 +61,7 @@
61
  * A form layout.
62
  *
63
  * @since 1.0.0
64
- * @var Wbcr_FactoryForms412_FormLayout
65
  */
66
  protected $layout;
67
 
@@ -94,7 +94,7 @@
94
  *
95
  * @since 1.0.0
96
  * @param mixed[] $options A holder options.
97
- * @param Wbcr_FactoryForms412_Form $form A parent form.
98
  */
99
  public function __construct($options, $form)
100
  {
@@ -102,7 +102,7 @@
102
  $this->form = $form;
103
  $this->layout = $form->layout;
104
 
105
- $this->html_builder = new Wbcr_FactoryForms412_HtmlAttributeBuilder();
106
 
107
  if( isset($this->options['cssClass']) ) {
108
  $this->html_builder->addCssClass($this->options['cssClass']);
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_FormElement') ) {
18
 
19
  /**
20
  * The base class for all form element (controls, holders).
23
  *
24
  * @since 1.0.0
25
  */
26
+ abstract class Wbcr_FactoryForms422_FormElement {
27
 
28
  /**
29
  * A type of an elemnt.
37
  * An html attribute builder.
38
  *
39
  * @since 1.0.0
40
+ * @var Wbcr_FactoryForms422_HtmlAttributeBuilder
41
  */
42
  private $html_builder;
43
 
53
  * A parent form.
54
  *
55
  * @since 1.0.0
56
+ * @var Wbcr_FactoryForms422_Form
57
  */
58
  protected $form;
59
 
61
  * A form layout.
62
  *
63
  * @since 1.0.0
64
+ * @var Wbcr_FactoryForms422_FormLayout
65
  */
66
  protected $layout;
67
 
94
  *
95
  * @since 1.0.0
96
  * @param mixed[] $options A holder options.
97
+ * @param Wbcr_FactoryForms422_Form $form A parent form.
98
  */
99
  public function __construct($options, $form)
100
  {
102
  $this->form = $form;
103
  $this->layout = $form->layout;
104
 
105
+ $this->html_builder = new Wbcr_FactoryForms422_HtmlAttributeBuilder();
106
 
107
  if( isset($this->options['cssClass']) ) {
108
  $this->html_builder->addCssClass($this->options['cssClass']);
libs/factory/forms/includes/form-layout.class.php CHANGED
@@ -14,12 +14,12 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_FormLayout') ) {
18
 
19
  /**
20
  * The base class for all form layouts.
21
  */
22
- abstract class Wbcr_FactoryForms412_FormLayout extends Wbcr_FactoryForms412_Holder {
23
 
24
  /**
25
  * A form layout name.
@@ -42,7 +42,7 @@
42
  *
43
  * @since 1.0.0
44
  * @param mixed[] $options A holder options.
45
- * @param Wbcr_FactoryForms412_Form $form A parent form.
46
  */
47
  public function __construct($options, $form)
48
  {
@@ -52,8 +52,8 @@
52
 
53
  parent::__construct($options, $form);
54
 
55
- $this->addCssClass('factory-forms-412-' . $this->type);
56
- $this->addCssClass('factory-forms-412-' . $this->name);
57
  }
58
 
59
  /**
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_FormLayout') ) {
18
 
19
  /**
20
  * The base class for all form layouts.
21
  */
22
+ abstract class Wbcr_FactoryForms422_FormLayout extends Wbcr_FactoryForms422_Holder {
23
 
24
  /**
25
  * A form layout name.
42
  *
43
  * @since 1.0.0
44
  * @param mixed[] $options A holder options.
45
+ * @param Wbcr_FactoryForms422_Form $form A parent form.
46
  */
47
  public function __construct($options, $form)
48
  {
52
 
53
  parent::__construct($options, $form);
54
 
55
+ $this->addCssClass('factory-forms-422-' . $this->type);
56
+ $this->addCssClass('factory-forms-422-' . $this->name);
57
  }
58
 
59
  /**
libs/factory/forms/includes/form.class.php CHANGED
@@ -15,16 +15,16 @@
15
  }
16
 
17
  // creating a license manager for each plugin created via the factory
18
- add_action('wbcr_factory_forms_412_plugin_created', 'wbcr_factory_forms_412_plugin_created');
19
 
20
- function wbcr_factory_forms_412_plugin_created($plugin)
21
  {
22
- $plugin->forms = new Wbcr_FactoryForms412_Manager($plugin);
23
  }
24
 
25
- if( !class_exists('Wbcr_FactoryForms412_Manager') ) {
26
 
27
- class Wbcr_FactoryForms412_Manager {
28
 
29
  // ----------------------------------------------------
30
  // Static fields and methods
@@ -57,7 +57,7 @@
57
  /**
58
  * Registers a set of new controls.
59
  *
60
- * @see FactoryForms412_Form::registerControl()
61
  *
62
  * @since 1.0.0
63
  * @return void
@@ -95,7 +95,7 @@
95
  /**
96
  * Registers a set of new holder controls.
97
  *
98
- * @see FactoryForms412_Form::registerHolder()
99
  *
100
  * @since 1.0.0
101
  * @return void
@@ -129,7 +129,7 @@
129
  /**
130
  * Registers a set of new custom form elements.
131
  *
132
- * @see FactoryForms412_Form::registerCustomElement()
133
  *
134
  * @since 1.0.0
135
  * @return void
@@ -180,11 +180,11 @@
180
  public static $controls_registered = false;
181
  }
182
  }
183
- if( !class_exists('Wbcr_FactoryForms412_Form') ) {
184
  /**
185
  * An abstraction for forms.
186
  */
187
- class Wbcr_FactoryForms412_Form {
188
 
189
  // ----------------------------------------------------
190
  // Object fields and methods
@@ -194,7 +194,7 @@
194
  * A value provider of the form that is used to save and load values.
195
  *
196
  * @since 1.0.0
197
- * @var Wbcr_IFactoryForms412_ValueProvider
198
  */
199
  private $provider;
200
 
@@ -245,7 +245,7 @@
245
  * A current form layout used to render a form.
246
  *
247
  * @since 1.0.0
248
- * @var Wbcr_FactoryForms412_FormLayout
249
  */
250
  public $layout;
251
 
@@ -261,20 +261,20 @@
261
  *
262
  * @since 1.0.0
263
  * @param array $options
264
- * @param Wbcr_Factory412_Plugin $plugin
265
  */
266
- public function __construct(array $options = array(), Wbcr_Factory412_Plugin $plugin)
267
  {
268
  // register controls once, when the first form is created
269
- if( !Wbcr_FactoryForms412_Manager::$controls_registered ) {
270
 
271
- do_action('wbcr_factory_forms_412_register_controls', $plugin);
272
 
273
  //if( !empty($plugin) ) {
274
- do_action('wbcr_factory_forms_412_register_controls_' . $plugin->getPluginName(), $plugin);
275
  //}
276
 
277
- Wbcr_FactoryForms412_Manager::$controls_registered = true;
278
  }
279
 
280
  $this->scope = isset($options['scope']) ? $options['scope'] : null;
@@ -289,14 +289,14 @@
289
  $this->form_layout = 'bootstrap-3';
290
  }
291
 
292
- Wbcr_FactoryForms412_Manager::$temper = 'flat';
293
  }
294
 
295
  /**
296
  * Sets a provider for the control.
297
  *
298
  * @since 1.0.0
299
- * @param Wbcr_IFactoryForms412_ValueProvider $provider
300
  * @return void
301
  */
302
  public function setProvider($provider)
@@ -332,14 +332,14 @@
332
  */
333
  public function getItems()
334
  {
335
- return apply_filters('wbcr_factory_412_form_items', $this->items, $this->name);
336
  }
337
 
338
  /**
339
  * Returns form controls (control objects).
340
  *
341
  * @since 1.0.0
342
- * @return Wbcr_FactoryForms412_Control[]
343
  */
344
  public function getControls()
345
  {
@@ -355,7 +355,7 @@
355
  * Builds a form items to the control objects ready to use.
356
  *
357
  * @param null $holder
358
- * @return Wbcr_FactoryForms412_Control[]
359
  */
360
 
361
  public function createControls($holder = null)
@@ -395,7 +395,7 @@
395
  *
396
  * @since 1.0.0
397
  * @param array $item Item data.
398
- * @return Wbcr_FactoryForms412_FormElement|null A form element.
399
  */
400
  public function createElement($item)
401
  {
@@ -417,7 +417,7 @@
417
  *
418
  * @since 1.0.0
419
  * @param mixed[] $item Data of items.
420
- * @return Wbcr_FactoryForms412_FormElement[] Created elements.
421
  */
422
  public function createElements($items = array())
423
  {
@@ -433,7 +433,7 @@
433
  *
434
  * @since 1.0.0
435
  * @param array $item Item data.
436
- * @return Wbcr_FactoryForms412_Control A control object.
437
  */
438
  public function createControl($item)
439
  {
@@ -441,7 +441,7 @@
441
 
442
  if( is_array($item) ) {
443
 
444
- $control_data = Wbcr_FactoryForms412_Manager::$registered_controls[$item['type']];
445
 
446
  require_once($control_data['include']);
447
 
@@ -465,7 +465,7 @@
465
  *
466
  * @since 1.0.0
467
  * @param array $item Item data.
468
- * @return Wbcr_FactoryForms412_Holder A control holder object.
469
  */
470
  public function createHolder($item)
471
  {
@@ -473,7 +473,7 @@
473
 
474
  if( is_array($item) ) {
475
 
476
- $holderData = Wbcr_FactoryForms412_Manager::$registered_holders[$item['type']];
477
  require_once($holderData['include']);
478
 
479
  $object = new $holderData['class']($item, $this);
@@ -491,7 +491,7 @@
491
  *
492
  * @since 1.0.0
493
  * @param mixed $item Item data.
494
- * @return Wbcr_FactoryForms412_FormElement A custom form element object.
495
  */
496
  public function createCustomElement($item)
497
  {
@@ -499,7 +499,7 @@
499
 
500
  if( is_array($item) ) {
501
 
502
- $data = Wbcr_FactoryForms412_Manager::$registered_custom_elements[$item['type']];
503
  require_once($data['include']);
504
 
505
  $options = $item;
@@ -523,12 +523,12 @@
523
  public function html($options = array())
524
  {
525
 
526
- if( !isset(Wbcr_FactoryForms412_Manager::$form_layouts[$this->form_layout]) ) {
527
  die(sprintf('[ERROR] The form layout %s was not found.', $this->form_layout));
528
  }
529
 
530
  // include a render code
531
- $layout_data = Wbcr_FactoryForms412_Manager::$form_layouts[$this->form_layout];
532
  require_once($layout_data['include']);
533
 
534
  $this->connectAssets();
@@ -552,7 +552,7 @@
552
  {
553
 
554
  $this->connectAssetsForItems();
555
- $layout_data = Wbcr_FactoryForms412_Manager::$form_layouts[$this->form_layout];
556
 
557
  if( $layout_data['name'] == 'default' ) {
558
  if( isset($layout_data['style']) ) {
@@ -602,9 +602,9 @@
602
 
603
  $haystack = array();
604
  if( self::isControl($type) ) {
605
- $haystack = Wbcr_FactoryForms412_Manager::$registered_controls;
606
  } elseif( self::isControlHolder($type) ) {
607
- $haystack = Wbcr_FactoryForms412_Manager::$registered_holders;
608
  }
609
 
610
  if( isset($haystack[$type]) ) {
@@ -660,7 +660,7 @@
660
  */
661
  public static function isControl($item)
662
  {
663
- return isset(Wbcr_FactoryForms412_Manager::$registered_controls[$item['type']]);
664
  }
665
 
666
  /**
@@ -672,7 +672,7 @@
672
  */
673
  public static function isControlHolder($item)
674
  {
675
- return isset(Wbcr_FactoryForms412_Manager::$registered_holders[$item['type']]);
676
  }
677
 
678
  /**
@@ -684,7 +684,7 @@
684
  */
685
  public static function isCustomElement($item)
686
  {
687
- return isset(Wbcr_FactoryForms412_Manager::$registered_custom_elements[$item['type']]);
688
  }
689
  }
690
  }
15
  }
16
 
17
  // creating a license manager for each plugin created via the factory
18
+ add_action('wbcr_factory_forms_422_plugin_created', 'wbcr_factory_forms_422_plugin_created');
19
 
20
+ function wbcr_factory_forms_422_plugin_created($plugin)
21
  {
22
+ $plugin->forms = new Wbcr_FactoryForms422_Manager($plugin);
23
  }
24
 
25
+ if( !class_exists('Wbcr_FactoryForms422_Manager') ) {
26
 
27
+ class Wbcr_FactoryForms422_Manager {
28
 
29
  // ----------------------------------------------------
30
  // Static fields and methods
57
  /**
58
  * Registers a set of new controls.
59
  *
60
+ * @see FactoryForms422_Form::registerControl()
61
  *
62
  * @since 1.0.0
63
  * @return void
95
  /**
96
  * Registers a set of new holder controls.
97
  *
98
+ * @see FactoryForms422_Form::registerHolder()
99
  *
100
  * @since 1.0.0
101
  * @return void
129
  /**
130
  * Registers a set of new custom form elements.
131
  *
132
+ * @see FactoryForms422_Form::registerCustomElement()
133
  *
134
  * @since 1.0.0
135
  * @return void
180
  public static $controls_registered = false;
181
  }
182
  }
183
+ if( !class_exists('Wbcr_FactoryForms422_Form') ) {
184
  /**
185
  * An abstraction for forms.
186
  */
187
+ class Wbcr_FactoryForms422_Form {
188
 
189
  // ----------------------------------------------------
190
  // Object fields and methods
194
  * A value provider of the form that is used to save and load values.
195
  *
196
  * @since 1.0.0
197
+ * @var Wbcr_IFactoryForms422_ValueProvider
198
  */
199
  private $provider;
200
 
245
  * A current form layout used to render a form.
246
  *
247
  * @since 1.0.0
248
+ * @var Wbcr_FactoryForms422_FormLayout
249
  */
250
  public $layout;
251
 
261
  *
262
  * @since 1.0.0
263
  * @param array $options
264
+ * @param Wbcr_Factory424_Plugin $plugin
265
  */
266
+ public function __construct(array $options = array(), Wbcr_Factory424_Plugin $plugin)
267
  {
268
  // register controls once, when the first form is created
269
+ if( !Wbcr_FactoryForms422_Manager::$controls_registered ) {
270
 
271
+ do_action('wbcr_factory_forms_422_register_controls', $plugin);
272
 
273
  //if( !empty($plugin) ) {
274
+ do_action('wbcr_factory_forms_422_register_controls_' . $plugin->getPluginName(), $plugin);
275
  //}
276
 
277
+ Wbcr_FactoryForms422_Manager::$controls_registered = true;
278
  }
279
 
280
  $this->scope = isset($options['scope']) ? $options['scope'] : null;
289
  $this->form_layout = 'bootstrap-3';
290
  }
291
 
292
+ Wbcr_FactoryForms422_Manager::$temper = 'flat';
293
  }
294
 
295
  /**
296
  * Sets a provider for the control.
297
  *
298
  * @since 1.0.0
299
+ * @param Wbcr_IFactoryForms422_ValueProvider $provider
300
  * @return void
301
  */
302
  public function setProvider($provider)
332
  */
333
  public function getItems()
334
  {
335
+ return apply_filters('wbcr_factory_424_form_items', $this->items, $this->name);
336
  }
337
 
338
  /**
339
  * Returns form controls (control objects).
340
  *
341
  * @since 1.0.0
342
+ * @return Wbcr_FactoryForms422_Control[]
343
  */
344
  public function getControls()
345
  {
355
  * Builds a form items to the control objects ready to use.
356
  *
357
  * @param null $holder
358
+ * @return Wbcr_FactoryForms422_Control[]
359
  */
360
 
361
  public function createControls($holder = null)
395
  *
396
  * @since 1.0.0
397
  * @param array $item Item data.
398
+ * @return Wbcr_FactoryForms422_FormElement|null A form element.
399
  */
400
  public function createElement($item)
401
  {
417
  *
418
  * @since 1.0.0
419
  * @param mixed[] $item Data of items.
420
+ * @return Wbcr_FactoryForms422_FormElement[] Created elements.
421
  */
422
  public function createElements($items = array())
423
  {
433
  *
434
  * @since 1.0.0
435
  * @param array $item Item data.
436
+ * @return Wbcr_FactoryForms422_Control A control object.
437
  */
438
  public function createControl($item)
439
  {
441
 
442
  if( is_array($item) ) {
443
 
444
+ $control_data = Wbcr_FactoryForms422_Manager::$registered_controls[$item['type']];
445
 
446
  require_once($control_data['include']);
447
 
465
  *
466
  * @since 1.0.0
467
  * @param array $item Item data.
468
+ * @return Wbcr_FactoryForms422_Holder A control holder object.
469
  */
470
  public function createHolder($item)
471
  {
473
 
474
  if( is_array($item) ) {
475
 
476
+ $holderData = Wbcr_FactoryForms422_Manager::$registered_holders[$item['type']];
477
  require_once($holderData['include']);
478
 
479
  $object = new $holderData['class']($item, $this);
491
  *
492
  * @since 1.0.0
493
  * @param mixed $item Item data.
494
+ * @return Wbcr_FactoryForms422_FormElement A custom form element object.
495
  */
496
  public function createCustomElement($item)
497
  {
499
 
500
  if( is_array($item) ) {
501
 
502
+ $data = Wbcr_FactoryForms422_Manager::$registered_custom_elements[$item['type']];
503
  require_once($data['include']);
504
 
505
  $options = $item;
523
  public function html($options = array())
524
  {
525
 
526
+ if( !isset(Wbcr_FactoryForms422_Manager::$form_layouts[$this->form_layout]) ) {
527
  die(sprintf('[ERROR] The form layout %s was not found.', $this->form_layout));
528
  }
529
 
530
  // include a render code
531
+ $layout_data = Wbcr_FactoryForms422_Manager::$form_layouts[$this->form_layout];
532
  require_once($layout_data['include']);
533
 
534
  $this->connectAssets();
552
  {
553
 
554
  $this->connectAssetsForItems();
555
+ $layout_data = Wbcr_FactoryForms422_Manager::$form_layouts[$this->form_layout];
556
 
557
  if( $layout_data['name'] == 'default' ) {
558
  if( isset($layout_data['style']) ) {
602
 
603
  $haystack = array();
604
  if( self::isControl($type) ) {
605
+ $haystack = Wbcr_FactoryForms422_Manager::$registered_controls;
606
  } elseif( self::isControlHolder($type) ) {
607
+ $haystack = Wbcr_FactoryForms422_Manager::$registered_holders;
608
  }
609
 
610
  if( isset($haystack[$type]) ) {
660
  */
661
  public static function isControl($item)
662
  {
663
+ return isset(Wbcr_FactoryForms422_Manager::$registered_controls[$item['type']]);
664
  }
665
 
666
  /**
672
  */
673
  public static function isControlHolder($item)
674
  {
675
+ return isset(Wbcr_FactoryForms422_Manager::$registered_holders[$item['type']]);
676
  }
677
 
678
  /**
684
  */
685
  public static function isCustomElement($item)
686
  {
687
+ return isset(Wbcr_FactoryForms422_Manager::$registered_custom_elements[$item['type']]);
688
  }
689
  }
690
  }
libs/factory/forms/includes/holder.class.php CHANGED
@@ -14,20 +14,20 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_Holder') ) {
18
 
19
  /**
20
  * The base class for control holders.
21
  *
22
  * @since 1.0.0
23
  */
24
- abstract class Wbcr_FactoryForms412_Holder extends Wbcr_FactoryForms412_FormElement {
25
 
26
  /**
27
  * Holder Elements.
28
  *
29
  * @since 1.0.0
30
- * @var Wbcr_FactoryForms412_Control[]
31
  */
32
  protected $elements = array();
33
 
@@ -44,7 +44,7 @@
44
  *
45
  * @since 1.0.0
46
  * @param mixed[] $options A holder options.
47
- * @param Wbcr_FactoryForms412_Form $form A parent form.
48
  */
49
  public function __construct($options, $form)
50
  {
@@ -56,7 +56,7 @@
56
  * Returns holder elements.
57
  *
58
  * @since 1.0.0
59
- * @return Wbcr_FactoryForms412_Control[].
60
  */
61
  public function getElements()
62
  {
@@ -84,7 +84,7 @@
84
  $is_first_item = false;
85
  }
86
 
87
- do_action('wbcr_factory_412_form_before_element_' . $element->getOption('name'));
88
 
89
  // if a current item is a control holder
90
  if( $element->is_holder ) {
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_Holder') ) {
18
 
19
  /**
20
  * The base class for control holders.
21
  *
22
  * @since 1.0.0
23
  */
24
+ abstract class Wbcr_FactoryForms422_Holder extends Wbcr_FactoryForms422_FormElement {
25
 
26
  /**
27
  * Holder Elements.
28
  *
29
  * @since 1.0.0
30
+ * @var Wbcr_FactoryForms422_Control[]
31
  */
32
  protected $elements = array();
33
 
44
  *
45
  * @since 1.0.0
46
  * @param mixed[] $options A holder options.
47
+ * @param Wbcr_FactoryForms422_Form $form A parent form.
48
  */
49
  public function __construct($options, $form)
50
  {
56
  * Returns holder elements.
57
  *
58
  * @since 1.0.0
59
+ * @return Wbcr_FactoryForms422_Control[].
60
  */
61
  public function getElements()
62
  {
84
  $is_first_item = false;
85
  }
86
 
87
+ do_action('wbcr_factory_424_form_before_element_' . $element->getOption('name'));
88
 
89
  // if a current item is a control holder
90
  if( $element->is_holder ) {
libs/factory/forms/includes/html-builder.class.php CHANGED
@@ -14,13 +14,13 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_HtmlAttributeBuilder') ) {
18
  /**
19
  * Html Attribute Builder
20
  *
21
  * @since 1.0.0
22
  */
23
- class Wbcr_FactoryForms412_HtmlAttributeBuilder {
24
 
25
  /**
26
  * An array to store css classes.
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_HtmlAttributeBuilder') ) {
18
  /**
19
  * Html Attribute Builder
20
  *
21
  * @since 1.0.0
22
  */
23
+ class Wbcr_FactoryForms422_HtmlAttributeBuilder {
24
 
25
  /**
26
  * An array to store css classes.
libs/factory/forms/includes/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/forms/includes/providers/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/forms/includes/providers/meta-value-provider.class.php CHANGED
@@ -14,7 +14,7 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_OptionsValueProvider') ) {
18
 
19
  /**
20
  * Factory Meta Value Provider
@@ -24,7 +24,7 @@
24
  *
25
  * @since 1.0.0
26
  */
27
- class Wbcr_FactoryForms412_MetaValueProvider implements Wbcr_IFactoryForms412_ValueProvider {
28
 
29
 
30
  public $scope;
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_OptionsValueProvider') ) {
18
 
19
  /**
20
  * Factory Meta Value Provider
24
  *
25
  * @since 1.0.0
26
  */
27
+ class Wbcr_FactoryForms422_MetaValueProvider implements Wbcr_IFactoryForms422_ValueProvider {
28
 
29
 
30
  public $scope;
libs/factory/forms/includes/providers/options-value-provider.class.php CHANGED
@@ -13,7 +13,7 @@
13
  exit;
14
  }
15
 
16
- if( !class_exists('Wbcr_FactoryForms412_OptionsValueProvider') ) {
17
 
18
  /**
19
  * Factory Options Value Provider
@@ -22,7 +22,7 @@
22
  *
23
  * @since 1.0.0
24
  */
25
- class Wbcr_FactoryForms412_OptionsValueProvider implements Wbcr_IFactoryForms412_ValueProvider {
26
 
27
  /**
28
  * A prefix that will be added to all option names.
@@ -43,7 +43,7 @@
43
  /**
44
  * Creates a new instance of an options value provider.
45
  */
46
- public function __construct(Wbcr_Factory412_Plugin $plugin)
47
  {
48
  $this->plugin = $plugin;
49
  }
13
  exit;
14
  }
15
 
16
+ if( !class_exists('Wbcr_FactoryForms422_OptionsValueProvider') ) {
17
 
18
  /**
19
  * Factory Options Value Provider
22
  *
23
  * @since 1.0.0
24
  */
25
+ class Wbcr_FactoryForms422_OptionsValueProvider implements Wbcr_IFactoryForms422_ValueProvider {
26
 
27
  /**
28
  * A prefix that will be added to all option names.
43
  /**
44
  * Creates a new instance of an options value provider.
45
  */
46
+ public function __construct(Wbcr_Factory424_Plugin $plugin)
47
  {
48
  $this->plugin = $plugin;
49
  }
libs/factory/forms/includes/providers/value-provider.interface.php CHANGED
@@ -14,13 +14,13 @@
14
  if( !defined('ABSPATH') ) {
15
  exit;
16
  }
17
- if( !class_exists('Wbcr_IFactoryForms412_ValueProvider') ) {
18
  /**
19
  * The interface for all value provides.
20
  *
21
  * @since 1.0.0
22
  */
23
- interface Wbcr_IFactoryForms412_ValueProvider {
24
 
25
  /**
26
  * Inits a form a provider to get data from a storage.
14
  if( !defined('ABSPATH') ) {
15
  exit;
16
  }
17
+ if( !class_exists('Wbcr_IFactoryForms422_ValueProvider') ) {
18
  /**
19
  * The interface for all value provides.
20
  *
21
  * @since 1.0.0
22
  */
23
+ interface Wbcr_IFactoryForms422_ValueProvider {
24
 
25
  /**
26
  * Inits a form a provider to get data from a storage.
libs/factory/forms/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/forms/langs/index.php DELETED
File without changes
libs/factory/forms/langs/{wbcr_factory_forms_412-ru_RU.mo → wbcr_factory_forms_422-ru_RU.mo} RENAMED
File without changes
libs/factory/forms/langs/{wbcr_factory_forms_412-ru_RU.po → wbcr_factory_forms_422-ru_RU.po} RENAMED
File without changes
libs/factory/forms/layouts/bootstrap-3/bootstrap-3.php CHANGED
@@ -14,11 +14,11 @@
14
  exit;
15
  }
16
 
17
- if( !class_exists('Wbcr_FactoryForms412_Bootstrap3FormLayout') ) {
18
  /**
19
  * A form layout based on Twitter Bootstrap 3
20
  */
21
- class Wbcr_FactoryForms412_Bootstrap3FormLayout extends Wbcr_FactoryForms412_FormLayout {
22
 
23
  public $name = 'default';
24
 
@@ -27,7 +27,7 @@
27
  *
28
  * @since 1.0.0
29
  * @param array $options A holder options.
30
- * @param Wbcr_FactoryForms412_Form $form A parent form.
31
  */
32
  public function __construct($options, $form)
33
  {
@@ -68,7 +68,7 @@
68
  }
69
 
70
  /**
71
- * @param Wbcr_FactoryForms412_Control $control
72
  */
73
  public function beforeControl($control)
74
  {
@@ -116,7 +116,7 @@
116
  }
117
 
118
  /**
119
- * @param Wbcr_FactoryForms412_Control $control
120
  */
121
  public function afterControl($control)
122
  {
@@ -168,7 +168,7 @@
168
  }
169
 
170
  /**
171
- * @param Wbcr_FactoryForms412_Control $control
172
  * @param int $index
173
  * @param int $total
174
  */
@@ -193,7 +193,7 @@
193
  }
194
 
195
  /**
196
- * @param Wbcr_FactoryForms412_Control $control
197
  * @param int $index
198
  * @param int $total
199
  */
14
  exit;
15
  }
16
 
17
+ if( !class_exists('Wbcr_FactoryForms422_Bootstrap3FormLayout') ) {
18
  /**
19
  * A form layout based on Twitter Bootstrap 3
20
  */
21
+ class Wbcr_FactoryForms422_Bootstrap3FormLayout extends Wbcr_FactoryForms422_FormLayout {
22
 
23
  public $name = 'default';
24
 
27
  *
28
  * @since 1.0.0
29
  * @param array $options A holder options.
30
+ * @param Wbcr_FactoryForms422_Form $form A parent form.
31
  */
32
  public function __construct($options, $form)
33
  {
68
  }
69
 
70
  /**
71
+ * @param Wbcr_FactoryForms422_Control $control
72
  */
73
  public function beforeControl($control)
74
  {
116
  }
117
 
118
  /**
119
+ * @param Wbcr_FactoryForms422_Control $control
120
  */
121
  public function afterControl($control)
122
  {
168
  }
169
 
170
  /**
171
+ * @param Wbcr_FactoryForms422_Control $control
172
  * @param int $index
173
  * @param int $total
174
  */
193
  }
194
 
195
  /**
196
+ * @param Wbcr_FactoryForms422_Control $control
197
  * @param int $index
198
  * @param int $total
199
  */
libs/factory/forms/layouts/bootstrap-3/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/forms/layouts/index.php CHANGED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/freemius/boot.php CHANGED
@@ -2,11 +2,11 @@
2
  /**
3
  * Load Freemius module.
4
  *
5
- * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
 
 
6
  * @copyright (c) 2018, Webcraftic Ltd
7
  *
8
- * @package core
9
- * @since 1.0.0
10
  */
11
 
12
  // Exit if accessed directly
@@ -14,29 +14,39 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  exit;
15
  }
16
 
17
- if ( defined( 'FACTORY_FREEMIUS_101_LOADED' ) ) {
18
  return;
19
  }
20
 
21
- define( 'FACTORY_FREEMIUS_101_LOADED', true );
22
- define( 'FACTORY_FREEMIUS_101_DIR', dirname( __FILE__ ) );
23
- define( 'FACTORY_FREEMIUS_101_URL', plugins_url( null, __FILE__ ) );
 
 
24
 
25
  #comp merge
26
  // Freemius
27
- require_once( FACTORY_FREEMIUS_101_DIR . '/includes/entities/class-freemius-entity.php' );
28
- require_once( FACTORY_FREEMIUS_101_DIR . '/includes/entities/class-freemius-scope.php' );
29
- require_once( FACTORY_FREEMIUS_101_DIR . '/includes/entities/class-freemius-user.php' );
30
- require_once( FACTORY_FREEMIUS_101_DIR . '/includes/entities/class-freemius-site.php' );
31
- require_once( FACTORY_FREEMIUS_101_DIR . '/includes/entities/class-freemius-license.php' );
32
-
33
- require_once( FACTORY_FREEMIUS_101_DIR . '/includes/licensing/class-freemius-provider.php' );
34
-
35
- require_once( FACTORY_FREEMIUS_101_DIR . '/includes/updates/class-freemius-repository.php' );
36
 
37
  if ( ! class_exists( 'Freemius_Api_WordPress' ) ) {
38
- require_once FACTORY_FREEMIUS_101_DIR . '/includes/sdk/FreemiusWordPress.php';
39
  }
40
 
41
- require_once( FACTORY_FREEMIUS_101_DIR . '/includes/class-freemius-api.php' );
 
 
 
 
 
 
 
 
 
 
42
  #endcomp
2
  /**
3
  * Load Freemius module.
4
  *
5
+ * @author Webcraftic <wordpress.webraftic@gmail.com>, Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @since 1.0.0
7
+ * @package core
8
  * @copyright (c) 2018, Webcraftic Ltd
9
  *
 
 
10
  */
11
 
12
  // Exit if accessed directly
14
  exit;
15
  }
16
 
17
+ if ( defined( 'FACTORY_FREEMIUS_112_LOADED' ) ) {
18
  return;
19
  }
20
 
21
+ define( 'FACTORY_FREEMIUS_112_VERSION', '1.1.2' );
22
+
23
+ define( 'FACTORY_FREEMIUS_112_LOADED', true );
24
+ define( 'FACTORY_FREEMIUS_112_DIR', dirname( __FILE__ ) );
25
+ define( 'FACTORY_FREEMIUS_112_URL', plugins_url( null, __FILE__ ) );
26
 
27
  #comp merge
28
  // Freemius
29
+ require_once( FACTORY_FREEMIUS_112_DIR . '/includes/entities/class-freemius-entity.php' );
30
+ require_once( FACTORY_FREEMIUS_112_DIR . '/includes/entities/class-freemius-scope.php' );
31
+ require_once( FACTORY_FREEMIUS_112_DIR . '/includes/entities/class-freemius-user.php' );
32
+ require_once( FACTORY_FREEMIUS_112_DIR . '/includes/entities/class-freemius-site.php' );
33
+ require_once( FACTORY_FREEMIUS_112_DIR . '/includes/entities/class-freemius-license.php' );
34
+ require_once( FACTORY_FREEMIUS_112_DIR . '/includes/licensing/class-freemius-provider.php' );
35
+ require_once( FACTORY_FREEMIUS_112_DIR . '/includes/updates/class-freemius-repository.php' );
 
 
36
 
37
  if ( ! class_exists( 'Freemius_Api_WordPress' ) ) {
38
+ require_once FACTORY_FREEMIUS_112_DIR . '/includes/sdk/FreemiusWordPress.php';
39
  }
40
 
41
+ require_once( FACTORY_FREEMIUS_112_DIR . '/includes/class-freemius-api.php' );
42
+
43
+ /**
44
+ * @param Wbcr_Factory424_Plugin $plugin
45
+ */
46
+ add_action( 'wbcr_factory_freemius_112_plugin_created', function ( $plugin ) {
47
+ # Устанавливаем класс провайдера лицензий для премиум менеджера
48
+ $plugin->set_license_provider( 'freemius', 'WBCR\Factory_Freemius_112\Premium\Provider' );
49
+ # Устанавливаем класс репозитория обновлений для менеджера обновлений
50
+ $plugin->set_update_repository( 'freemius', 'WBCR\Factory_Freemius_112\Updates\Freemius_Repository' );
51
+ } );
52
  #endcomp
libs/factory/freemius/includes/class-freemius-api.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Freemius_101;
4
 
5
  use Freemius_Api_WordPress;
6
  use Freemius_Exception;
7
- use Wbcr_Factory412_Plugin;
8
 
9
  if ( ! defined( 'ABSPATH' ) ) {
10
  exit;
@@ -33,7 +33,7 @@ final class Api {
33
  private $api;
34
 
35
  /**
36
- * @var Wbcr_Factory412_Plugin
37
  */
38
  private $plugin;
39
 
@@ -48,14 +48,14 @@ final class Api {
48
  private static $clock_diff;
49
 
50
  /**
51
- * @param Wbcr_Factory412_Plugin $slug
52
  * @param string $scope 'app', 'developer', 'user' or 'install'.
53
  * @param number $id Element's id.
54
  * @param string $public_key Public key.
55
  * @param bool|string $secret_key Element's secret key.
56
  * @param bool $is_sandbox
57
  */
58
- private function __construct( Wbcr_Factory412_Plugin $plugin, $scope, $id, $public_key, $secret_key, $is_sandbox ) {
59
  if ( ! class_exists( 'Freemius_Api_WordPress' ) ) {
60
  require_once WP_FS__DIR_SDK . '/FreemiusWordPress.php';
61
  }
@@ -73,7 +73,7 @@ final class Api {
73
  }
74
 
75
  /**
76
- * @param Wbcr_Factory412_Plugin $plugin
77
  * @param string $scope 'app', 'developer', 'user' or 'install'.
78
  * @param number $id Element's id.
79
  * @param string $public_key Public key.
@@ -82,7 +82,7 @@ final class Api {
82
  *
83
  * @return Api
84
  */
85
- public static function instance( Wbcr_Factory412_Plugin $plugin, $scope, $id, $public_key, $is_sandbox, $secret_key = false ) {
86
  $identifier = md5( $plugin->getPluginName() . $scope . $id . $public_key . ( is_string( $secret_key ) ? $secret_key : '' ) . json_encode( $is_sandbox ) );
87
 
88
  if ( ! isset( self::$instances[ $identifier ] ) ) {
1
  <?php
2
 
3
+ namespace WBCR\Factory_Freemius_112;
4
 
5
  use Freemius_Api_WordPress;
6
  use Freemius_Exception;
7
+ use Wbcr_Factory424_Plugin;
8
 
9
  if ( ! defined( 'ABSPATH' ) ) {
10
  exit;
33
  private $api;
34
 
35
  /**
36
+ * @var Wbcr_Factory424_Plugin
37
  */
38
  private $plugin;
39
 
48
  private static $clock_diff;
49
 
50
  /**
51
+ * @param Wbcr_Factory424_Plugin $slug
52
  * @param string $scope 'app', 'developer', 'user' or 'install'.
53
  * @param number $id Element's id.
54
  * @param string $public_key Public key.
55
  * @param bool|string $secret_key Element's secret key.
56
  * @param bool $is_sandbox
57
  */
58
+ private function __construct( Wbcr_Factory424_Plugin $plugin, $scope, $id, $public_key, $secret_key, $is_sandbox ) {
59
  if ( ! class_exists( 'Freemius_Api_WordPress' ) ) {
60
  require_once WP_FS__DIR_SDK . '/FreemiusWordPress.php';
61
  }
73
  }
74
 
75
  /**
76
+ * @param Wbcr_Factory424_Plugin $plugin
77
  * @param string $scope 'app', 'developer', 'user' or 'install'.
78
  * @param number $id Element's id.
79
  * @param string $public_key Public key.
82
  *
83
  * @return Api
84
  */
85
+ public static function instance( Wbcr_Factory424_Plugin $plugin, $scope, $id, $public_key, $is_sandbox, $secret_key = false ) {
86
  $identifier = md5( $plugin->getPluginName() . $scope . $id . $public_key . ( is_string( $secret_key ) ? $secret_key : '' ) . json_encode( $is_sandbox ) );
87
 
88
  if ( ! isset( self::$instances[ $identifier ] ) ) {
libs/factory/freemius/includes/entities/class-freemius-entity.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Freemius_101\Entities;
4
 
5
  use stdClass;
6
 
1
  <?php
2
 
3
+ namespace WBCR\Factory_Freemius_112\Entities;
4
 
5
  use stdClass;
6
 
libs/factory/freemius/includes/entities/class-freemius-license.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Freemius_101\Entities;
4
 
5
  use stdClass;
6
 
@@ -14,7 +14,7 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  * @copyright (c) 2018 Webraftic Ltd, Freemius, Inc.
15
  * @version 1.0
16
  */
17
- class License extends Entity implements \WBCR\Factory_412\Premium\Interfaces\License {
18
 
19
  /**
20
  * @var number
1
  <?php
2
 
3
+ namespace WBCR\Factory_Freemius_112\Entities;
4
 
5
  use stdClass;
6
 
14
  * @copyright (c) 2018 Webraftic Ltd, Freemius, Inc.
15
  * @version 1.0
16
  */
17
+ class License extends Entity implements \WBCR\Factory_424\Premium\Interfaces\License {
18
 
19
  /**
20
  * @var number
libs/factory/freemius/includes/entities/class-freemius-plugin.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Freemius_101\Entities;
4
 
5
  use stdClass;
6
 
1
  <?php
2
 
3
+ namespace WBCR\Factory_Freemius_112\Entities;
4
 
5
  use stdClass;
6
 
libs/factory/freemius/includes/entities/class-freemius-scope.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Freemius_101\Entities;
4
 
5
  use stdClass;
6
 
1
  <?php
2
 
3
+ namespace WBCR\Factory_Freemius_112\Entities;
4
 
5
  use stdClass;
6
 
libs/factory/freemius/includes/entities/class-freemius-site.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Freemius_101\Entities;
4
 
5
  use stdClass;
6
 
1
  <?php
2
 
3
+ namespace WBCR\Factory_Freemius_112\Entities;
4
 
5
  use stdClass;
6
 
libs/factory/freemius/includes/entities/class-freemius-user.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Freemius_101\Entities;
4
 
5
  if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
1
  <?php
2
 
3
+ namespace WBCR\Factory_Freemius_112\Entities;
4
 
5
  if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
libs/factory/freemius/includes/entities/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/freemius/includes/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
libs/factory/freemius/includes/licensing/class-freemius-provider.php CHANGED
@@ -1,17 +1,16 @@
1
  <?php
2
 
3
- namespace WBCR\Factory_Freemius_101\Premium;
4
-
5
- use WBCR\Factory_Freemius_101\Entities\License;
6
- use WBCR\Factory_Freemius_101\Entities\Plugin;
7
- use WBCR\Factory_Freemius_101\Entities\Site;
8
- use WBCR\Factory_Freemius_101\Entities\User;
9
- use WBCR\Factory_412\Premium\Provider as License_Provider;
10
- use Wbcr_Factory412_Plugin;
11
- use WBCR\Factory_Freemius_101\Api;
12
  use WP_Error;
13
  use Exception;
14
- use stdClass;
15
 
16
  // Exit if accessed directly
17
  if ( ! defined( 'ABSPATH' ) ) {
@@ -19,8 +18,7 @@ if ( ! defined( 'ABSPATH' ) ) {
19
  }
20
 
21
  /**
22
- * @author Webcraftic <wordpress.webraftic@gmail.com>,
1
  <?php
2
 
3
+ namespace WBCR\Factory_Freemius_112\Premium;
4
+
5
+ use WBCR\Factory_Freemius_112\Entities\License;
6
+ use WBCR\Factory_Freemius_112\Entities\Plugin;
7
+ use WBCR\Factory_Freemius_112\Entities\Site;
8
+ use WBCR\Factory_Freemius_112\Entities\User;
9
+ use WBCR\Factory_424\Premium\Provider as License_Provider;
10
+ use Wbcr_Factory424_Plugin;
11
+ use WBCR\Factory_Freemius_112\Api;
12
  use WP_Error;
13
  use Exception;
 
14
 
15
  // Exit if accessed directly
16
  if ( ! defined( 'ABSPATH' ) ) {
18
  }
19
 
20
  /**