· 6 years ago · Jan 09, 2020, 06:20 PM
1<?php
2/*
3Plugin Name: Gravity Forms Debug Add-On
4Plugin URI: https://www.gravityforms.com
5Description: Helps debug issues with Gravity Forms.
6Version: 1.0.beta11
7Author: rocketgenius
8Author URI: https://www.rocketgenius.com
9License: GPL-2.0+
10Text Domain: gravityformsdebug
11Domain Path: /languages
12
13------------------------------------------------------------------------
14Copyright 2012-2019 Rocketgenius Inc.
15
16This program is free software; you can redistribute it and/or modify
17it under the terms of the GNU General Public License as published by
18the Free Software Foundation; either version 2 of the License, or
19(at your option) any later version.
20
21This program is distributed in the hope that it will be useful,
22but WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24GNU General Public License for more details.
25
26You should have received a copy of the GNU General Public License
27along with this program; if not, write to the Free Software
28Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29*/
30
31// If the add-on framework isn't there, bail.
32if( ! is_callable( array( 'GFForms', 'include_addon_framework' ) ) ) {
33 return;
34}
35
36// Include the addon framework.
37GFForms::include_addon_framework();
38
39
40/**
41 * Class GFDebug
42 */
43class GFDebug extends GFAddOn {
44
45 /**
46 * @var string
47 */
48 protected $_version = '1.0.beta11';
49
50 /**
51 * @var string
52 */
53 protected $_min_gravityforms_version = '2.2';
54
55 /**
56 * @var string
57 */
58 protected $_slug = 'gravityformsdebug';
59
60 /**
61 * @var string
62 */
63 protected $_path = 'gravityformsdebug/debug.php';
64
65 /**
66 * @var string
67 */
68 protected $_full_path = __FILE__;
69
70 /**
71 * @var string
72 */
73 protected $_title = 'Gravity Forms Debug Add-On';
74
75 /**
76 * @var string
77 */
78 protected $_short_title = 'Debug';
79
80 /**
81 * @var string
82 */
83 protected $_capabilities_plugin_page = 'activate_plugins';
84
85 /**
86 * @var string
87 */
88 public $_mu_plugin_file = 'gf_mu_debug.php';
89
90 /**
91 * @var array
92 */
93 public $_gf_plugins = array();
94
95 /**
96 * @var array
97 */
98 public $_immune_plugins = array(
99 'Gravity Forms',
100 'Gravity Forms Debug Add-On'
101 );
102
103 /**
104 * @var array
105 */
106 public $_default_themes = array(
107 'Twenty Nineteen' => 'twentynineteen',
108 'Twenty Seventeen' => 'twentyseventeen',
109 'Twenty Sixteen' => 'twentysixteen',
110 'Twenty Fifteen' => 'twentyfifteen',
111 'Twenty Fourteen' => 'twentyfourteen',
112 'Twenty Thirteen' => 'twentythirteen',
113 'Twenty Twelve' => 'twentytwelve',
114 'Twenty Eleven' => 'twentyeleven',
115 'Twenty Ten' => 'twentyten'
116 );
117
118 /**
119 * @var null
120 */
121 private static $instance = null;
122
123 /**
124 * @return GFDebug|null
125 */
126 public static function get_instance() {
127
128 if ( self::$instance == null ) {
129 self::$instance = new self;
130 }
131
132 return self::$instance;
133 }
134
135 /**
136 * GFDebug constructor.
137 */
138 public function __construct() {
139
140 add_action( 'init', array( $this, 'maybe_handle_settings_submission' ), 1 );
141
142 parent::__construct();
143
144 }
145
146 /**
147 * Prevent the add-on being listed on the logging tab.
148 *
149 * @param array $plugins Add-ons which support logging.
150 *
151 * @return array
152 */
153 public function set_logging_supported( $plugins ) {
154 return $plugins;
155 }
156
157 /**
158 *
159 */
160 public function plugin_page() {
161
162 $this->page_header();
163
164 $func = $this->get_current_subview() . '_page';
165
166 if( is_callable( array( $this, $func ) ) ) {
167 call_user_func( array( $this, $func ) );
168 } else {
169 die( __( 'This subview does not exist.', 'gravityformsdebug' ) );
170 }
171
172 $this->page_footer();
173
174 }
175
176 /**
177 *
178 */
179 public function conflict_tester_page() {
180 ?>
181
182 <form method="post" action="" id="gdebug-form">
183
184 <h2><?php _e( 'Conflict Tester', 'gravityformsdebug' ); ?></h2>
185
186 <input type="hidden" name="<?php echo $this->_slug; ?>_conflict_tester_settings" value="1" />
187 <input type="hidden" name="action" id="gdebug-action" value="" />
188 <?php wp_nonce_field( $this->prefix( 'ct_settings_submission' ), $this->prefix( 'ct_settings_submission' ) ); ?>
189
190 <?php $this->conflict_tester_settings_ui(); ?>
191
192 </form>
193
194 <style type="text/css">
195 #tab_conflict_tester h2 { margin: 0 0 24px; }
196 #gdebug-form { }
197 #gdebug-form .button { vertical-align: middle; }
198 .gdebug-ct-plugins-select-all { padding: 0 20px; margin: 0 0 20px; }
199 .gdebug-ct-plugins { overflow: hidden; border: 1px solid #eee; padding: 20px; margin: 0 0 20px; background-color: #fff; }
200 .gdebug-ct-plugins li { width: 50%; float: left; }
201 .gdebug-ct-plugins li.active label { font-weight: bold !important; }
202 .gdebug-ct-plugin-actions { margin: 0 0 20px; }
203 .gdebug-ct-plugin-actions li { }
204 .gdebug-ct-plugins .gdebug-select-all { width: 100%; border-bottom: 1px dotted #eee; margin: 0 0 10px; padding: 0 0 10px; }
205 .gdebug-plugin-actions-row { }
206 .gdebug-plugin-actions-row .gdebug-selected-label { margin-left: 10px; }
207 .gdebug-theme-file { color: #999; }
208 .wp-active label:after {
209 font-family: 'FontAwesome', sans-serif;
210 content: "\f069";
211 padding-left: 5px;
212 opacity: 0.3;
213 }
214 .wp-active-note { color: #999; float: right; }
215 .wp-active-note i { color: #000; opacity: 0.3; }
216 </style>
217
218 <script type="text/javascript">
219
220 jQuery( document ).ready( function( $ ){
221
222
223 var $pluginInputs = $( '.gdebug-ct-plugins input' );
224
225 $pluginInputs.click( function() {
226 $( 'button#gdebug-save-active-plugins' ).prop( 'disabled', false );
227 } );
228
229 $pluginInputs.not( '.gdebug-select-all input' ).click( function() {
230 if( ! $( this ).is( ':checked' ) )
231 $( this ).parents( '.gdebug-ct-plugins' ).find( '.gdebug-select-all input' ).prop( 'checked', false );
232 } );
233
234 } );
235
236 ( function( $, GDebug ){
237
238 GDebug.setActionSubmit = function( action ) {
239
240 var actionInput = $( 'input#gdebug-action' ),
241 form = $( 'form#gdebug-form' );
242
243 actionInput.val( action );
244 form.submit();
245
246 }
247
248 })( jQuery, window.GDebug = window.GDebug || {} );
249
250 </script>
251
252 <?php
253
254 }
255
256 /**
257 *
258 */
259 private function conflict_tester_settings_ui() {
260
261 if( $this->is_conflict_tester_enabled() ) {
262
263 $is_installed = $this->install_mu_plugin();
264 $plugins = get_plugins();
265 $default_theme = $this->get_default_theme();
266
267 if( ! $is_installed ): ?>
268 <div id="message" class="error"><p><?php _e( 'There was an issue installing the conflict tester.', 'gravityformdebug' ); ?></p></div>
269 <?php endif;
270
271 }
272
273 ?>
274
275 <table class="form-table">
276
277 <tbody>
278
279 <tr valign="top">
280 <th scope="row"><label for=""><?php _e( 'Conflict Tester Status', 'gravityformsdebug' ); ?></label></th>
281 <td>
282 <?php if( $this->is_conflict_tester_enabled() ): ?>
283 <button class="button" type="button" onclick="GDebug.setActionSubmit( 'disable' );"><?php _e( 'Disable Conflict Tester', 'gravityformsdebug' ); ?></button>
284 <?php else: ?>
285 <button class="button" type="button" onclick="GDebug.setActionSubmit( 'enable' );"><?php _e( 'Enable Conflict Tester', 'gravityformsdebug' ); ?></button>
286 <?php if( rgget( 'error' ) && rgget( 'disabled' ) ): ?>
287 <?php $this->disable_conflict_tester( false ); ?>
288 <span id="enable-ct-message" class="gf_keystatus_invalid_text" style="margin-left:10px;"><i class="fa fa-times"></i> Conflict Tester cannot be enabled on this site.</i></span>
289 <?php endif; ?>
290 <script type="text/javascript"> setTimeout( function() { jQuery( '#enable-ct-message' ).fadeOut(); }, 5000 ); </script>
291 <p class="description"><?php _e( 'All plugins will be disabled and a default WordPress theme will be used when enabled. This only applies to the currently logged in user. The currently active plugins and theme will load for all other users and visitors.' ); ?></p>
292 <?php endif; ?>
293 </td>
294 </tr>
295
296 <?php if( $this->is_conflict_tester_enabled() ): ?>
297
298 <tr valign="top" class="gdebug-theme-row">
299 <th><label for=""><?php _e( 'Default Theme', 'gravityformsdebug' ); ?></label></th>
300 <td>
301
302 <?php if( ! $default_theme ): ?>
303
304 <?php
305
306 $theme_names = array_keys( $this->_default_themes );
307 $theme_name = rgar( $theme_names, 0 );
308
309 printf(
310 __( 'You do not have any WordPress default themes installed. Please install %1$s%3$s%2$s to complete a full conflict test.' ),
311 '<a href="' . admin_url( 'theme-install.php?search=' . urlencode( $theme_name ) ) . '">',
312 '</a>',
313 $theme_name
314 );
315
316 ?>
317
318 <?php else: ?>
319
320 <?php printf(
321 '%s <span class="gdebug-theme-file">(%s)</span>',
322 $default_theme->name, $default_theme->template
323 ); ?>
324
325 <?php endif; ?>
326
327 </td>
328 </tr>
329
330 <tr valign="top" class="gdebug-plugin-actions-row">
331 <th><label for=""><?php _e( 'Plugins', 'gravityformsdebug' ); ?></label></th>
332 <td>
333 <button disabled="disabled" class="button" id="gdebug-save-active-plugins" onclick="GDebug.setActionSubmit( 'activate_plugins' );">
334 <?php _e( 'Save Active Plugins', 'gravityformsdebug' ); ?>
335 </button>
336 <?php if( rgget( 'action' ) == 'active-plugins-updated' ): ?>
337 <span id="active-plugins-message" class="gf_keystatus_valid_text" style="margin-left:10px;"><i class="fa fa-check"></i> Active plugins saved.</i></span>
338 <?php elseif( rgget( 'error' ) ): ?>
339 <span id="active-plugins-message" class="gf_keystatus_invalid_text" style="margin-left:10px;"><i class="fa fa-times"></i> One or more of the plugins generated an error.</i></span>
340 <?php endif; ?>
341 <script type="text/javascript"> setTimeout( function() { jQuery( '#active-plugins-message' ).fadeOut(); }, 5000 ); </script>
342 </td>
343 </tr>
344
345 <tr>
346 <td colspan="2">
347
348 <h4><?php _e( 'Gravity Forms Plugins', 'gravityformdebug' ); ?></h4>
349 <ul class="gdebug-ct-plugins gdebug-ct-gf-plugins">
350
351 <li class="gdebug-select-all">
352 <input type="checkbox" id="gdebug-select-all-gf" onclick="jQuery( '.gdebug-ct-gf-plugins input' ).prop( 'checked', jQuery( this ).is( ':checked' ) );" />
353 <label for="gdebug-select-all-gf"><?php _e( 'Select All', 'gravityformsdebug' ); ?></label>
354 <span class="wp-active-note">
355 <i class="fa fa-asterisk"></i> <?php _e( 'Denotes Orginally Active Plugin', 'gravityformsdebug' ); ?>
356 </span>
357 </li>
358
359 <?php foreach( $plugins as $slug => $plugin ) {
360
361 if( ! in_array( $plugin['Name'], $this->get_gf_plugins() ) || in_array( $plugin['Name'], $this->_immune_plugins ) )
362 continue;
363
364 $is_active = $this->is_plugin_active( $slug );
365
366 $classes = array();
367 if( $is_active ) {
368 $classes[] = 'active';
369 }
370
371 // is plugin active outside of debugger?
372 if( $this->is_plugin_wp_active( $slug ) ) {
373 $classes[] = 'wp-active';
374 }
375
376 printf(
377 '<li class="%2$s"><input type="checkbox" name="plugins[]" id="%4$s" %3$s value="%4$s" /><label for="%4$s">%1$s</label></li>',
378 $plugin['Name'],
379 implode( ' ', $classes ),
380 $is_active ? 'checked="checked"' : '',
381 $slug
382 );
383
384 } ?>
385 </ul>
386
387 <h4><?php _e( 'Other Plugins', 'gravityformdebug' ); ?></h4>
388 <ul class="gdebug-ct-plugins gdebug-ct-other-plugins">
389
390 <li class="gdebug-select-all">
391 <input type="checkbox" id="gdebug-select-all-other" onclick="jQuery( '.gdebug-ct-other-plugins input' ).prop( 'checked', jQuery( this ).is( ':checked' ) );" />
392 <label for="gdebug-select-all-other"><?php _e( 'Select All', 'gravityformsdebug' ); ?></label>
393 <span class="wp-active-note">
394 <i class="fa fa-asterisk"></i> <?php _e( 'Denotes Orginally Active Plugin', 'gravityformsdebug' ); ?>
395 </span>
396 </li>
397
398 <?php foreach( $plugins as $slug => $plugin ) {
399
400 if( in_array( $plugin['Name'], $this->get_gf_plugins() ) || in_array( $plugin['Name'], $this->_immune_plugins ) )
401 continue;
402
403 $is_active = $this->is_plugin_active( $slug );
404
405 $classes = array();
406 if( $is_active ) {
407 $classes[] = 'active';
408 }
409
410 // is plugin active outside of debugger?
411 if( $this->is_plugin_wp_active( $slug ) ) {
412 $classes[] = 'wp-active';
413 }
414
415 printf(
416 '<li class="%2$s"><input type="checkbox" name="plugins[]" id="%4$s" %3$s value="%4$s" /><label for="%4$s">%1$s</label></li>',
417 $plugin['Name'],
418 implode( ' ', $classes ),
419 $is_active ? 'checked="checked"' : '',
420 $slug
421 );
422
423 } ?>
424
425 </ul>
426
427 </td>
428 </tr>
429
430 <?php endif; ?>
431
432 <tr valign="top" class="gdebug-ct-disable-link">
433 <th><label for=""><?php _e( 'Disable Link', 'gravityformsdebug' ); ?></label></th>
434 <td>
435 <input type="text" value="<?php echo $this->get_disable_url(); ?>" style="width:90%;" onclick="jQuery( this ).select();" />
436 <p class="description"><?php _e( 'To manually disable the Conflict Tester, use the above URL.' ); ?></p>
437 </td>
438 </tr>
439
440 </tbody>
441 </table>
442
443 <?php
444
445 }
446
447 /**
448 * Get the default WordPress theme available.
449 *
450 * @access public
451 * @return string|bool
452 */
453 public function get_default_theme() {
454
455 // Get installed themes.
456 $themes = wp_get_themes();
457
458 // Loop through WordPress default themes.
459 foreach( $this->_default_themes as $default_theme ) {
460
461 // Loop through installed themes.
462 foreach( $themes as $theme ) {
463
464 // If installed theme is a default theme, return it.
465 if ( $theme->template == $default_theme ) {
466 return $theme;
467 }
468
469 }
470
471 }
472
473 return false;
474
475 }
476
477 /**
478 * Get list of official Gravity Forms plugins.
479 *
480 * @access public
481 * @return array
482 */
483 public function get_gf_plugins() {
484
485 // If list of Gravity Forms plugins has already been populated, return it.
486 if ( ! empty( $this->_gf_plugins ) ) {
487 return $this->_gf_plugins;
488 }
489
490 // Get the list of plugins from the Gravity Manager.
491 $plugins_list = wp_remote_get( GRAVITY_MANAGER_URL . '/api.php?op=get_plugins' );
492
493 // If plugins list response is an error, return the Gravity Forms plugins property.
494 if ( is_wp_error( $plugins_list ) ) {
495 return $this->_gf_plugins;
496 }
497
498 // Unserialize the plugins list.
499 $plugins_list = maybe_unserialize( $plugins_list['body'] );
500
501 // Loop through the plugins.
502 foreach ( $plugins_list as $plugin ) {
503
504 // Get the plugin title.
505 $plugin = rgar( $plugin, 'title' );
506
507 // If the plugin title is empty, skip it.
508 if ( rgblank( $plugin ) ) {
509 continue;
510 }
511
512 // If the plugin title does not start with Gravity Forms, add it.
513 if ( strpos( $plugin, 'Gravity Forms' ) !== 0 ) {
514 $plugin = 'Gravity Forms ' . $plugin;
515 }
516
517 // Add plugin to list.
518 $this->_gf_plugins[] = $plugin;
519
520 // If this is the PayPal Add-On, add PayPal Standard to the plugins list.
521 if ( strpos( $plugin, 'PayPal Add-On' ) !== false ) {
522 $this->_gf_plugins[] = 'Gravity Forms PayPal Standard Add-On';
523 }
524
525 }
526
527 return $this->_gf_plugins;
528
529 }
530
531 /**
532 * Check if a specific plugin is active.
533 *
534 * @access public
535 * @param string $slug Plugin slug.
536 * @return bool
537 */
538 public function is_plugin_active( $slug ) {
539
540 $active_plugins = get_user_meta( get_current_user_id(), $this->prefix( 'ct_active_plugins' ), true );
541 if( ! is_array( $active_plugins ) )
542 return false;
543
544 foreach( $active_plugins as $plugin ) {
545 if( $plugin == $slug )
546 return true;
547 }
548
549 return false;
550 }
551
552 /**
553 * @param $slug
554 *
555 * @return bool
556 */
557 public function is_plugin_wp_active( $slug ) {
558
559 if( function_exists( 'gf_mu_debug' ) && is_array( gf_mu_debug()->wp_active_plugins ) ) {
560 $is_active = in_array( $slug, gf_mu_debug()->wp_active_plugins );
561 } else {
562 $is_active = is_plugin_active( $slug );
563 }
564
565 return $is_active;
566 }
567
568 /**
569 *
570 */
571 public function maybe_handle_settings_submission() {
572
573 if( $this->is_settings_submission() ) {
574 $this->handle_settings_submission();
575 }
576
577 }
578
579 /**
580 *
581 */
582 protected function handle_settings_submission() {
583
584 $action = rgpost( 'action' );
585 if( ! $action )
586 return;
587
588 switch( $action ) {
589 case 'enable':
590 $this->enable_conflict_tester();
591 wp_redirect( remove_query_arg( null ) );
592 break;
593 case 'disable':
594 $this->disable_conflict_tester();
595 wp_redirect( remove_query_arg( null ) );
596 break;
597 case 'activate_plugins':
598 $plugins = rgpost( 'plugins' );
599 $this->update_active_plugins( $plugins, self_admin_url( 'admin.php?page=gravityformsdebug' ) );
600 break;
601 }
602
603 }
604
605 /**
606 *
607 */
608 public function enable_conflict_tester() {
609
610 setcookie( 'gravityformsdebug_ct_enabled', true, null, '/' );
611 setcookie( 'gravityformsdebug_ct_user_id', get_current_user_id(), null, '/' );
612 setcookie( 'gravityformsdebug_ct_error_check', true, null, '/' );
613
614 $is_installed = $this->install_mu_plugin();
615
616 }
617
618 /**
619 * @param bool $delete_cookies
620 *
621 * @return bool
622 */
623 public function disable_conflict_tester( $delete_cookies = true ) {
624
625 $is_uninstalled = $this->uninstall_mu_plugin();
626 $is_active_plugins_cleared = delete_user_meta( get_current_user_id(), $this->prefix( 'ct_active_plugins' ) );
627
628 if( $delete_cookies ) {
629
630 unset( $_COOKIE['gravityformsdebug_ct_enabled'] );
631 unset( $_COOKIE['gravityformsdebug_ct_user_id'] );
632
633 setcookie( 'gravityformsdebug_ct_enabled', null, null, '/' );
634 setcookie( 'gravityformsdebug_ct_user_id', null, null, '/' );
635
636 }
637
638 return $is_uninstalled && $is_active_plugins_cleared;
639 }
640
641 /**
642 * @return mixed|null|string
643 */
644 public function is_conflict_tester_enabled() {
645 return rgar( $_COOKIE, 'gravityformsdebug_ct_enabled' );
646 }
647
648 /**
649 * @param $plugins
650 * @param $redirect
651 *
652 * @return bool|int
653 */
654 protected function update_active_plugins( $plugins, $redirect ) {
655
656 if( ! $plugins ) {
657 $plugins = array();
658 }
659
660 // make sure including any of the plugins will not generate a fatal error
661 foreach( $plugins as $plugin ) {
662
663 wp_redirect( add_query_arg( array(
664 '_error_nonce' => wp_create_nonce( 'plugin-activation-error_' . $plugin ),
665 'error' => true,
666 'plugin' => $plugin
667 ), $redirect ) );
668
669 ob_start();
670 wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin );
671 include_once( WP_PLUGIN_DIR . '/' . $plugin );
672 ob_get_clean();
673
674 }
675
676 wp_redirect( admin_url( 'admin.php?page=gravityformsdebug&action=active-plugins-updated' ) );
677
678 return update_user_meta( get_current_user_id(), $this->prefix( 'ct_active_plugins' ), $plugins );
679 }
680
681 /**
682 * @return bool
683 */
684 protected function is_settings_submission() {
685
686 $is_submit = rgpost( $this->prefix( 'conflict_tester_settings' ) ) == true;
687
688 return $is_submit && check_admin_referer( $this->prefix( 'ct_settings_submission' ), $this->prefix( 'ct_settings_submission' ) );
689 }
690
691 /**
692 * @return bool
693 */
694 private function install_mu_plugin() {
695
696 if( $this->mu_plugin_file_exists() )
697 return true;
698
699 if( ! $this->mu_plugins_folder_exists() && ! $this->create_mu_plugins_folder() )
700 return false;
701
702 $source_path = $this->get_base_path() . "/includes/{$this->_mu_plugin_file}";
703 $target_path = $this->get_mu_plugins_dir() . "/{$this->_mu_plugin_file}";
704
705 $result = copy( $source_path, $target_path );
706
707 chmod( $target_path, 0775 );
708
709 return $result;
710 }
711
712 /**
713 * @return bool
714 */
715 private function uninstall_mu_plugin() {
716
717 $target_path = $this->get_mu_plugins_dir() . "/{$this->_mu_plugin_file}";
718 if( ! file_exists( $target_path ) )
719 return true;
720
721 return unlink( $target_path );
722 }
723
724 /**
725 * @param $name
726 *
727 * @return string
728 */
729 final public function prefix( $name ) {
730 return "{$this->_slug}_{$name}";
731 }
732
733 /**
734 * @return bool
735 */
736 public function mu_plugin_file_exists() {
737 return file_exists( $this->get_mu_plugins_dir() . "/{$this->_mu_plugin_file}" );
738 }
739
740 /**
741 * @return bool
742 */
743 public function mu_plugins_folder_exists() {
744 return file_exists( $this->get_mu_plugins_dir() );
745 }
746
747 /**
748 * @return bool
749 */
750 public function create_mu_plugins_folder() {
751 return mkdir( $this->get_mu_plugins_dir(), 0775, true );
752 }
753
754 /**
755 * @return string
756 */
757 public function get_mu_plugins_dir() {
758 return WP_CONTENT_DIR . '/mu-plugins';
759 }
760
761 /**
762 * @param string $title
763 */
764 public function page_header( $title = '' ){
765
766 // register admin styles
767 wp_register_style( 'gform_admin', GFCommon::get_base_url() . '/css/admin.css' );
768 wp_print_styles( array( 'jquery-ui-styles', 'gform_admin', 'wp-pointer' ) );
769
770 // get view details
771 $subviews = $this->get_subviews();
772
773 ?>
774
775 <div class="wrap <?php echo GFCommon::get_browser_class() ?>">
776
777 <?php GFCommon::display_admin_message(); ?>
778
779 <div id="gform_tab_group" class="gform_tab_group vertical_tabs">
780
781 <ul id="gform_tabs" class="gform_tabs">
782 <?php foreach( $subviews as $view ):
783 $query = array( 'subview' => $view['name'] );
784 if( isset( $view['query'] ) )
785 $query = array_merge( $query, $view['query'] );
786 ?>
787 <li <?php echo $this->get_current_subview() == $view['name'] ? 'class="active"' : '' ?>>
788 <a href="<?php echo add_query_arg( $query ); ?>"><?php echo $view['label'] ?></a>
789 </li>
790 <?php endforeach; ?>
791 </ul>
792
793 <div id="gform_tab_container" class="gform_tab_container">
794 <div class="gform_tab_content" id="tab_<?php echo $this->get_current_subview() ?>">
795
796 <?php
797 }
798
799 /**
800 *
801 */
802 public function page_footer() {
803 ?>
804
805 </div> <!-- / gform_tab_content -->
806 </div> <!-- / gform_tab_container -->
807 </div> <!-- / gform_tab_group -->
808
809 <br class="clear" style="clear: both;" />
810
811 </div> <!-- / wrap -->
812
813 <script type="text/javascript">
814 jQuery(document).ready( function( $ ) {
815 $( '.gform_tab_container' ).css( 'minHeight', jQuery( '#gform_tabs' ).height() + 100 );
816 } );
817 </script>
818
819 <?php
820 }
821
822 /**
823 * @return array
824 */
825 public function get_subviews() {
826
827 $subviews = array(
828 '10' => array(
829 'name' => 'conflict_tester',
830 'label' => __( 'Conflict Tester', 'gravityformsdebug' )
831 )
832 );
833
834 ksort( $subviews, SORT_NUMERIC );
835
836 return $subviews;
837 }
838
839 /**
840 * @return string
841 */
842 public function get_current_subview() {
843 return rgempty( 'subview', $_GET ) ? 'conflict_tester' : rgget( 'subview' );
844 }
845
846 /**
847 * @return string
848 */
849 public function get_disable_url() {
850 return add_query_arg( array( 'gf_disable_conflict_tester' => 1 ), home_url() . '/' );
851 }
852
853}
854
855/**
856 * @return GFDebug|null
857 */
858function gravity_forms_debug() {
859 return GFDebug::get_instance();
860}
861
862// Runs the debugging plugin.
863gravity_forms_debug();
864
865
866
867
868
869
870request_id}","add_language_pair_url":"","custom_text_url":"","select_translator_iframe_url":"","translator_contact_iframe_url":"","quote_iframe_url":"","has_translator_selection":false,"project_name_length":128,"suid":"3393562c8687d38db9c447854bd20957","doc_url":"https://wpml.org/translation-service/capita/","notification":false,"tms":false,"has_language_pairs":false,"deadline":true,"oauth":false,"oauth_url":"","popup_message":"","how_to_get_credentials_desc":"The username, password, customer name, and contact name will be provided upon creating a Capita account","how_to_get_credentials_url":"https://wpml.org/translation-service/capita/#connecting-your-site-to-capita","client_create_account_page_url":"https://www.capitatranslationinterpreting.com/contact-us/","partner":false,"custom_fields":[{"label":"Username","name":"username","type":"text"},{"label":"Password","name":"password","type":"text"},{"label":"Customer Name","name":"customer_name","type":"text"},{"label":"Contact Name","name":"contact_name","type":"text"}],"default_service":0,"translation_feedback":true,"feedback_forward_method":"email","rankings":{"quality":0,"quality_ranking":0.0,"speed":2,"speed_ranking":2294.0,"popularity":2,"popularity_ranking":16.08,"primary":2,"primary_ranking":16.08},"specializations":[],"countries":[],"redirect_to_ts?":true},{"id":8,"name":"Gengo","description":"Gengo’s people-powered translation platform helps you translate content into over 36 languages through a selective, global network of translators.","url":"http://gengo.com/","logo_url":"https://d1lsub6zbh43gv.cloudfront.net/production/logos/gengo.png","project_details_url":"https://gengo.com/auth/form/login/","add_language_pair_url":"","custom_text_url":"","select_translator_iframe_url":"","translator_contact_iframe_url":"","quote_iframe_url":"","has_translator_selection":false,"project_name_length":128,"suid":"63f155572eb659a462aac247ee1bbf8d","doc_url":"https://wpml.org/translation-service/gengo/","notification":true,"tms":false,"has_language_pairs":true,"deadline":false,"oauth":false,"oauth_url":"","popup_message":"","how_to_get_credentials_desc":"Your public and secret keys are found on your Gengo Customer Dashboard","how_to_get_credentials_url":"https://wpml.org/translation-service/gengo/#generate-api-keys","client_create_account_page_url":"https://wpml.org/translation-service/gengo/#create-gengo-account","partner":false,"custom_fields":[{"label":"Public key","name":"public_key","type":"text"},{"label":"Private key","name":"private_key","type":"text"}],"default_service":0,"translation_feedback":true,"feedback_forward_method":"email","rankings":{"quality":0,"quality_ranking":0.0,"speed":2,"speed_ranking":2470.0,"popularity":2,"popularity_ranking":15.28,"primary":2,"primary_ranking":15.28},"specializations":[{"name":"Business","key":"business"},{"name":"e-Commerce","key":"e-commerce"},{"name":"Tourism & Travel","key":"tourism_travel"}],"countries":[{"name":"Japan","code":"JP"},{"name":"Philippines","code":"PH"},{"name":"United States","code":"US"}],"redirect_to_ts?":true},{"id":22,"name":"SDL Language Cloud","description":"SDL Language Cloud has been translating content for small to medium-size businesses for more than 25 years. It employs 15,000 in-territory translators which specialize in automotive, banking and e-commerce among other industries.","url":"https://languagecloud.sdl.com/","logo_url":"https://d1lsub6zbh43gv.cloudfront.net/production/logos/sdl-language-cloud.png","project_details_url":"https://languagecloud.sdl.com/en/managed-translation/login","add_language_pair_url":"","custom_text_url":"","select_translator_iframe_url":"","translator_contact_iframe_url":"","quote_iframe_url":"","has_translator_selection":false,"project_name_length":128,"suid":"e050f3d3a0bfccd551c2286233d60837","doc_url":"https://wpml.org/translation-service/sdl-language-cloud/","notification":true,"tms":false,"has_language_pairs":true,"deadline":true,"oauth":false,"oauth_url":"","popup_message":"","how_to_get_credentials_desc":"Your username and password are the same as the credentials you use to login to SDL Language Cloud","how_to_get_credentials_url":"https://wpml.org/translation-service/sdl-language-cloud/#connecting-to-language-cloud","client_create_account_page_url":"https://oos.sdl.com/asp/products/ssl/RegisterUser.aspx","partner":false,"custom_fields":[{"label":"Username","name":"username","type":"text"},{"label":"Password","name":"password","type":"text"}],"default_service":0,"translation_feedback":true,"feedback_forward_method":"manual","rankings":{"quality":0,"quality_ranking":0.0,"speed":4,"speed_ranking":2772.0,"popularity":2,"popularity_ranking":15.2,"primary":2,"primary_ranking":15.2},"specializations":[],"countries":[],"redirect_to_ts?":true},{"id":12,"name":"OneHourTranslation","description":"OneHourTranslation provides translations in more than 75 languages and 2500 languages pairs for medium to large businesses. It specializes in providing business translations in a variety of fields including legal, technical and web applications.","url":"https://www.onehourtranslation.com","logo_url":"https://d1lsub6zbh43gv.cloudfront.net/production/logos/onehourtranslation.png","project_details_url":"https://www.onehourtranslation.com/my-projects/customer/","add_language_pair_url":"","custom_text_url":"","select_translator_iframe_url":"","translator_contact_iframe_url":"","quote_iframe_url":"","has_translator_selection":false,"project_name_length":128,"suid":"8850fd4bfdaae2a2d63e51fb1f2ac3e4","doc_url":"https://wpml.org/translation-service/onehourtranslation/","notification":true,"tms":false,"has_language_pairs":true,"deadline":true,"oauth":false,"oauth_url":"","popup_message":"","how_to_get_credentials_desc":"Your Secret Key and Public Key are located under \"Profile > API Keys\" on your OneHourTranslation Control panel","how_to_get_credentials_url":"https://wpml.org/translation-service/onehourtranslation/#api-secret-public-keys","client_create_account_page_url":"https://wpml.org/translation-service/onehourtranslation/#create-account","partner":false,"custom_fields":[{"label":"Secret Key","name":"secret_key","type":"text"},{"label":"Public Key","name":"public_key","type":"text"}],"default_service":0,"translation_feedback":true,"feedback_forward_method":"email","rankings":{"quality":0,"quality_ranking":0.0,"speed":3,"speed_ranking":2670.0,"popularity":2,"popularity_ranking":14.95,"primary":2,"primary_ranking":14.95},"specializations":[{"name":"Technical","key":"technical"},{"name":"Business","key":"business"},{"name":"e-Commerce","key":"e-commerce"}],"countries":[{"name":"Israel","code":"IL"},{"name":"Romania","code":"RO"},{"name":"Ukraine","code":"UA"},{"name":"United States","code":"US"}],"redirect_to_ts?":true},{"id":39,"name":"Avilínga","description":"Avilínga is a Swiss company which has been translating content for companies in the aviation industry since 2006. In particular, it specializes in technical aviation translations.","url":"http://avilinga.com","logo_url":"https://d1lsub6zbh43gv.cloudfront.net/production/logos/avilinga.png","project_details_url":"","add_language_pair_url":"","custom_text_url":"","select_translator_iframe_url":"","translator_contact_iframe_url":"","quote_iframe_url":"","has_translator_selection":false,"project_name_length":128,"suid":"f38976dca685689ebf19fd516fb4e918","doc_url":"https://wpml.org/translation-service/avilinga/","notification":true,"tms":false,"has_language_pairs":true,"deadline":true,"oauth":false,"oauth_url":"","popup_message":"","how_to_get_credentials_desc":"An Avilinga team member will email you a unique API Token","how_to_get_credentials_url":"https://wpml.org/translation-service/avilinga/#retrieving-api-token","client_create_account_page_url":"https://wpml.org/translation-service/avilinga/#requesting-an-avilinga-account","partner":false,"custom_fields":[{"label":"API token","name":"api_token","type":"text"}],"default_service":0,"translation_feedback":true,"feedback_forward_method":"api","rankings":{"quality":0,"quality_ranking":0.0,"speed":0,"speed_ranking":0.0,"popularity":2,"popularity_ranking":9.08,"primary":2,"primary_ranking":9.08},"specializations":[],"countries":[],"redirect_to_ts?":false},{"id":43,"name":"GPI","description":"GPI is a team of language, technology, project management and business professionals with over 20 years of extensive experience in translation services helping companies communicate and conduct business in more than 100 languages and 15 disciplines.","url":"http://www.globalizationpartners.com/","logo_url":"https://d1lsub6zbh43gv.cloudfront.net/production/logos/gpi.png","project_details_url":"URL from request to GPI","add_language_pair_url":"","custom_text_url":"","select_translator_iframe_url":"","translator_contact_iframe_url":"","quote_iframe_url":"","has_translator_selection":false,"project_name_length":128,"suid":"bbfd2c9ae5d6d34b08719f8fcbde80d6","doc_url":"https://wpml.org/translation-service/gpi/","notification":false,"tms":false,"has_language_pairs":false,"deadline":true,"oauth":false,"oauth_url":"","popup_message":"","how_to_get_credentials_desc":"A GPI team member will email an API Key and API Secret Key","how_to_get_credentials_url":"https://wpml.org/translation-service/gpi/#receiving-api-keys","client_create_account_page_url":"https://wpml.org/translation-service/gpi/#requesting-an-account","partner":false,"custom_fields":[{"label":"API Key","name":"api_key","type":"text"},{"label":"API Secret Key","name":"api_secret_key","type":"text"}],"default_service":0,"translation_feedback":true,"feedback_forward_method":"email","rankings":{"quality":0,"quality_ranking":0.0,"speed":0,"speed_ranking":0.0,"popularity":1,"popularity_ranking":0.35,"primary":1,"primary_ranking":0.35},"specializations":[{"name":"Technical","key":"technical"},{"name":"Marketing & Branding","key":"marketing_branding"},{"name":"Tourism & Travel","key":"tourism_travel"}],"countries":[],"redirect_to_ts?":true}]
871}