GravityView  2.17
The best, easiest way to display Gravity Forms entries on your website.
HelpScout.php
Go to the documentation of this file.
1 <?php
2 /**
3  * @license GPL-2.0-or-later
4  *
5  * Modified by gravityview on 13-January-2023 using Strauss.
6  * @see https://github.com/BrianHenryIE/strauss
7  */
8 
10 
16 
17 class HelpScout {
18  const HS_BEACON_KEY = 'e899c3af-bfb9-479a-9579-38e758664fb7';
19 
20  const HASH_KEY = 't4MTtLRuIH74gBuQ/2OVpj0NscYAjdg9nY1rw67PiT8=';
21 
22  /**
23  * @since 1.0.0
24  *
25  * @var TrustedLogin Class instance.
26  */
27  private static $_instance;
28 
29  private function __construct() {
30  add_filter( 'gk/foundation/inline-scripts', [ $this, 'enqueue_beacon_script' ] );
31  }
32 
33  /**
34  * Returns class instance.
35  *
36  * @since 1.0.0
37  *
38  * @return TrustedLogin
39  */
40  public static function get_instance() {
41  if ( ! self::$_instance ) {
42  self::$_instance = new self();
43  }
44 
45  return self::$_instance;
46  }
47 
48  /**
49  * Outputs inline JS code that initializes the HS beacon.
50  *
51  * @since 1.0.0
52  *
53  * @param array $scripts
54  *
55  * @return array
56  */
57  public function enqueue_beacon_script( $scripts ) {
58  if ( ! $this->should_display_beacon() ) {
59  return $scripts;
60  }
61 
62  $beacon_configuration = json_encode( $this->get_beacon_configuration() );
63 
64  $js = <<<JS
65 !function(e,t,n){function a(){var e=t.getElementsByTagName('script')[0],n=t.createElement('script');n.type='text/javascript',n.async=!0,n.src='https://beacon-v2.helpscout.net',e.parentNode.insertBefore(n,e)}if(e.Beacon=n=function(t,n,a){e.Beacon.readyQueue.push({method:t,options:n,data:a})},n.readyQueue=[],'complete'===t.readyState)return a();e.attachEvent?e.attachEvent('onload',a):e.addEventListener('load',a,!1)}(window,document,window.Beacon||function(){});
66 var beaconConfig = {$beacon_configuration}; for (var param in beaconConfig) { window.Beacon( param, beaconConfig[param]); }
67 JS;
68 
69  $scripts[] = [
70  'script' => $js,
71  ];
72 
73  return $scripts;
74  }
75 
76  /**
77  * Determines if the HS beacon should be displayed.
78  *
79  * @since 1.0.0
80  *
81  * @return bool
82  */
83  public function should_display_beacon() {
84  $is_enabled = SettingsFramework::get_instance()->get_plugin_setting( FoundationCore::ID, 'support_port' );
85 
86  if ( ! $is_enabled ) {
87  return false;
88  }
89 
90  /**
91  * @TODO: Possibly implement additional checks as it's done in GravityView:
92  *
93  * If the user doesn't have the `gravityview_support_port` capability, returns false; then
94  * If global setting is "hide", returns false; then
95  * If user preference is not set, return global setting; then
96  * If user preference is set, return that setting.
97  */
98 
99  $page = Arr::get( $_REQUEST, 'page' );
100  $post_type = Arr::get( $_REQUEST, 'post_type' );
101 
102  $display_beacon = false;
103 
104  if ( in_array( $page, [ SettingsFramework::ID, LicensesFramework::ID ], true ) ) {
105  $display_beacon = true;
106  }
107 
108  /**
109  * @filter `gk/foundation/integrations/helpscout/display` Toggles whether HS beacon should be displayed. Return "true" to short-circuit all other checks.
110  *
111  * @since 1.0.0
112  *
113  * @param bool $display_beacon Whether to display the beacon.
114  * @param string|null $page Current page ($_REQUEST['page']).
115  * @param string|null $post_type Current post type ($_REQUEST['post_type']).
116  */
117  return apply_filters( 'gk/foundation/integrations/helpscout/display', $display_beacon, $page, $post_type );
118  }
119 
120  /**
121  * Returns HS beacon configuration options.
122  *
123  * @since 1.0.0
124  *
125  * @return array
126  */
127  public function get_beacon_configuration() {
128  $foundation_settings = SettingsFramework::get_instance()->get_plugin_settings( FoundationCore::ID );
129 
130  $current_user = wp_get_current_user();
131 
132  $beacon_configuration = [
133  'init' => self::HS_BEACON_KEY,
134  'config' => [
135  'color' => '#4d9bbe',
136  'poweredBy' => false,
137  'docsEnabled' => true,
138  'topArticles' => true,
139  'iconImage' => 'question',
140  'zIndex' => 10000 + 10, // Above #adminmenuwrap, which is 9990 and modal content, which is 10000 + 1.
141  'labels' => $this->get_beacon_label_translations(),
142  'messaging' => [
143  'chatEnabled' => ( ! is_multisite() && current_user_can( 'manage_options' ) ) ||
144  ( is_multisite() && current_user_can( 'manage_network_options' ) && CoreHelpers::is_network_admin() ),
145  ],
146  ],
147  // Each session data parameter is limited to 10k characters.
148  'session-data' => [
149  'WP Version' => mb_substr( get_bloginfo( 'version', 'display' ), 0, 10000 ),
150  'PHP Version' => mb_substr( PHP_VERSION . ' on ' . esc_html( Arr::get( $_SERVER, 'SERVER_SOFTWARE' ) ), 0, 10000 ),
151  ],
152  'prefill' => [
153  'name' => mb_substr( $current_user->display_name, 0, 80 ),
154  'email' => mb_substr( $current_user->user_email, 0, 80 ),
155  ],
156  'identify' => [
157  'email' => mb_substr( $current_user->user_email, 0, 80 ),
158  'name' => mb_substr( $current_user->display_name, 0, 80 ),
159  'signature' => hash_hmac( 'sha256', mb_substr( $current_user->user_email, 0, 80 ), self::HASH_KEY ),
160  'affiliate_id' => mb_substr( Arr::get( $foundation_settings, 'affiliate_id', '' ), 0, 255 ),
161  'is_super_admin' => is_super_admin(),
162  'alt_emails' => mb_substr( sprintf( 'Admin: %s / GV Support: %s', get_bloginfo( 'admin_email' ), Arr::get( $foundation_settings, 'support_email' ) ), 0, 255 ),
163  'wordpress_version' => mb_substr( get_bloginfo( 'version', 'display' ), 0, 255 ),
164  'php_version' => mb_substr( PHP_VERSION . ' on ' . esc_html( $_SERVER['SERVER_SOFTWARE'] ), 0, 255 ),
165  'no_conflict_mode' => Arr::get( $foundation_settings, 'no_conflict_mode' ) ? 'Disabled' : 'Enabled',
166  'gravityview_version' => mb_substr( class_exists( '\GV\Plugin' ) ? \GV\Plugin::$version : 'Not Installed', 0, 255 ),
167  'gravity_forms_version' => mb_substr( class_exists( '\GFForms' ) ? \GFForms::$version : 'Not Installed', 0, 255 ),
168  'locale' => get_user_locale(),
169  'is_support_contact' => ( $current_user->user_email === Arr::get( $foundation_settings, 'support_email' ) ),
170  ],
171  'suggest' => [],
172  ];
173 
174  /**
175  * @filter `gk/foundation/integrations/helpscout/configuration` Modified HS beacon configuration.
176  *
177  * @since 1.0.0
178  *
179  * @param array $beacon_configuration Beacon configuration.
180  */
181  return apply_filters( 'gk/foundation/integrations/helpscout/configuration', $beacon_configuration );
182  }
183 
184  /**
185  * Returns translated labels. These combines default HS translations with custom GravityView translations.
186  *
187  * @since 1.0.0
188  *
189  * @see https://github.com/gravityview/GravityView/blob/3a999a0ce8d96cd63386c575fd3199730ded6491/includes/admin/class-gravityview-support-port.php#L137-L156
190  * @see https://developer.helpscout.com/beacon-2/web/javascript-api/#translate-options
191  *
192  * @return array
193  */
194  public function get_beacon_label_translations() {
195  $translations = [
196  // Answers
197  'suggestedForYou' => __( 'Instant Answers', 'gk-gravityview' ),
198  'getInTouch' => __( 'Get in touch', 'gk-gravityview' ),
199  'searchLabel' => __( 'Search GravityKit Docs', 'gk-gravityview' ),
200  'tryAgain' => __( 'Try again', 'gk-gravityview' ),
201  'defaultMessageErrorText' => __( 'There was a problem sending your message. Please try again in a moment.', 'gk-gravityview' ),
202  'beaconButtonClose' => __( 'Close', 'gk-gravityview' ),
203  'beaconButtonChatMinimize' => __( 'Minimize chat', 'gk-gravityview' ),
204  'beaconButtonChatOpen' => __( 'Open chat', 'gk-gravityview' ),
205  // Ask
206  'answer' => __( 'Answer', 'gk-gravityview' ),
207  'ask' => __( 'Ask', 'gk-gravityview' ),
208  'messageButtonLabel' => __( 'Email', 'gk-gravityview' ),
209  'noTimeToWaitAround' => __( 'No time to wait around? We usually respond within a few hours', 'gk-gravityview' ),
210  'chatButtonLabel' => __( 'Chat', 'gk-gravityview' ),
211  'chatButtonDescription' => __( 'We\'re online right now, talk with our team in real-time', 'gk-gravityview' ),
212  'wereHereToHelp' => __( 'Start a conversation', 'gk-gravityview' ),
213  'whatMethodWorks' => __( 'What channel do you prefer?', 'gk-gravityview' ),
214  'previousMessages ' => __( 'Previous Conversations', 'gk-gravityview' ),
215  // Search Results
216  'cantFindAnswer' => __( 'Can\'t find the answer?', 'gk-gravityview' ),
217  'relatedArticles' => __( 'Related Articles', 'gk-gravityview' ),
218  'nothingFound' => __( 'Hmm…', 'gk-gravityview' ),
219  'docsSearchEmptyText' => __( 'We couldn\'t find any articles that match your search.', 'gk-gravityview' ),
220  'tryBroaderTerm' => __( 'Try a broader term, or', 'gk-gravityview' ),
221  'docsArticleErrorText' => __( 'There was a problem loading this article. Please double-check your internet connection and try again.', 'gk-gravityview' ),
222  'docsSearchErrorText' => __( 'Your search timed out. Please double-check your internet connection and try again.', 'gk-gravityview' ),
223  'escalationQuestionFeedback' => __( 'Did this answer your question?', 'gk-gravityview' ),
224  'escalationQuestionFeedbackNo' => __( 'No', 'gk-gravityview' ),
225  'escalationQuestionFeedbackYes' => __( 'Yes', 'gk-gravityview' ),
226  'escalationSearchText' => __( 'Browse our help docs for an answer to your question', 'gk-gravityview' ),
227  'escalationSearchTitle' => __( 'Keep searching', 'gk-gravityview' ),
228  'escalationTalkText' => __( 'Talk with a friendly member of our support team', 'gk-gravityview' ),
229  'escalationTalkTitle' => __( 'Talk to us', 'gk-gravityview' ),
230  'escalationThanksFeedback' => __( 'Thanks for the feedback', 'gk-gravityview' ),
231  'escalationWhatNext' => __( 'What next?', 'gk-gravityview' ),
232  // Send A Message
233  'sendAMessage' => __( 'Send a message', 'gk-gravityview' ),
234  'firstAFewQuestions' => __( 'Let\'s begin with a few questions', 'gk-gravityview' ),
235  'howCanWeHelp' => __( 'How can we help?', 'gk-gravityview' ),
236  'responseTime' => __( 'We usually respond in a few hours', 'gk-gravityview' ),
237  'history' => __( 'History', 'gk-gravityview' ),
238  'uploadAnImage' => __( 'Upload an image', 'gk-gravityview' ),
239  'attachAFile' => __( 'Attach a screenshot or file', 'gk-gravityview' ),
240  'continueEditing' => __( 'Continue writing…', 'gk-gravityview' ),
241  'lastUpdated' => __( 'Last updated', 'gk-gravityview' ),
242  'you' => __( 'You', 'gk-gravityview' ),
243  'nameLabel' => __( 'Your Name', 'gk-gravityview' ),
244  'subjectLabel' => __( 'Subject', 'gk-gravityview' ),
245  'emailLabel' => __( 'Email address', 'gk-gravityview' ),
246  'messageLabel' => __( 'How can we help?', 'gk-gravityview' ),
247  'messageSubmitLabel' => __( 'Send a message', 'gk-gravityview' ),
248  'next' => __( 'Next', 'gk-gravityview' ),
249  'weAreOnIt' => __( 'Message sent!', 'gk-gravityview' ),
250  'messageConfirmationText' => __( 'You\'ll receive an email reply within a few hours.', 'gk-gravityview' ),
251  'viewAndUpdateMessage' => __( 'You can view and update your message in', 'gk-gravityview' ),
252  'mayNotBeEmpty' => __( 'May not be empty', 'gk-gravityview' ),
253  'customFieldsValidationLabel' => __( 'Please complete all fields', 'gk-gravityview' ),
254  'emailValidationLabel' => __( 'Please enter a valid email address', 'gk-gravityview' ),
255  'attachmentErrorText' => __( 'There was a problem uploading your attachment. Please try again in a moment.', 'gk-gravityview' ),
256  'attachmentSizeErrorText' => strtr(
257  _x( 'The maximum file size is [size]', 'Placeholders inside [] are not to be translated.', 'gk-gravityview' ),
258  [ '[size]' => size_format( 10485760 ) ] // 10MB in bytes.
259  ),
260  //Previous messages
261  'addReply' => __( 'Add a reply', 'gk-gravityview' ),
262  'addYourMessageHere' => __( 'Add your message here…', 'gk-gravityview' ),
263  'sendMessage' => __( 'Send message', 'gk-gravityview' ),
264  'received' => __( 'Received', 'gk-gravityview' ),
265  'waitingForAnAnswer' => __( 'Waiting for an answer', 'gk-gravityview' ),
266  'previousMessageErrorText' => __( 'There was a problem retrieving your previous messages. Please double-check your Internet connection and try again.', 'gk-gravityview' ),
267  'justNow' => __( 'Just Now', 'gk-gravityview' ),
268  // Chat
269  'chatHeadingTitle' => __( 'Chat with our team', 'gk-gravityview' ),
270  'chatHeadingSublabel' => __( 'We\'ll be with you soon', 'gk-gravityview' ),
271  'chatEndCalloutHeading' => __( 'All done!', 'gk-gravityview' ),
272  'chatEndCalloutMessage' => __( 'A copy of this conversation will land in your inbox shortly.', 'gk-gravityview' ),
273  'chatEndCalloutLink' => __( 'Return home', 'gk-gravityview' ),
274  'chatEndUnassignedCalloutHeading' => __( 'Sorry about that', 'gk-gravityview' ),
275  'chatEndUnassignedCalloutMessage' => __( 'It looks like nobody made it to your chat. We\'ll send you an email response as soon as possible.', 'gk-gravityview' ),
276  'chatEndWaitingCustomerHeading' => __( 'Sorry about that', 'gk-gravityview' ),
277  'chatEndWaitingCustomerMessage' => __( 'Your question has been added to our email queue and we\'ll get back to you shortly.', 'gk-gravityview' ),
278  'ending' => __( 'Ending…', 'gk-gravityview' ),
279  'endChat' => __( 'End chat', 'gk-gravityview' ),
280  'chatEnded' => strtr(
281  _x( '[name] ended the chat', 'Placeholders inside [] are not to be translated.', 'gk-gravityview' ),
282  [ '[name]' => '' ] // HS has a blank space before the translation.
283  ),
284  'chatConnected' => strtr(
285  _x( 'Connected to [name]', 'Placeholders inside [] are not to be translated.', 'gk-gravityview' ),
286  [ '[name]' => '' ] // HS has a blank space after the translation.
287  ),
288  'chatbotName' => __( 'Help Bot', 'gk-gravityview' ),
289  'chatbotGreet' => __( 'Hi there! You can begin by asking your question below. Someone will be with you shortly.', 'gk-gravityview' ),
290  'chatbotPromptEmail' => __( 'Got it. Real quick, what\'s your email address? We\'ll use it for any follow-up messages.', 'gk-gravityview' ),
291  'chatbotConfirmationMessage' => __( 'Thanks! Someone from our team will jump into the chat soon.', 'gk-gravityview' ),
292  'chatbotGenericErrorMessage' => __( 'Something went wrong sending your message, please try again in a few minutes.', 'gk-gravityview' ),
293  'chatbotInactivityPrompt' => __( 'Since the chat has gone idle, I\'ll end this chat in a few minutes.', 'gk-gravityview' ),
294  'chatbotInvalidEmailMessage' => __( 'Looks like you\'ve entered an invalid email address. Want to try again?', 'gk-gravityview' ),
295  'chatbotAgentDisconnectedMessage' => strtr(
296  _x( '[name] has disconnected from the chat. It\'s possible they lost their internet connection, so I\'m looking for someone else to take over. Sorry for the delay!', 'Placeholders inside [] are not to be translated.', 'gk-gravityview' ),
297  [ '[name]' => '' ] // HS has a blank space before the translation.
298  ),
299  'chatAvailabilityChangeMessage' => __( 'Our team\'s availability has changed and there\'s no longer anyone available to chat. Send us a message instead and we\'ll get back to you.', 'gk-gravityview' ),
300  // Transcript Email
301  'emailHeading' => strtr(
302  _x( 'Today\'s chat with [name]', 'Placeholders inside [] are not to be translated.', 'gk-gravityview' ),
303  [ '[name]' => '' ] // HS has a blank space after the translation.
304  ),
305  'emailGreeting' => strtr(
306  _x( 'Hey [name]', 'Placeholders inside [] are not to be translated.', 'gk-gravityview' ),
307  [ '[name]' => '' ] // HS has a blank space after the translation.
308  ),
309  'emailCopyOfDiscussion' => __( 'Here\'s a copy of your discussion', 'gk-gravityview' ),
310  'emailContinueConversation' => __( 'If you\'ve got any other questions, feel free to hit reply and continue the conversation.', 'gk-gravityview' ),
311  'emailJoinedLineItem' => strtr( _x( '[name] joined the chat', 'Placeholders inside [] are not to be translated.', 'gk-gravityview' ),
312  [ '[name]' => '' ] // HS has a blank space before the translation.
313  ),
314  'emailEndedLineItem' => strtr(
315  _x( '[name] ended the chat', 'Placeholders inside [] are not to be translated.', 'gk-gravityview' ),
316  [ '[name]' => '' ] // HS has a blank space before the translation.
317  ),
318  'emailYou' => __( 'You', 'gk-gravityview' ),
319  ];
320 
321  foreach ( $translations as &$translation ) {
322  $translation = mb_substr( $translation, 0, 160 ); // Maximum characters for a translation value.
323  }
324 
325  return $translations;
326  }
327 }
static get( $array, $key, $default=null)
{}
Definition: Arr.php:99
enqueue_beacon_script( $scripts)
Outputs inline JS code that initializes the HS beacon.
Definition: HelpScout.php:57
get_beacon_configuration()
Returns HS beacon configuration options.
Definition: HelpScout.php:127
get_beacon_label_translations()
Returns translated labels.
Definition: HelpScout.php:194
should_display_beacon()
Determines if the HS beacon should be displayed.
Definition: HelpScout.php:83
static get_instance()
Returns class instance.
Definition: HelpScout.php:40