Google Reviews Widget - Version 2.0

Version Description

  • Plugin keeps the widgets and shortcodes
  • Reviews feed builder
  • Separate menu in wp-admin
  • Fully architecture redesign
  • Bug fixes
Download this release

Release Info

Developer widgetpack
Plugin Icon 128x128 Google Reviews Widget
Version 2.0
Comparing to
See all releases

Code changes from version 1.9.9 to 2.0

Files changed (73) hide show
  1. api/json.php +0 -378
  2. api/urlopen.php +0 -248
  3. assets/css/admin.css +376 -0
  4. assets/css/feedbuilder.css +219 -0
  5. {static → assets}/css/google-review.css +0 -0
  6. {static → assets}/css/rplg-setting.css +16 -20
  7. {static → assets}/css/rplg-wp.css +0 -0
  8. {static → assets}/img/button-down-black.svg +0 -0
  9. {static → assets}/img/google.png +0 -0
  10. {static → assets}/img/google_key_1.png +0 -0
  11. {static → assets}/img/google_key_2.png +0 -0
  12. {static → assets}/img/google_key_2_1.png +0 -0
  13. {static → assets}/img/google_key_3.png +0 -0
  14. {static → assets}/img/google_key_4.png +0 -0
  15. {static → assets}/img/google_key_4_1.png +0 -0
  16. {static → assets}/img/google_key_5.png +0 -0
  17. {static → assets}/img/google_key_6.png +0 -0
  18. {static → assets}/img/google_key_7.png +0 -0
  19. {static → assets}/img/google_key_8.png +0 -0
  20. {static → assets}/img/google_placeid_1.png +0 -0
  21. {static → assets}/img/google_placeid_2.png +0 -0
  22. {static → assets}/img/google_placeid_3.png +0 -0
  23. {static → assets}/img/google_rating_logo_36.png +0 -0
  24. assets/img/logo.png +0 -0
  25. assets/img/menu_icon.png +0 -0
  26. {static → assets}/img/powered_by_google_on_non_white.png +0 -0
  27. {static → assets}/img/powered_by_google_on_white.png +0 -0
  28. assets/js/admin.js +10 -0
  29. {static → assets}/js/blazy.min.js +0 -0
  30. assets/js/feedbuilder.js +706 -0
  31. {static → assets}/js/grw-finder.js +0 -0
  32. {static → assets}/js/rplg.js +0 -0
  33. {static → assets}/js/wpac-time.js +0 -0
  34. {static → assets}/js/wpac.js +0 -0
  35. autoloader.php +34 -0
  36. grw-finder.php +0 -69
  37. grw-options.php +0 -140
  38. grw-reviews-helper.php +0 -149
  39. grw-reviews.php +0 -127
  40. grw-setting.php +0 -401
  41. grw-widget.php +0 -200
  42. grw.php +20 -675
  43. helper/debug.php +0 -51
  44. includes/admin/class-admin-feed-columns.php +90 -0
  45. includes/admin/class-admin-menu.php +91 -0
  46. includes/admin/class-admin-notice.php +73 -0
  47. includes/admin/class-admin-page.php +31 -0
  48. includes/admin/class-admin-rev.php +69 -0
  49. includes/admin/class-admin-tophead.php +47 -0
  50. includes/class-activator.php +241 -0
  51. includes/class-assets.php +133 -0
  52. includes/class-builder-page.php +128 -0
  53. includes/class-deactivator.php +11 -0
  54. includes/class-debug-info.php +99 -0
  55. includes/class-feed-deserializer.php +46 -0
  56. includes/class-feed-old.php +55 -0
  57. includes/class-feed-page.php +26 -0
  58. includes/class-feed-serializer.php +36 -0
  59. includes/class-feed-shortcode.php +47 -0
  60. includes/class-feed-widget.php +133 -0
  61. includes/class-plugin-settings.php +163 -0
  62. includes/class-plugin-support.php +101 -0
  63. includes/class-plugin.php +124 -0
  64. includes/class-post-types.php +70 -0
  65. includes/class-settings-save.php +111 -0
  66. includes/class-view.php +321 -0
  67. includes/core/class-connect-google.php +239 -0
  68. includes/core/class-core.php +316 -0
  69. includes/core/class-database.php +63 -0
  70. includes/index.php +1 -0
  71. grw-setting-fig.php → includes/page-setting-fig.php +15 -15
  72. grw-setting-support.php → includes/page-setting-support.php +1 -1
  73. readme.txt +9 -2
api/json.php DELETED
@@ -1,378 +0,0 @@
1
- <?php
2
- /*
3
- ***************************************************************************
4
- * Copyright (C) 2007 by Cesar D. Rodas *
5
- * crodas@phpy.org *
6
- * *
7
- * Permission is hereby granted, free of charge, to any person obtaining *
8
- * a copy of this software and associated documentation files (the *
9
- * "Software"), to deal in the Software without restriction, including *
10
- * without limitation the rights to use, copy, modify, merge, publish, *
11
- * distribute, sublicense, and/or sell copies of the Software, and to *
12
- * permit persons to whom the Software is furnished to do so, subject to *
13
- * the following conditions: *
14
- * *
15
- * The above copyright notice and this permission notice shall be *
16
- * included in all copies or substantial portions of the Software. *
17
- * *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
19
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
20
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
21
- * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
22
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
23
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
24
- * OTHER DEALINGS IN THE SOFTWARE. *
25
- ***************************************************************************
26
- */
27
-
28
- /**
29
- * Serialize and Unserialize PHP Objects and array
30
- * into JSON notation.
31
- *
32
- * @category Javascript
33
- * @package JSON
34
- * @author Cesar D. Rodas <crodas@phpy.org>
35
- * @copyright 2007 Cesar D. Rodas
36
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
37
- * @version 1.0
38
- * @link http://cesars.users.phpclasses.org/json
39
- */
40
-
41
- define('IN_NOWHERE',0);
42
- define('IN_STRING',1);
43
- define('IN_OBJECT',2);
44
- define('IN_ATOMIC',3);
45
- define('IN_ASSIGN',4);
46
- define('IN_ENDSTMT',5);
47
- define('IN_ARRAY',6);
48
-
49
- /**
50
- * JSON
51
- *
52
- * This class serilize an PHP OBJECT or an ARRAY into JSON
53
- * notation. Also convert a JSON text into a PHP OBJECT or
54
- * array.
55
- *
56
- * @category Javascript
57
- * @package JSON
58
- * @author Cesar D. Rodas <crodas@phpy.org>
59
- * @copyright 2007 Cesar D. Rodas
60
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
61
- * @version 1.0
62
- * @link http://cesars.users.phpclasses.org/json
63
- */
64
- class JSON
65
- {
66
- /**
67
- * Was parsed with an error?
68
- *
69
- * var bool
70
- * @access private
71
- */
72
- var $error;
73
-
74
- function Json() {
75
- $this->error = false;
76
- }
77
-
78
- /**
79
- * Serialize
80
- *
81
- * Serialize a PHP OBJECT or an ARRAY into
82
- * JSON notation.
83
- *
84
- * param mixed $obj Object or array to serialize
85
- * return string JSON.
86
- */
87
- function serialize($obj) {
88
- if ( is_object($obj) ) {
89
- $e = get_object_vars($obj);
90
- /* bug reported by Ben Rowe */
91
- /* Adding default empty array if the */
92
- /* object doesn't have any property */
93
- $properties = array();
94
- foreach ($e as $k => $v) {
95
- $properties[] = $this->_serialize( $k,$v );
96
- }
97
- return "{".implode(",",$properties)."}";
98
- } else if ( is_array($obj) ) {
99
- return $this->_serialize('',$obj);
100
- }
101
- }
102
-
103
- /**
104
- * UnSerialize
105
- *
106
- * Transform an JSON text into a PHP object
107
- * and return it.
108
- * @access public
109
- * @param string $text JSON text
110
- * @return mixed PHP Object, array or false.
111
- */
112
- function unserialize( $text ) {
113
- $this->error = false;
114
-
115
- return !$this->error ? $this->_unserialize($text) : false;
116
- }
117
-
118
- /**
119
- * UnSerialize
120
- *
121
- * Transform an JSON text into a PHP object
122
- * and return it.
123
- * @access private
124
- * @param string $text JSON text
125
- * @return mixed PHP Object, array or false.
126
- */
127
- function _unserialize($text) {
128
- $ret = new stdClass;
129
-
130
- while ( $f = $this->getNextToken($text,$i,$type) ) {
131
- switch ( $type ) {
132
- case IN_ARRAY:
133
- $tmp = $this->_unserializeArray($text);
134
- $ret = $tmp[0];
135
- break;
136
- case IN_OBJECT:
137
- $g=0;
138
- do {
139
- $varName = $this->getNextToken($f,$g,$xType);
140
- if ( $xType != IN_STRING ) {
141
- return false; /* error parsing */
142
- }
143
- $this->getNextToken($f,$g,$xType);
144
- if ( $xType != IN_ASSIGN) return false;
145
- $value = $this->getNextToken($f,$g,$xType);
146
-
147
- if ( $xType == IN_OBJECT) {
148
- $ret->$varName = $this->unserialize( "{".$value."}" );
149
- $g--;
150
- } else if ($xType == IN_ARRAY) {
151
- $ret->$varName = $this->_unserializeArray( $value);
152
- $g--;
153
- } else
154
- $ret->$varName = $value;
155
-
156
- $this->getNextToken($f,$g,$xType);
157
- } while ( $xType == IN_ENDSTMT);
158
- break;
159
- default:
160
- $this->error = true;
161
- break 2;
162
- }
163
- }
164
- return $ret;
165
- }
166
-
167
- /**
168
- * JSON Array Parser
169
- *
170
- * This method transform an json-array into a PHP
171
- * array
172
- * @access private
173
- * @param string $text String to parse
174
- * @return Array PHP Array
175
- */
176
- function _unserializeArray($text) {
177
- $r = array();
178
- do {
179
- $f = $this->getNextToken($text,$i,$type);
180
- switch ( $type ) {
181
- case IN_STRING:
182
- case IN_ATOMIC:
183
- $r[] = $f;
184
- break;
185
- case IN_OBJECT:
186
- $r[] = $this->unserialize("{".$f."}");
187
- $i--;
188
- break;
189
- case IN_ARRAY:
190
- $r[] = $this->_unserializeArray($f);
191
- $i--;
192
- break;
193
-
194
- }
195
- $this->getNextToken($text,$i,$type);
196
- } while ( $type == IN_ENDSTMT);
197
-
198
- return $r;
199
- }
200
-
201
- /**
202
- * Tokenizer
203
- *
204
- * Return to the Parser the next valid token and the type
205
- * of the token. If the tokenizer fails it returns false.
206
- *
207
- * @access private
208
- * @param string $e Text to extract token
209
- * @param integer $i Start position to search next token
210
- * @param integer $state Variable to get the token type
211
- * @return string|bool Token in string or false on error.
212
- */
213
- function getNextToken($e, &$i, &$state) {
214
- $state = IN_NOWHERE;
215
- $end = -1;
216
- $start = -1;
217
- while ( $i < strlen($e) && $end == -1 ) {
218
- switch( $e[$i] ) {
219
- /* objects */
220
- case "{":
221
- case "[":
222
- $_tag = $e[$i];
223
- $_endtag = $_tag == "{" ? "}" : "]";
224
- if ( $state == IN_NOWHERE ) {
225
- $start = $i+1;
226
- switch ($state) {
227
- case IN_NOWHERE:
228
- $aux = 1; /* for loop objects */
229
- $state = $_tag == "{" ? IN_OBJECT : IN_ARRAY;
230
- break;
231
- default:
232
- break 2; /* exit from switch and while */
233
- }
234
- while ( ++$i && $i < strlen($e) && $aux != 0 ) {
235
- switch( $e[$i] ) {
236
- case $_tag:
237
- $aux++;
238
- break;
239
- case $_endtag:
240
- $aux--;
241
- break;
242
- }
243
- }
244
- $end = $i-1;
245
- }
246
- break;
247
-
248
- case '"':
249
- case "'":
250
- $state = IN_STRING;
251
- $buf = "";
252
- while ( ++$i && $i < strlen($e) && $e[$i] != '"' ) {
253
- if ( $e[$i] == "\\")
254
- $i++;
255
- $buf .= $e[$i];
256
- }
257
- $i++;
258
- return $buf;
259
- break;
260
- case ":":
261
- $state = IN_ASSIGN;
262
- $end = 1;
263
- break;
264
- case "n":
265
- if ( substr($e,$i,4) == "null" ) {
266
- $i=$i+4;
267
- $state = IN_ATOMIC;
268
- return NULL;
269
- }
270
- else break 2; /* exit from switch and while */
271
- case "t":
272
- if ( substr($e,$i,4) == "true") {
273
- $state = IN_ATOMIC;
274
- $i=$i+4;
275
- return true;
276
- }
277
- else break 2; /* exit from switch and while */
278
- break;
279
- case "f":
280
- if ( substr($e,$i,5) == "false") {
281
- $state = IN_ATOMIC;
282
- $i=$i+5;
283
- return false;
284
- }
285
- else break 2; /* exit from switch and while */
286
- break;
287
- case ",":
288
- $state = IN_ENDSTMT;
289
- $end = 1;
290
- break;
291
- case " ":
292
- case "\t":
293
- case "\r":
294
- case "\n":
295
- break;
296
- case "+":
297
- case "-":
298
- case 0:
299
- case 1:
300
- case 2:
301
- case 3:
302
- case 4:
303
- case 5:
304
- case 6:
305
- case 7:
306
- case 8:
307
- case 9:
308
- case '.':
309
- $state = IN_ATOMIC;
310
- $start = (int)$i;
311
- if ( $e[$i] == "-" || $e[$i] == "+")
312
- $i++;
313
- for ( ; $i < strlen($e) && (is_numeric($e[$i]) || $e[$i] == "." || strtolower($e[$i]) == "e") ;$i++){
314
- $n = $i+1 < strlen($e) ? $e[$i+1] : "";
315
- $a = strtolower($e[$i]);
316
- if ( $a == "e" && ($n == "+" || $n == "-"))
317
- $i++;
318
- else if ( $a == "e")
319
- $this->error=true;
320
- }
321
-
322
- $end = $i;
323
- break 2; /* break while too */
324
- default:
325
- $this->error = true;
326
-
327
- }
328
- $i++;
329
- }
330
-
331
- return $start == -1 || $end == -1 ? false : substr($e, $start, $end - $start);
332
- }
333
-
334
- /**
335
- * Internal Serializer
336
- *
337
- * @param string $key Variable name
338
- * @param mixed $value Value of the variable
339
- * @access private
340
- * @return string Serialized variable
341
- */
342
- function _serialize ( $key = '', &$value ) {
343
- $r = '';
344
- if ( $key != '')$r .= "\"${key}\" : ";
345
- if ( is_numeric($value) ) {
346
- $r .= ''.$value.'';
347
- } else if ( is_string($value) ) {
348
- $r .= '"'.$this->toString($value).'"';
349
- } else if ( is_object($value) ) {
350
- $r .= $this->serialize($value);
351
- } else if ( is_null($value) ) {
352
- $r .= "null";
353
- } else if ( is_bool($value) ) {
354
- $r .= $value ? "true":"false";
355
- } else if ( is_array($value) ) {
356
- foreach($value as $k => $v)
357
- $f[] = $this->_serialize('',$v);
358
- $r .= "[".implode(",",$f)."]";
359
- unset($f);
360
- }
361
- return $r;
362
- }
363
-
364
- /**
365
- * Convert String variables
366
- *
367
- * @param string $e Variable with an string value
368
- * @access private
369
- * @return string Serialized variable
370
- */
371
- function toString($e) {
372
- $rep = array("\\","\r","\n","\t","'",'"');
373
- $val = array("\\\\",'\r','\n','\t','\'','\"');
374
- $e = str_replace($rep, $val, $e);
375
- return $e;
376
- }
377
- }
378
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/urlopen.php DELETED
@@ -1,248 +0,0 @@
1
- <?php
2
-
3
- if (!function_exists('rplg_urlopen')) {
4
-
5
- define('RPLG_USER_AGENT', 'RPLG-WPPlugin/1.0');
6
- define('RPLG_SOCKET_TIMEOUT', 10);
7
-
8
- if (!extension_loaded('json')) {
9
- require_once(dirname(__FILE__) . '/json.php');
10
- function rplg_json_decode($data) {
11
- $json = new JSON;
12
- return $json->unserialize($data);
13
- }
14
- } else {
15
- function rplg_json_decode($data) {
16
- return json_decode($data);
17
- }
18
- }
19
-
20
- function rplg_json_urlopen($url, $postdata=false, $headers=array()) {
21
- if (!($response = rplg_urlopen($url, $postdata, $headers)) || !$response['code']) {
22
- //$this->last_error = 'COULDNT_CONNECT';
23
- return false;
24
- }
25
- return rplg_json_decode($response['data']);
26
- }
27
-
28
- function rplg_urlopen($url, $postdata=false, $headers=array()) {
29
- $response = array(
30
- 'data' => '',
31
- 'code' => 0
32
- );
33
-
34
- $url = preg_replace('/\s+/', '+', $url);
35
-
36
- if(function_exists('curl_init')) {
37
- if (!function_exists('curl_setopt_array')) {
38
- function curl_setopt_array(&$ch, $curl_options) {
39
- foreach ($curl_options as $option => $value) {
40
- if (!curl_setopt($ch, $option, $value)) {
41
- return false;
42
- }
43
- }
44
- return true;
45
- }
46
- }
47
- _rplg_curl_urlopen($url, $postdata, $headers, $response);
48
- } else if(ini_get('allow_url_fopen') && function_exists('stream_get_contents')) {
49
- _rplg_fopen_urlopen($url, $postdata, $headers, $response);
50
- } else {
51
- _rplg_fsockopen_urlopen($url, $postdata, $headers, $response);
52
- }
53
- return $response;
54
- }
55
-
56
- /*-------------------------------- curl --------------------------------*/
57
- function _rplg_curl_urlopen($url, $postdata, $headers, &$response) {
58
- $c = curl_init($url);
59
- $postdata_str = rplg_get_query_string($postdata);
60
-
61
- $c_options = array(
62
- CURLOPT_USERAGENT => RPLG_USER_AGENT,
63
- CURLOPT_RETURNTRANSFER => true,
64
- CURLOPT_POST => ($postdata_str ? 1 : 0),
65
- CURLOPT_HEADER => true,
66
- CURLOPT_HTTPHEADER => array_merge(array('Expect:'), $headers),
67
- CURLOPT_TIMEOUT => RPLG_SOCKET_TIMEOUT
68
- );
69
- if($postdata) {
70
- $c_options[CURLOPT_POSTFIELDS] = $postdata_str;
71
- }
72
- curl_setopt_array($c, $c_options);
73
-
74
- $open_basedir = ini_get('open_basedir');
75
- if(empty($open_basedir) && filter_var(ini_get('safe_mode'), FILTER_VALIDATE_BOOLEAN) === false) {
76
- curl_setopt($c, CURLOPT_FOLLOWLOCATION, true);
77
- }
78
- curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
79
-
80
- $data = curl_exec($c);
81
-
82
- // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string
83
- if (stripos($data, "HTTP/1.0 200 Connection established\r\n\r\n") !== false) {
84
- $data = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $data);
85
- }
86
-
87
- list($resp_headers, $response['data']) = explode("\r\n\r\n", $data, 2);
88
-
89
- $response['headers'] = _rplg_get_response_headers($resp_headers, $response);
90
- $response['code'] = curl_getinfo($c, CURLINFO_HTTP_CODE);
91
- curl_close($c);
92
- }
93
-
94
- /*-------------------------------- fopen --------------------------------*/
95
- function _rplg_fopen_urlopen($url, $postdata, $headers, &$response) {
96
- $params = array();
97
-
98
- if($postdata) {
99
- $params = array('http' => array(
100
- 'method' => 'POST',
101
- 'header' => implode("\r\n", array_merge(array('Content-Type: application/x-www-form-urlencoded'), $headers)),
102
- 'content' => rplg_get_query_string($postdata),
103
- 'timeout' => RPLG_SOCKET_TIMEOUT
104
- ));
105
- } else {
106
- $params = array('http' => array(
107
- 'header' => implode("\r\n", $headers)
108
- ));
109
- }
110
-
111
- ini_set('user_agent', RPLG_USER_AGENT);
112
- $ctx = stream_context_create($params);
113
- $fp = fopen($url, 'rb', false, $ctx);
114
- if(!$fp) { return false; }
115
-
116
- list($unused, $response['code'], $unused) = explode(' ', $http_response_header[0], 3);
117
- $resp_headers = array_slice($http_response_header, 1);
118
-
119
- foreach($resp_headers as $unused=>$header) {
120
- $header = explode(':', $header);
121
- $header[0] = trim($header[0]);
122
- $header[1] = trim($header[1]);
123
- $resp_headers[strtolower($header[0])] = strtolower($header[1]);
124
- }
125
- $response['data'] = stream_get_contents($fp);
126
- $response['headers'] = $resp_headers;
127
- }
128
-
129
- /*-------------------------------- fsockpen --------------------------------*/
130
- function _rplg_fsockopen_urlopen($url, $postdata, $headers, &$response) {
131
- $buf = '';
132
- $req = '';
133
- $length = 0;
134
- $postdata_str = rplg_get_query_string($postdata);
135
- $url_pieces = parse_url($url);
136
- $host = $url_pieces['host'];
137
-
138
- if(!isset($url_pieces['port'])) {
139
- switch($url_pieces['scheme']) {
140
- case 'http':
141
- $url_pieces['port'] = 80;
142
- break;
143
- case 'https':
144
- $url_pieces['port'] = 443;
145
- $host = 'ssl://' . $url_pieces['host'];
146
- break;
147
- }
148
- }
149
-
150
- if(!isset($url_pieces['path'])) { $url_pieces['path'] = '/'; }
151
-
152
- if(($url_pieces['port'] == 80 && $url_pieces['scheme'] == 'http') ||
153
- ($url_pieces['port'] == 443 && $url_pieces['scheme'] == 'https')) {
154
- $req_host = $url_pieces['host'];
155
- } else {
156
- $req_host = $url_pieces['host'] . ':' . $url_pieces['port'];
157
- }
158
-
159
- $fp = @fsockopen($host, $url_pieces['port'], $errno, $errstr, RPLG_SOCKET_TIMEOUT);
160
- if(!$fp) { return false; }
161
-
162
- $path = $url_pieces['path'];
163
- if (isset($url_pieces['query'])) $path .= '?'.$url_pieces['query'];
164
-
165
- $req .= ($postdata_str ? 'POST' : 'GET') . ' ' . $path . " HTTP/1.1\r\n";
166
- $req .= 'Host: ' . $req_host . "\r\n";
167
- $req .= rplg_get_http_headers_for_request($postdata_str, $headers);
168
- if($postdata_str) {
169
- $req .= "\r\n\r\n" . $postdata_str;
170
- }
171
- $req .= "\r\n\r\n";
172
-
173
- fwrite($fp, $req);
174
- while(!feof($fp)) {
175
- $buf .= fgets($fp, 4096);
176
- }
177
-
178
- list($headers, $response['data']) = explode("\r\n\r\n", $buf, 2);
179
-
180
- $headers = _rplg_get_response_headers($headers, $response);
181
-
182
- if(isset($headers['transfer-encoding']) && 'chunked' == strtolower($headers['transfer-encoding'])) {
183
- $chunk_data = $response['data'];
184
- $joined_data = '';
185
- while(true) {
186
- list($chunk_length, $chunk_data) = explode("\r\n", $chunk_data, 2);
187
- $chunk_length = hexdec($chunk_length);
188
- if(!$chunk_length || !strlen($chunk_data)) { break; }
189
-
190
- $joined_data .= substr($chunk_data, 0, $chunk_length);
191
- $chunk_data = substr($chunk_data, $chunk_length + 1);
192
- $length += $chunk_length;
193
- }
194
- $response['data'] = $joined_data;
195
- } else {
196
- $length = $headers['content-length'];
197
- }
198
- $response['headers'] = $headers;
199
- }
200
-
201
- /*-------------------------------- helpers --------------------------------*/
202
- function rplg_get_query_string($params) {
203
- $query = '';
204
-
205
- if($params) {
206
- foreach($params as $key=>$value) {
207
- $query .= urlencode($key) . '=' . urlencode($value) . '&';
208
- }
209
- }
210
- return $query;
211
- }
212
-
213
- function _rplg_get_response_headers($headers, &$response) {
214
- $headers = explode("\r\n", $headers);
215
- list($unused, $response['code'], $unused) = explode(' ', $headers[0], 3);
216
- $headers = array_slice($headers, 1);
217
- foreach($headers as $unused=>$header) {
218
- $header = explode(':', $header);
219
- $header[0] = trim($header[0]);
220
- $header[1] = trim($header[1]);
221
- $headers[strtolower($header[0])] = $header[1];
222
- }
223
- return $headers;
224
- }
225
-
226
- function rplg_get_http_headers_for_request($content, $headers) {
227
- $req_headers = array();
228
- $req_headers[] = 'User-Agent: ' . RPLG_USER_AGENT;
229
- $req_headers[] = 'Connection: close';
230
- if($content) {
231
- $req_headers[] = 'Content-Length: ' . strlen($content);
232
- $req_headers[] = 'Content-Type: application/x-www-form-urlencoded';
233
- }
234
- return implode("\r\n", array_merge($req_headers, $headers));
235
- }
236
-
237
- function rplg_url_method() {
238
- if(function_exists('curl_init')) {
239
- return 'curl';
240
- } else if(ini_get('allow_url_fopen') && function_exists('stream_get_contents')) {
241
- return 'fopen';
242
- } else {
243
- return 'fsockopen';
244
- }
245
- }
246
- }
247
-
248
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/admin.css ADDED
@@ -0,0 +1,376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .grw-admin #wpcontent {
2
+ padding: 0;
3
+ }
4
+
5
+ .google-reviews_page_grw-builder #wpcontent,
6
+ .grw-admin.google-reviews_page_grw-builder #wpcontent {
7
+ padding-right: 320px;
8
+ }
9
+
10
+ .toplevel_page_grw .wp-menu-image img {
11
+ width: 18px;
12
+ }
13
+
14
+ .grw-admin.edit-php #wpbody {
15
+ color: #5d6f80;
16
+ padding-left: 20px;
17
+ position: relative;
18
+ }
19
+
20
+ .grw-admin .update-nag {
21
+ margin: 20px 0 0 20px;
22
+ }
23
+
24
+ .grw-admin.edit-php .update-nag {
25
+ margin: 20px 20px 0 0;
26
+ }
27
+
28
+ .grw-admin.edit-php .update-nag ~ .update-nag {
29
+ margin-left: 0;
30
+ }
31
+
32
+ .grw-tophead {
33
+ -ms-flex-align: center;
34
+ -webkit-align-items: center;
35
+ -webkit-box-align: center;
36
+ -webkit-box-sizing: border-box;
37
+ align-items: center;
38
+ background-color: #fff;
39
+ border-bottom: 1px solid #cfd9db;
40
+ padding: 15px 20px;
41
+ box-sizing: border-box;
42
+ overflow: hidden;
43
+ position: relative;
44
+ top: 46px;
45
+ width: 100%;
46
+ }
47
+
48
+ @media (min-width: 601px) {
49
+ .grw-tophead {
50
+ -ms-flex-align: stretch;
51
+ -webkit-align-items: stretch;
52
+ -webkit-box-align: stretch;
53
+ align-items: stretch;
54
+ display: -webkit-box;
55
+ display: -webkit-flex;
56
+ display: -ms-flexbox;
57
+ display: flex;
58
+ top: 0;
59
+ }
60
+ }
61
+
62
+ .grw-tophead img {
63
+ width: 32px;
64
+ margin: 0 4px 0 0;
65
+ vertical-align: middle;
66
+ }
67
+
68
+ .grw-tophead-title {
69
+ padding: 0;
70
+ font-size: 18px;
71
+ font-weight: 600;
72
+ line-height: 1.4em;
73
+ }
74
+
75
+ .grw-page-title {
76
+ font-size: 23px;
77
+ font-weight: 400;
78
+ margin: 0;
79
+ padding: 20px 0 0 20px;
80
+ line-height: 29px;
81
+ }
82
+
83
+ .grw-admin #wpbody #screen-meta-links {
84
+ display:none
85
+ }
86
+
87
+ .grw-admin #screen-meta {
88
+ background-color: #ecf0f1;
89
+ border: 0;
90
+ margin: 0;
91
+ }
92
+
93
+ .grw-admin #screen-meta-links {
94
+ position: absolute;
95
+ top: 0;
96
+ right: 0;
97
+ z-index: 1;
98
+ }
99
+
100
+ .grw-admin.edit-php #wpbody .wp-header-end,
101
+ .grw-admin.post-new-php #wpbody .wp-header-end,
102
+ .grw-admin.post-php #wpbody .wp-header-end {
103
+ margin-top: 6px;
104
+ }
105
+
106
+ .grw-toolbar {
107
+ padding: 15px 20px;
108
+ background-color: #fff;
109
+ border-bottom: 1px solid #cfd9db;
110
+ }
111
+
112
+ @media (min-width: 783px) {
113
+ .grw-toolbar {
114
+ -webkit-box-align: center;
115
+ -ms-flex-align: center;
116
+ align-items: center;
117
+ display: -webkit-box;
118
+ display: -ms-flexbox;
119
+ display: flex;
120
+ -webkit-box-pack: justify;
121
+ -ms-flex-pack: justify;
122
+ justify-content: space-between;
123
+ }
124
+ }
125
+
126
+ .grw-toolbar-title {
127
+ -webkit-box-flex: 1;
128
+ -ms-flex: 1;
129
+ flex: 1;
130
+ margin-bottom: 0;
131
+ margin-right: 20px;
132
+ min-width: 0;
133
+ }
134
+
135
+ .grw-toolbar-title-input {
136
+ background-color: transparent!important;
137
+ border: none!important;
138
+ -webkit-box-shadow: none!important;
139
+ box-shadow: none!important;
140
+ width: 100%;
141
+ }
142
+
143
+ .grw-toolbar-title-input {
144
+ font-size: 18px;
145
+ font-weight: 400;
146
+ line-height: 1.4em;
147
+ margin: 0;
148
+ padding: 0;
149
+ }
150
+
151
+ .grw-toolbar-control {
152
+ display: -webkit-box;
153
+ display: -ms-flexbox;
154
+ display: flex;
155
+ }
156
+
157
+ .grw-toolbar-control button {
158
+ margin-left: 20px!important;
159
+ }
160
+
161
+ .grw-toolbar-control input[type="text"] {
162
+ width: 200px;
163
+ height: 34px;
164
+ font-size: 14px;
165
+ }
166
+
167
+ .grw-toolbar-options label {
168
+ display: block;
169
+ padding: 0 0 0 4px;
170
+ }
171
+
172
+ /* hide post content (json) in title column */
173
+ .grw-admin .type-grw_collection .title.column-title {
174
+ font-size: 0;
175
+ }
176
+ .grw-admin .type-grw_collection .title.column-title strong,
177
+ .grw-admin .type-grw_collection .title.column-title .row-actions {
178
+ line-height: 1.5em;
179
+ }
180
+
181
+ .grw-builder-workspace {
182
+ display: block;
183
+ position: relative;
184
+ width: 100%;
185
+ overflow-y: hidden;
186
+ box-sizing: border-box;
187
+ }
188
+
189
+ .grw-builder-preview {
190
+ font-size: 14px;
191
+ grid-area: preview;
192
+ min-height: 0;
193
+ min-width: 0;
194
+ padding: 20px;
195
+ line-height: 1.75;
196
+ }
197
+
198
+ .grw-builder-options {
199
+ box-sizing: border-box;
200
+ position: fixed;
201
+ top: 32px;
202
+ bottom: 0;
203
+ right: 0;
204
+ width: 320px;
205
+ overflow: hidden;
206
+ transition: all 0.3s;
207
+ z-index: 1;
208
+ overflow-y: auto;
209
+ background: #fafafa;
210
+ }
211
+
212
+ .nav-tab.nav-tab-active {
213
+ box-shadow: none;
214
+ background: #fff;
215
+ border-bottom-color: #fff;
216
+ }
217
+
218
+ .grw-settings-workspace {
219
+ font-size: 14px;
220
+ margin: 20px;
221
+ padding: 20px;
222
+ background: #fff;
223
+ }
224
+
225
+ .grw-settings-workspace p {
226
+ font-size: 14px;
227
+ }
228
+
229
+ .grw-field,
230
+ .grw-field * {
231
+ box-sizing: border-box;
232
+ }
233
+
234
+ .grw-field {
235
+ padding: 0 0 15px 0;
236
+ margin-top: 1em;
237
+ margin-bottom: 1em;
238
+ border-bottom: 1px dashed #ddd;
239
+ }
240
+
241
+ @media (min-width: 600px) {
242
+ .grw-field {
243
+ display: flex;
244
+ flex-wrap: wrap;
245
+ }
246
+ .grw-field-label {
247
+ flex: 0 0 25%;
248
+ padding-right: 4%;
249
+ }
250
+ .grw-field-option {
251
+ flex: 0 0 75%;
252
+ }
253
+ }
254
+
255
+ .grw-field input[type="text"] {
256
+ margin: 0;
257
+ padding: 5px 8px;
258
+ border-radius: 2px;
259
+ }
260
+
261
+ .grw-field select {
262
+ width: 15em;
263
+ margin-left: 0;
264
+ }
265
+
266
+ .grw-alert {
267
+ font-size: 14px;
268
+ line-height: 1.846;
269
+ border: none;
270
+ color: #fff;
271
+ padding: 15px;
272
+ margin-bottom: 23px;
273
+ border: 1px solid transparent;
274
+ border-radius: 3px;
275
+ }
276
+
277
+ .grw-alert-dismissable,
278
+ .grw-alert-dismissible {
279
+ padding-right: 35px;
280
+ }
281
+
282
+ .grw-alert-success {
283
+ color: #fff;
284
+ border-color: #d6e9c6;
285
+ background-color: #4caf50;
286
+ }
287
+
288
+ .grw-alert-warning {
289
+ background-color: #a22525;
290
+ }
291
+
292
+ .grw-alert a:not(.close),
293
+ .grw-alert .alert-link {
294
+ color: #fff;
295
+ font-weight: bold;
296
+ }
297
+
298
+ .grw-settings-workspace .grw-alert {
299
+ max-width: 500px;
300
+ word-wrap: break-word;
301
+ }
302
+
303
+ .grw-flex-row {
304
+ display: flex;
305
+ flex-flow: row wrap;
306
+ width: 100%;
307
+ align-items: center!important;
308
+ text-align: left;
309
+ margin-bottom: 40px;
310
+ }
311
+
312
+ .grw-flex-col,
313
+ .grw-flex-col3 {
314
+ box-sizing: border-box;
315
+ padding: 0 20px;
316
+ line-height: 24px;
317
+ }
318
+
319
+ .grw-flex-col:first-child,
320
+ .grw-flex-col3:first-child {
321
+ padding-right: 10px;
322
+ }
323
+
324
+ @media (min-width: 700px) {
325
+ .grw-flex-col {
326
+ width: 50%;
327
+ }
328
+ .grw-flex-col7 {
329
+ width: 70%;
330
+ }
331
+ .grw-flex-col3 {
332
+ width: 30%;
333
+ }
334
+ }
335
+
336
+ .grw-support-question {
337
+ padding-bottom: 10px;
338
+ }
339
+
340
+ .grw-support-workspace {
341
+ font-size: 15px;
342
+ line-height: 22px;
343
+ margin: 20px;
344
+ padding: 20px;
345
+ background: #fff;
346
+ }
347
+
348
+ .grw-support-workspace p {
349
+ font-size: 15px;
350
+ }
351
+
352
+ .grw-support-workspace img {
353
+ width: 100%;
354
+ }
355
+
356
+ .grw-support-workspace .subheader {
357
+ color: #4b76b7;
358
+ margin: 40px 0 20px;
359
+ text-decoration: underline;
360
+ }
361
+
362
+ .grw-support-workspace .grw-flex-col > b:first-child,
363
+ .grw-support-workspace .grw-flex-col3 > b:first-child {
364
+ padding: 2px 8px;
365
+ margin-right: 4px;
366
+ border-radius: 50%;
367
+ color: #fff;
368
+ background: #36ad55;
369
+ box-shadow: 0 2px 5px 0 rgb(0 0 0 / 26%);
370
+ }
371
+
372
+ .box-img {
373
+ padding: 15px;
374
+ margin: 0 0 10px;
375
+ box-shadow: 0 2px 5px 0 rgba(0,0,0,.26);
376
+ }
assets/css/feedbuilder.css ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .grw-builder-platforms {
2
+ position: relative;
3
+ box-sizing: border-box;
4
+ }
5
+
6
+ /*.grw-platform-google .grw-builder-top {
7
+ color: #e7711b;
8
+ }
9
+
10
+ .grw-platform-facebook .grw-builder-top {
11
+ color: #3c5b9b;
12
+ }
13
+
14
+ .grw-platform-yelp .grw-builder-top {
15
+ color: #d32323;
16
+ }*/
17
+
18
+ .grw-builder-top {
19
+ padding: 10px;
20
+ color: #23282d;
21
+ font-size: 13px;
22
+ font-weight: 600;
23
+ line-height: 1.4em;
24
+ cursor: pointer;
25
+ border: 1px solid #e5e5e5;
26
+ box-shadow: 0 1px 1px rgba(0,0,0,.04);
27
+ background: #fafafa url('../img/button-down-black.svg') no-repeat right;
28
+ }
29
+
30
+ .grw-builder-top:hover {
31
+ border-color: #999;
32
+ box-shadow: 0 1px 2px rgba(0,0,0,.1);
33
+ }
34
+
35
+ .grw-builder-inside {
36
+ border-top: none;
37
+ padding: 10px 10px 0;
38
+ line-height: 16px;
39
+ background: #fff;
40
+ border: 1px solid #e5e5e5;
41
+ box-shadow: 0 1px 1px rgba(0,0,0,.04);
42
+ }
43
+
44
+ .grw-builder-inside .grw-builder-option {
45
+ margin: 10px 0 0;
46
+ position: relative;
47
+ }
48
+
49
+ .grw-builder-inside .grw-builder-option:first-child {
50
+ margin-top: 0;
51
+ }
52
+
53
+ .grw-builder-inside .grw-builder-option:last-child {
54
+ margin-bottom: 10px;
55
+ }
56
+
57
+ .grw-builder-inside input[type="text"],
58
+ .grw-builder-inside select,
59
+ .grw-builder-inside button,
60
+ .grw-builder-inside textarea {
61
+ width: 100%;
62
+ clear: both;
63
+ border-spacing: 0;
64
+ }
65
+
66
+ .grw-builder-inside pre {
67
+ margin: 0;
68
+ color: #b73434;
69
+ font-size: 10px;
70
+ line-height: 16px;
71
+ padding: 4px;
72
+ background: #fff;
73
+ overflow: auto;
74
+ }
75
+
76
+ .grw-builder-connect {
77
+ margin: 0 0 10px;
78
+ padding: 6px;
79
+ color: #fff;
80
+ border: none;
81
+ cursor: pointer;
82
+ text-align: center;
83
+ background: #eee;
84
+ }
85
+
86
+ .grw-builder-connect.grw-connect-google {
87
+ font-weight: 600;
88
+ font-size: 12px;
89
+ text-transform: uppercase;
90
+ background: #fa8e08;
91
+ }
92
+
93
+ .grw-connect-google-inside {
94
+ padding: 0 1px;
95
+ }
96
+
97
+ .grw-builder-connect.grw-connect-facebook {
98
+ background: #3c5b9b;
99
+ }
100
+
101
+ .grw-builder-connect.grw-connect-tripadvisor {
102
+ background: #3eca77;
103
+ }
104
+
105
+ .grw-builder-connect.grw-connect-yelp {
106
+ margin-bottom: 0;
107
+ background: #d32323;
108
+ }
109
+
110
+ .grw-builder-connect.grw-connect-google + div,
111
+ .grw-builder-connect.grw-connect-yelp + div {
112
+ margin-top: 10px;
113
+ }
114
+
115
+ .grw-connections {
116
+ padding-bottom: 10px;
117
+ }
118
+
119
+ .grw-connection {
120
+ cursor: move;
121
+ }
122
+
123
+ .grw-connect-business {
124
+ color: #333;
125
+ text-align: left;
126
+ margin: 10px 0 0;
127
+ border: 1px solid #ccc;
128
+ background: #fafafa url(../img/button-down-black.svg) no-repeat right;
129
+ }
130
+
131
+ .grw-connect-business + div {
132
+ padding: 4px;
133
+ border: 1px solid rgb(204, 204, 204);
134
+ border-top: 0;
135
+ }
136
+
137
+ .grw-connect-select {
138
+ display: none!important;
139
+ }
140
+
141
+ .grw-platform-multiple .grw-connect-select {
142
+ display: inline-block!important;
143
+ }
144
+
145
+ .grw-connect-photo {
146
+ width: 24px;
147
+ height: 24px;
148
+ margin-right: 10px;
149
+ border-radius: 50%;
150
+ border: 1px solid #ccc;
151
+ vertical-align: middle;
152
+ }
153
+
154
+ .grw-connect-photo-change {
155
+ margin-right: 10px
156
+ }
157
+
158
+ .grw-connect-error {
159
+ color: #e60909;
160
+ font-size: 13px;
161
+ }
162
+
163
+ .grw-connection-checkbox {
164
+ display: none;
165
+ margin: 10px 0 0 6px;
166
+ }
167
+
168
+ .grw-platform-multiple .grw-connection-checkbox {
169
+ display: block;
170
+ }
171
+
172
+ .grw-quest {
173
+ position: absolute;
174
+ top: 6px;
175
+ right: 3px;
176
+ width: 16px;
177
+ cursor: pointer;
178
+ font-size: 12px;
179
+ font-weight: bold;
180
+ text-align: center;
181
+ border: 1px solid #ccc;
182
+ border-radius: 50px;
183
+ background: #eee;
184
+ }
185
+
186
+ .grw-quest.grw-quest-top {
187
+ top: 0;
188
+ }
189
+
190
+ .grw-quest.grw-quest-top22 {
191
+ top: 22px;
192
+ }
193
+
194
+ .grw-quest:hover {
195
+ border: 1px solid #999;
196
+ }
197
+
198
+ .grw-quest-help {
199
+ display: none;
200
+ margin: 0 0 10px 0;
201
+ padding: 4px;
202
+ font-size: 13px;
203
+ line-height: 18px;
204
+ background: #eee;
205
+ }
206
+
207
+ .grw-well {
208
+ padding: 10px;
209
+ margin: 10px 0px;
210
+ border-radius: 3px;
211
+ border: 1px solid #d9d9d9;
212
+ background: #f1f1f1;
213
+ }
214
+
215
+ #rating_temp {
216
+ height: 260px;
217
+ font-size: 12px;
218
+ word-break: break-all;
219
+ }
{static → assets}/css/google-review.css RENAMED
File without changes
{static → assets}/css/rplg-setting.css RENAMED
@@ -1,7 +1,3 @@
1
- #wpcontent {
2
- padding: 0;
3
- }
4
-
5
  .rplg-version {
6
  position: absolute;
7
  top: 6px;
@@ -10,7 +6,7 @@
10
  -moz-border-radius: 3px;
11
  border-radius: 3px;
12
  display: inline-block;
13
- margin: 20px 0 0;
14
  padding: 6px 10px;
15
  font-size: 12px;
16
  line-height: 14px;
@@ -195,25 +191,25 @@
195
  display: none !important;
196
  }
197
 
198
- .rplg-setting .wp-review-hidden {
199
- opacity: .5;
200
  }
201
 
202
- .rplg-setting .wp-review-hide {
203
- color: #fff;
204
- font-size: 12px;
205
- font-weight: 600;
206
- line-height: 26px;
207
- text-decoration: none;
208
- text-transform: uppercase;
209
- padding: 2px 8px;
210
- border-radius: 3px;
211
- border-color: #0062cc;
212
- background-color: #427fbf;
213
  }
214
 
215
- .rplg-setting .wp-review-hide:hover {
216
- background-color: #1d62ab;
217
  }
218
 
219
  #support h3 {
 
 
 
 
1
  .rplg-version {
2
  position: absolute;
3
  top: 6px;
6
  -moz-border-radius: 3px;
7
  border-radius: 3px;
8
  display: inline-block;
9
+ margin: 12px 0 0;
10
  padding: 6px 10px;
11
  font-size: 12px;
12
  line-height: 14px;
191
  display: none !important;
192
  }
193
 
194
+ .wp-gr .wp-review-hidden {
195
+ opacity: .5 !important;
196
  }
197
 
198
+ .wp-gr .wp-review-hide {
199
+ color: #fff !important;
200
+ font-size: 12px !important;
201
+ font-weight: 600 !important;
202
+ line-height: 26px !important;
203
+ text-decoration: none !important;
204
+ text-transform: uppercase !important;
205
+ padding: 2px 8px !important;
206
+ border-radius: 3px !important;
207
+ border-color: #0062cc !important;
208
+ background-color: #427fbf !important;
209
  }
210
 
211
+ .wp-gr .wp-review-hide:hover {
212
+ background-color: #1d62ab !important;
213
  }
214
 
215
  #support h3 {
{static → assets}/css/rplg-wp.css RENAMED
File without changes
{static → assets}/img/button-down-black.svg RENAMED
File without changes
{static → assets}/img/google.png RENAMED
File without changes
{static → assets}/img/google_key_1.png RENAMED
File without changes
{static → assets}/img/google_key_2.png RENAMED
File without changes
{static → assets}/img/google_key_2_1.png RENAMED
File without changes
{static → assets}/img/google_key_3.png RENAMED
File without changes
{static → assets}/img/google_key_4.png RENAMED
File without changes
{static → assets}/img/google_key_4_1.png RENAMED
File without changes
{static → assets}/img/google_key_5.png RENAMED
File without changes
{static → assets}/img/google_key_6.png RENAMED
File without changes
{static → assets}/img/google_key_7.png RENAMED
File without changes
{static → assets}/img/google_key_8.png RENAMED
File without changes
{static → assets}/img/google_placeid_1.png RENAMED
File without changes
{static → assets}/img/google_placeid_2.png RENAMED
File without changes
{static → assets}/img/google_placeid_3.png RENAMED
File without changes
{static → assets}/img/google_rating_logo_36.png RENAMED
File without changes
assets/img/logo.png ADDED
Binary file
assets/img/menu_icon.png ADDED
Binary file
{static → assets}/img/powered_by_google_on_non_white.png RENAMED
File without changes
{static → assets}/img/powered_by_google_on_white.png RENAMED
File without changes
assets/js/admin.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($) {
2
+
3
+ $('.grw-admin-page a.nav-tab').on('click', function(e) {
4
+ var $this = $(this), activeId = $this.attr('href');
5
+ $(activeId).show().siblings('.tab-content').hide();
6
+ $this.addClass('nav-tab-active').siblings().removeClass('nav-tab-active');
7
+ e.preventDefault();
8
+ });
9
+
10
+ });
{static → assets}/js/blazy.min.js RENAMED
File without changes
assets/js/feedbuilder.js ADDED
@@ -0,0 +1,706 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var HTML_CONTENT = '' +
2
+
3
+ '<div class="grw-builder-platforms grw-builder-inside">' +
4
+
5
+ '<div class="grw-toggle grw-builder-connect grw-connect-google">Connect Google</div>' +
6
+ '<div class="grw-connect-google-inside" style="display:none">' +
7
+ '<div class="grw-builder-option">' +
8
+ '<input type="text" class="grw-connect-id" value="" placeholder="Place ID" />' +
9
+ '<span class="grw-quest grw-toggle" title="Click to help">?</span>' +
10
+ '<div class="grw-quest-help">' +
11
+ 'Enter Place ID of your Google location. If you don\'t know this, you can simply find it by ' +
12
+ '<a href="' + GRW_VARS.supportUrl + '" target="_blank">this instruction</a>.' +
13
+ '</div>' +
14
+ '</div>' +
15
+ '<div class="grw-builder-option">' +
16
+ '<select class="grw-connect-lang">' +
17
+ '<option value="">Use default language (English) or choose specific</option>' +
18
+ '<option value="ar">Arabic</option>' +
19
+ '<option value="bg">Bulgarian</option>' +
20
+ '<option value="bn">Bengali</option>' +
21
+ '<option value="ca">Catalan</option>' +
22
+ '<option value="cs">Czech</option>' +
23
+ '<option value="da">Danish</option>' +
24
+ '<option value="de">German</option>' +
25
+ '<option value="el">Greek</option>' +
26
+ '<option value="en">English</option>' +
27
+ //'<option value="en-AU">English (Australian)</option>' +
28
+ //'<option value="en-GB">English (Great Britain)</option>' +
29
+ '<option value="es">Spanish</option>' +
30
+ '<option value="eu">Basque</option>' +
31
+ '<option value="eu">Basque</option>' +
32
+ '<option value="fa">Farsi</option>' +
33
+ '<option value="fi">Finnish</option>' +
34
+ '<option value="fil">Filipino</option>' +
35
+ '<option value="fr">French</option>' +
36
+ '<option value="gl">Galician</option>' +
37
+ '<option value="gu">Gujarati</option>' +
38
+ '<option value="hi">Hindi</option>' +
39
+ '<option value="hr">Croatian</option>' +
40
+ '<option value="hu">Hungarian</option>' +
41
+ '<option value="id">Indonesian</option>' +
42
+ '<option value="it">Italian</option>' +
43
+ '<option value="iw">Hebrew</option>' +
44
+ '<option value="ja">Japanese</option>' +
45
+ '<option value="kn">Kannada</option>' +
46
+ '<option value="ko">Korean</option>' +
47
+ '<option value="lt">Lithuanian</option>' +
48
+ '<option value="lv">Latvian</option>' +
49
+ '<option value="ml">Malayalam</option>' +
50
+ '<option value="mr">Marathi</option>' +
51
+ '<option value="nl">Dutch</option>' +
52
+ '<option value="no">Norwegian</option>' +
53
+ '<option value="pl">Polish</option>' +
54
+ '<option value="pt">Portuguese</option>' +
55
+ '<option value="pt-BR">Portuguese (Brazil)</option>' +
56
+ '<option value="pt-PT">Portuguese (Portugal)</option>' +
57
+ '<option value="ro">Romanian</option>' +
58
+ '<option value="ru">Russian</option>' +
59
+ '<option value="sk">Slovak</option>' +
60
+ '<option value="sl">Slovenian</option>' +
61
+ '<option value="sr">Serbian</option>' +
62
+ '<option value="sv">Swedish</option>' +
63
+ '<option value="ta">Tamil</option>' +
64
+ '<option value="te">Telugu</option>' +
65
+ '<option value="th">Thai</option>' +
66
+ '<option value="tl">Tagalog</option>' +
67
+ '<option value="tr">Turkish</option>' +
68
+ '<option value="uk">Ukrainian</option>' +
69
+ '<option value="vi">Vietnamese</option>' +
70
+ '<option value="zh-CN">Chinese (Simplified)</option>' +
71
+ '<option value="zh-TW">Chinese (Traditional)</option>' +
72
+ '</select>' +
73
+ '</div>' +
74
+ '<div class="grw-builder-option">' +
75
+ '<input type="text" class="grw-connect-key" value="' + GRW_VARS.googleAPIKey + '" placeholder="Google Places API Key" />' +
76
+ '<span class="grw-quest grw-toggle" title="Click to help">?</span>' +
77
+ '<div class="grw-quest-help">' +
78
+ 'Except a Place ID you should also create your own Google API key, it\'s very simple and won\'t take more than a few minutes, please <a href="' + GRW_VARS.supportUrl + '" target="_blank">read this manual</a>.' +
79
+ '</div>' +
80
+ '</div>' +
81
+ '<div class="grw-builder-option">' +
82
+ '<button class="grw-connect-btn">Connect Google</button>' +
83
+ '<small class="grw-connect-error"></small>' +
84
+ '</div>' +
85
+ '</div>' +
86
+
87
+ '<div class="grw-connections"></div>' +
88
+
89
+ '</div>' +
90
+
91
+ '<div class="grw-connect-options">' +
92
+
93
+ '<div class="grw-builder-inside">' +
94
+
95
+ '<div class="grw-builder-option">' +
96
+ 'Pagination' +
97
+ '<input type="text" name="pagination" value="">' +
98
+ '</div>' +
99
+
100
+ '<div class="grw-builder-option">' +
101
+ 'Maximum characters before \'read more\' link' +
102
+ '<input type="text" name="text_size" value="">' +
103
+ '</div>' +
104
+
105
+ '<div class="grw-builder-option">' +
106
+ 'Maximum width' +
107
+ '<input type="text" name="max_width" value="" placeholder="for instance: 300px">' +
108
+ '</div>' +
109
+
110
+ '<div class="grw-builder-option">' +
111
+ 'Maximum height' +
112
+ '<input type="text" name="max_height" value="" placeholder="for instance: 500px">' +
113
+ '</div>' +
114
+
115
+ '<div class="grw-builder-option">' +
116
+ '<label>' +
117
+ '<input type="checkbox" name="hide_based_on" value="">' +
118
+ 'Hide \'Based on ... reviews\'' +
119
+ '</label>' +
120
+ '</div>' +
121
+
122
+ '<div class="grw-builder-option">' +
123
+ '<label>' +
124
+ '<input type="checkbox" name="hide_reviews" value="">' +
125
+ 'Hide reviews, leave only rating header' +
126
+ '</label>' +
127
+ '</div>' +
128
+
129
+ '<div class="grw-builder-option">' +
130
+ '<label>' +
131
+ '<input type="checkbox" name="centered" value="">' +
132
+ 'Place by center (only if Width is set)' +
133
+ '</label>' +
134
+ '</div>' +
135
+
136
+ '<div class="grw-builder-option">' +
137
+ '<label>' +
138
+ '<input type="checkbox" name="dark_theme">' +
139
+ 'Dark background' +
140
+ '</label>' +
141
+ '</div>' +
142
+
143
+ '</div>' +
144
+
145
+ '<div class="grw-builder-top grw-toggle">Advance Options</div>' +
146
+ '<div class="grw-builder-inside" style="display:none">' +
147
+ '<div class="grw-builder-option">' +
148
+ '<label>' +
149
+ '<input type="checkbox" name="lazy_load_img" checked>' +
150
+ 'Lazy load images' +
151
+ '</label>' +
152
+ '</div>' +
153
+ '<div class="grw-builder-option">' +
154
+ '<label>' +
155
+ '<input type="checkbox" name="google_def_rev_link">' +
156
+ 'Use default Google reviews link' +
157
+ '</label>' +
158
+ '<span class="grw-quest grw-quest-top grw-toggle" title="Click to help">?</span>' +
159
+ '<div class="grw-quest-help" style="display:none;">If the direct link to all reviews <b>https://search.google.com/local/reviews?placeid=&lt;PLACE_ID&gt;</b> does not work with your Google place (leads to 404), please use this option to use the default reviews link to Google map.</div>' +
160
+ '</div>' +
161
+ '<div class="grw-builder-option">' +
162
+ '<label>' +
163
+ '<input type="checkbox" name="open_link" checked>' +
164
+ 'Open links in new Window' +
165
+ '</label>' +
166
+ '</div>' +
167
+ '<div class="grw-builder-option">' +
168
+ '<label>' +
169
+ '<input type="checkbox" name="nofollow_link" checked>' +
170
+ 'Use no follow links' +
171
+ '</label>' +
172
+ '</div>' +
173
+ '<div class="grw-builder-option">' +
174
+ 'Reviewer avatar size' +
175
+ '<select name="reviewer_avatar_size">' +
176
+ '<option value="56" selected="selected">Small: 56px</option>' +
177
+ '<option value="128">Medium: 128px</option>' +
178
+ '<option value="256">Large: 256px</option>' +
179
+ '</select>' +
180
+ '</div>' +
181
+ '<div class="grw-builder-option">' +
182
+ 'Cache data' +
183
+ '<select name="cache">' +
184
+ '<option value="1">1 Hour</option>' +
185
+ '<option value="3">3 Hours</option>' +
186
+ '<option value="6">6 Hours</option>' +
187
+ '<option value="12" selected="selected">12 Hours</option>' +
188
+ '<option value="24">1 Day</option>' +
189
+ '<option value="48">2 Days</option>' +
190
+ '<option value="168">1 Week</option>' +
191
+ '<option value="">Disable (NOT recommended)</option>' +
192
+ '</select>' +
193
+ '</div>' +
194
+ '<div class="grw-builder-option">' +
195
+ 'Reviews limit' +
196
+ '<input type="text" name="reviews_limit" value="">' +
197
+ '</div>' +
198
+ '</div>' +
199
+
200
+ '</div>';
201
+
202
+ function grw_builder_init($, data) {
203
+
204
+ var el = document.querySelector(data.el);
205
+ if (!el) return;
206
+
207
+ el.innerHTML = HTML_CONTENT;
208
+
209
+ if (data.conns) {
210
+ grw_deserialize_connections($, el, data.conns, data.opts);
211
+ }
212
+
213
+ // Google Connect
214
+ var platform_google_el = el.querySelector('.grw-connect-google-inside');
215
+ grw_connection($, platform_google_el, 'google');
216
+
217
+ $('.grw-connect-options input[type="text"],.grw-connect-options textarea').keyup(function() {
218
+ grw_serialize_connections();
219
+ });
220
+ $('.grw-connect-options input[type="checkbox"],.grw-connect-options select').change(function() {
221
+ grw_serialize_connections();
222
+ });
223
+
224
+ $('.grw-toggle', el).unbind('click').click(function () {
225
+ $(this).toggleClass('toggled');
226
+ $(this).next().slideToggle();
227
+ });
228
+
229
+ if ($('.grw-connections').sortable) {
230
+ $('.grw-connections').sortable({
231
+ stop: function(event, ui) {
232
+ grw_serialize_connections();
233
+ }
234
+ });
235
+ $('.grw-connections').disableSelection();
236
+ }
237
+
238
+ $('.wp-review-hide').click(function() {
239
+ var $this = $(this);
240
+ $.post(GRW_VARS.handlerUrl + '&cf_action=grw_hide_review', {
241
+ id : $this.attr('data-id'),
242
+ feed_id : $('input[name="grw_feed[post_id]"]').val(),
243
+ grw_wpnonce : $('#grw_nonce').val()
244
+ }, function(res) {
245
+ var parent = $this.parent().parent();
246
+ if (res.hide) {
247
+ $this.text('show review');
248
+ parent.addClass('wp-review-hidden');
249
+ } else {
250
+ $this.text('hide review');
251
+ parent.removeClass('wp-review-hidden');
252
+ }
253
+ }, 'json');
254
+ return false;
255
+ });
256
+
257
+ $('#grw_save').click(function() {
258
+ return grw_feed_save();
259
+ });
260
+ }
261
+
262
+ function grw_feed_save() {
263
+ if (!window.grw_title.value) {
264
+ window.grw_title.focus();
265
+ return false;
266
+ }
267
+
268
+ var content = document.getElementById('grw-builder-connection').value;
269
+ if (content) {
270
+ var json = JSON.parse(content)
271
+ if (json) {
272
+ if (json.connections && json.connections.length) {
273
+ return true;
274
+ }
275
+ }
276
+ }
277
+
278
+ alert("Please click 'CONNECT GOOGLE' and connect your Google reviews then save this widget");
279
+ return false;
280
+ }
281
+
282
+ function grw_connection($, el, platform) {
283
+ var connect_btn = el.querySelector('.grw-connect-btn');
284
+ $(connect_btn).click(function() {
285
+
286
+ var connect_id_el = el.querySelector('.grw-connect-id'),
287
+ connect_key_el = el.querySelector('.grw-connect-key');
288
+
289
+ if (!connect_id_el.value) {
290
+ connect_id_el.focus();
291
+ return false;
292
+ } else if (!connect_key_el.value) {
293
+ connect_key_el.focus();
294
+ return false;
295
+ }
296
+
297
+ var id = (platform == 'yelp' ? /.+\/biz\/(.*?)(\?|\/|$)/.exec(connect_id_el.value)[1] : connect_id_el.value),
298
+ lang = el.querySelector('.grw-connect-lang').value,
299
+ key = connect_key_el.value;
300
+
301
+ connect_btn.innerHTML = 'Please wait...';
302
+ connect_btn.disabled = true;
303
+
304
+ var url = GRW_VARS.handlerUrl + '&cf_action=grw_connect_' + platform + '&v=' + new Date().getTime();
305
+ jQuery.post(url, {
306
+ id: decodeURIComponent(id),
307
+ lang: lang,
308
+ key: key,
309
+ grw_wpnonce: jQuery('#grw_nonce').val()
310
+ }, function(res) {
311
+
312
+ console.log('grw_connect_debug:', res);
313
+
314
+ connect_btn.innerHTML = 'Connect ' + (platform.charAt(0).toUpperCase() + platform.slice(1));
315
+ connect_btn.disabled = false;
316
+
317
+ var error_el = el.querySelector('.grw-connect-error');
318
+
319
+ if (res.status == 'success') {
320
+
321
+ error_el.innerHTML = '';
322
+
323
+ var connection_params = {
324
+ id : res.result.id,
325
+ lang : lang,
326
+ name : res.result.name,
327
+ photo : res.result.photo,
328
+ refresh : true,
329
+ platform : platform,
330
+ props : {
331
+ default_photo : res.result.photo
332
+ }
333
+ };
334
+
335
+ grw_connection_add($, el, connection_params);
336
+ grw_serialize_connections();
337
+
338
+ } else {
339
+
340
+ error_el.innerHTML = '<b>Error</b>: ' + res.result.error_message;
341
+ if (res.result.status == 'OVER_QUERY_LIMIT') {
342
+ error_el.innerHTML += '<br><br>More recently, Google has limited the API to 1 request per day for new users, try to create new <a href="https://developers.google.com/places/web-service/get-api-key#get_an_api_key" target="_blank">Google API key</a>, save in the setting and Connect Google again.';
343
+ }
344
+
345
+ }
346
+
347
+ }, 'json');
348
+ return false;
349
+ });
350
+ }
351
+
352
+ function grw_connection_add($, el, conn, checked) {
353
+
354
+ var connected_id = 'grw-' + conn.platform + '-' + conn.id.replace(/\//g, '');
355
+ if (conn.lang != null) {
356
+ connected_id += conn.lang;
357
+ }
358
+
359
+ var connected_el = $('#' + connected_id);
360
+
361
+ if (!connected_el.length) {
362
+ connected_el = $('<div class="grw-connection"></div>')[0];
363
+ connected_el.id = connected_id;
364
+ if (conn.lang != undefined) {
365
+ connected_el.setAttribute('data-lang', conn.lang);
366
+ }
367
+ connected_el.setAttribute('data-platform', conn.platform);
368
+ connected_el.innerHTML = grw_connection_render(conn, checked);
369
+
370
+ var connections_el = $('.grw-connections')[0];
371
+ connections_el.appendChild(connected_el);
372
+
373
+ jQuery('.grw-toggle', connected_el).unbind('click').click(function () {
374
+ jQuery(this).toggleClass('toggled');
375
+ jQuery(this).next().slideToggle();
376
+ });
377
+
378
+ var file_frame;
379
+ jQuery('.grw-connect-photo-change', connected_el).on('click', function(e) {
380
+ e.preventDefault();
381
+ grw_upload_photo(connected_el, file_frame, function() {
382
+ grw_serialize_connections();
383
+ });
384
+ return false;
385
+ });
386
+
387
+ jQuery('.grw-connect-photo-default', connected_el).on('click', function(e) {
388
+ grw_change_photo(connected_el, conn.props.default_photo);
389
+ grw_serialize_connections();
390
+ return false;
391
+ });
392
+
393
+ $('input[type="text"]', connected_el).keyup(function() {
394
+ grw_serialize_connections();
395
+ });
396
+
397
+ $('input[type="checkbox"]', connected_el).click(function() {
398
+ grw_serialize_connections();
399
+ });
400
+
401
+ $('.grw-connect-delete', connected_el).click(function() {
402
+ if (confirm('Are you sure to delete this business?')) {
403
+ if (!GRW_VARS.wordpress) {
404
+ var id = connected_el.querySelector('input[name="id"]').value,
405
+ deleted = window.connections_delete.value;
406
+ window.connections_delete.value += (deleted ? ',' + id : id);
407
+ }
408
+ $(connected_el).remove();
409
+ grw_serialize_connections();
410
+ }
411
+ return false;
412
+ });
413
+ }
414
+ }
415
+
416
+ function grw_connection_render(conn, checked) {
417
+ var name = conn.name;
418
+ if (conn.lang) {
419
+ name += ' (' + conn.lang + ')';
420
+ }
421
+
422
+ conn.photo = conn.photo || 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
423
+
424
+ var option = document.createElement('option');
425
+ if (conn.platform == 'google' && conn.props && conn.props.place_id) {
426
+ option.value = conn.props.place_id;
427
+ } else {
428
+ option.value = conn.id;
429
+ }
430
+ option.text = grw_capitalize(conn.platform) + ': ' + conn.name;
431
+
432
+ return '' +
433
+ '<div class="grw-toggle grw-builder-connect grw-connect-business">' +
434
+ '<input type="checkbox" class="grw-connect-select" onclick="event.stopPropagation();" ' + (checked?'checked':'') + ' /> ' +
435
+ name + (conn.address ? ' (' + conn.address + ')' : '') +
436
+ '</div>' +
437
+ '<div style="display:none">' +
438
+ (function(props) {
439
+ var result = '';
440
+ for (prop in props) {
441
+ if (prop != 'platform' && Object.prototype.hasOwnProperty.call(props, prop)) {
442
+ result += '<input type="hidden" name="' + prop + '" value="' + props[prop] + '" class="grw-connect-prop" readonly />';
443
+ }
444
+ }
445
+ return result;
446
+ })(conn.props) +
447
+ '<input type="hidden" name="id" value="' + conn.id + '" readonly />' +
448
+ (conn.address ? '<input type="hidden" name="address" value="' + conn.address + '" readonly />' : '') +
449
+ (conn.access_token ? '<input type="hidden" name="access_token" value="' + conn.access_token + '" readonly />' : '') +
450
+ '<div class="grw-builder-option">' +
451
+ '<img src="' + conn.photo + '" alt="' + conn.name + '" class="grw-connect-photo">' +
452
+ '<a href="#" class="grw-connect-photo-change">Change</a>' +
453
+ '<a href="#" class="grw-connect-photo-default">Default</a>' +
454
+ '<input type="hidden" name="photo" class="grw-connect-photo-hidden" value="' + conn.photo + '" tabindex="2"/>' +
455
+ '<input type="file" tabindex="-1" accept="image/*" onchange="grw_upload_image(this.parentNode, this.files)" style="display:none!important">' +
456
+ '</div>' +
457
+ '<div class="grw-builder-option">' +
458
+ '<input type="text" name="name" value="' + conn.name + '" />' +
459
+ '</div>' +
460
+ (conn.website != undefined ?
461
+ '<div class="grw-builder-option">' +
462
+ '<input type="text" name="website" value="' + conn.website + '" />' +
463
+ '</div>'
464
+ : '' ) +
465
+ (conn.lang != undefined ?
466
+ '<div class="grw-builder-option">' +
467
+ '<input type="text" name="lang" value="' + conn.lang + '" placeholder="Default language (English)" readonly />' +
468
+ '</div>'
469
+ : '' ) +
470
+ (conn.review_count != undefined ?
471
+ '<div class="grw-builder-option">' +
472
+ '<input type="text" name="review_count" value="' + conn.review_count + '" placeholder="Total number of reviews" />' +
473
+ '<span class="grw-quest grw-toggle" title="Click to help">?</span>' +
474
+ '<div class="grw-quest-help">Google return only 5 most helpful reviews and does not return information about total number of reviews and you can type here it manually.</div>' +
475
+ '</div>'
476
+ : '' ) +
477
+ (conn.refresh != undefined ?
478
+ '<div class="grw-builder-option">' +
479
+ '<label>' +
480
+ '<input type="checkbox" name="refresh" ' + (conn.refresh ? 'checked' : '') + '> Refresh reviews' +
481
+ '</label>' +
482
+ '<span class="grw-quest grw-quest-top grw-toggle" title="Click to help">?</span>' +
483
+ '<div class="grw-quest-help">' +
484
+ (conn.platform == 'google' ? 'The plugin uses the Google Places API to get your reviews. <b>The API only returns the 5 most helpful reviews (it\'s a limitation of Google, not the plugin)</b>. This option calls the Places API once in 24 hours (to keep the plugin\'s free and avoid a Google Billing) to check for a new reviews and if there are, adds to the plugin. Thus slowly building up a database of reviews.<br><br>Also if you see the new reviews on Google map, but after some time it\'s not added to the plugin, it means that Google does not include these reviews to the API and the plugin can\'t get this.<br><br>If you need to get all reviews, please use <a href="https://richplugins.com/business-reviews-bundle-wordpress-plugin" target="_blank">the Business plugin</a> which uses a Google My Business API, but this GMB API is available only for verified Google business owner accounts.' : '') +
485
+ (conn.platform == 'yelp' ? 'The plugin uses the Yelp API to get your reviews. <b>The API only returns the 3 most helpful reviews without sorting possibility.</b> When Yelp changes the 3 most helpful the plugin will automatically add the new one to your database. Thus slowly building up a database of reviews.' : '') +
486
+ '</div>' +
487
+ '</div>'
488
+ : '' ) +
489
+ '<div class="grw-builder-option">' +
490
+ '<button class="grw-connect-delete">Delete business</button>' +
491
+ '</div>' +
492
+ '</div>';
493
+ }
494
+
495
+ function grw_serialize_connections() {
496
+
497
+ var connections = [],
498
+ connections_el = document.querySelectorAll('.grw-connection');
499
+
500
+ for (var i in connections_el) {
501
+ if (Object.prototype.hasOwnProperty.call(connections_el, i)) {
502
+
503
+ var select_el = connections_el[i].querySelector('.grw-connect-select');
504
+ if (select_el && !grw_is_hidden(select_el) && !select_el.checked) {
505
+ continue;
506
+ }
507
+
508
+ var connection = {},
509
+ lang = connections_el[i].getAttribute('data-lang'),
510
+ platform = connections_el[i].getAttribute('data-platform'),
511
+ inputs = connections_el[i].querySelectorAll('input');
512
+
513
+ //connections[platform] = connections[platform] || [];
514
+
515
+ if (lang != undefined) {
516
+ connection.lang = lang;
517
+ }
518
+
519
+ for (var j in inputs) {
520
+ if (Object.prototype.hasOwnProperty.call(inputs, j)) {
521
+ var input = inputs[j],
522
+ name = input.getAttribute('name');
523
+
524
+ if (!name) continue;
525
+
526
+ if (input.className == 'grw-connect-prop') {
527
+ connection.props = connection.props || {};
528
+ connection.props[name] = input.value;
529
+ } else {
530
+ connection[name] = (input.type == 'checkbox' ? input.checked : input.value);
531
+ }
532
+ }
533
+ }
534
+ connection.platform = platform;
535
+ connections.push(connection);
536
+ }
537
+ }
538
+
539
+ var options = {},
540
+ options_el = document.querySelector('.grw-connect-options').querySelectorAll('input[name],select,textarea');
541
+
542
+ for (var o in options_el) {
543
+ if (Object.prototype.hasOwnProperty.call(options_el, o)) {
544
+ var input = options_el[o],
545
+ name = input.getAttribute('name');
546
+
547
+ if (input.type == 'checkbox') {
548
+ options[name] = input.checked;
549
+ } else if (input.value != undefined) {
550
+ options[name] = (input.type == 'textarea' || name == 'word_filter' || name == 'word_exclude' ? encodeURIComponent(input.value) : input.value);
551
+ }
552
+ }
553
+ }
554
+
555
+ if (GRW_VARS.wordpress) {
556
+ document.getElementById('grw-builder-connection').value = JSON.stringify({connections: connections, options: options});
557
+ } else {
558
+ document.getElementById('grw-builder-connections').value = JSON.stringify(connections);
559
+ document.getElementById('grw-builder-options').value = JSON.stringify(options);
560
+ }
561
+ }
562
+
563
+ function grw_deserialize_connections($, el, connections, options) {
564
+ if (GRW_VARS.wordpress) {
565
+ options = connections.options;
566
+ if (Array.isArray(connections.connections)) {
567
+ connections = connections.connections;
568
+ } else {
569
+ var temp_conns = [];
570
+ if (Array.isArray(connections.google)) {
571
+ for (var c = 0; c < connections.google.length; c++) {
572
+ connections.google[c].platform = 'google';
573
+ }
574
+ temp_conns = temp_conns.concat(connections.google);
575
+ }
576
+ if (Array.isArray(connections.facebook)) {
577
+ for (var c = 0; c < connections.facebook.length; c++) {
578
+ connections.facebook[c].platform = 'facebook';
579
+ }
580
+ temp_conns = temp_conns.concat(connections.facebook);
581
+ }
582
+ if (Array.isArray(connections.yelp)) {
583
+ for (var c = 0; c < connections.yelp.length; c++) {
584
+ connections.yelp[c].platform = 'yelp';
585
+ }
586
+ temp_conns = temp_conns.concat(connections.yelp);
587
+ }
588
+ connections = temp_conns;
589
+ }
590
+ } else {
591
+ connections = JSON.parse(connections);
592
+ options = JSON.parse(options);
593
+ }
594
+
595
+ for (var i = 0; i < connections.length; i++) {
596
+ grw_connection_add($, el.querySelector('.grw-builder-platforms'), connections[i], true);
597
+ }
598
+
599
+ for (var opt in options) {
600
+ if (Object.prototype.hasOwnProperty.call(options, opt)) {
601
+ var control = el.querySelector('input[name="' + opt + '"],select[name="' + opt + '"],textarea[name="' + opt + '"]');
602
+ if (control) {
603
+ var name = control.getAttribute('name');
604
+ if (typeof(options[opt]) === 'boolean') {
605
+ control.checked = options[opt];
606
+ } else {
607
+ control.value = (control.type == 'textarea' || name == 'word_filter' || name == 'word_exclude' ? decodeURIComponent(options[opt]) : options[opt]);
608
+ if (opt.indexOf('_photo') > -1 && control.value) {
609
+ control.parentNode.querySelector('img').src = control.value;
610
+ }
611
+ }
612
+ }
613
+ }
614
+ }
615
+ }
616
+
617
+ function grw_upload_photo(el, file_frame, cb) {
618
+ if (GRW_VARS.wordpress) {
619
+ if (file_frame) {
620
+ file_frame.open();
621
+ return;
622
+ }
623
+
624
+ file_frame = wp.media.frames.file_frame = wp.media({
625
+ title: jQuery(this).data('uploader_title'),
626
+ button: {text: jQuery(this).data('uploader_button_text')},
627
+ multiple: false
628
+ });
629
+
630
+ file_frame.on('select', function() {
631
+ var attachment = file_frame.state().get('selection').first().toJSON();
632
+ grw_change_photo(el, attachment.url);
633
+ cb && cb(attachment.url);
634
+ });
635
+ file_frame.open();
636
+ } else {
637
+ el.querySelector('input[type="file"]').click();
638
+ return false;
639
+ }
640
+ }
641
+
642
+ function grw_upload_image(el, files) {
643
+ var formData = new FormData();
644
+ for (var i = 0, file; file = files[i]; ++i) {
645
+ formData.append('file', file);
646
+ }
647
+
648
+ var handler = this;
649
+
650
+ if (!this.xhr) {
651
+ this.xhr = new XMLHttpRequest();
652
+ }
653
+ this.xhr.open('POST', 'https://media.cackle.me/upload2', true);
654
+ this.xhr.onload = function(e) {
655
+ if (4 === handler.xhr.readyState) {
656
+ if (200 === handler.xhr.status && handler.xhr.responseText.length > 0) {
657
+ var img = 'https://media.cackle.me/' + handler.xhr.responseText;
658
+ grw_change_photo(el, img);
659
+ }
660
+ }
661
+ };
662
+ this.xhr.send(formData);
663
+ }
664
+
665
+ function grw_change_photo(el, photo_url) {
666
+ var place_photo_hidden = jQuery('.grw-connect-photo-hidden', el),
667
+ place_photo_img = jQuery('.grw-connect-photo', el);
668
+
669
+ place_photo_hidden.val(photo_url);
670
+ place_photo_img.attr('src', photo_url);
671
+ place_photo_img.show();
672
+
673
+ grw_serialize_connections();
674
+ }
675
+
676
+ function grw_popup(url, width, height, cb) {
677
+ var top = top || (screen.height/2)-(height/2),
678
+ left = left || (screen.width/2)-(width/2),
679
+ win = window.open(url, '', 'location=1,status=1,resizable=yes,width='+width+',height='+height+',top='+top+',left='+left);
680
+ function check() {
681
+ if (!win || win.closed != false) {
682
+ cb();
683
+ } else {
684
+ setTimeout(check, 100);
685
+ }
686
+ }
687
+ setTimeout(check, 100);
688
+ }
689
+
690
+ function grw_randstr(len) {
691
+ var result = '',
692
+ chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
693
+ charsLen = chars.length;
694
+ for ( var i = 0; i < len; i++ ) {
695
+ result += chars.charAt(Math.floor(Math.random() * charsLen));
696
+ }
697
+ return result;
698
+ }
699
+
700
+ function grw_is_hidden(el) {
701
+ return el.offsetParent === null;
702
+ }
703
+
704
+ function grw_capitalize(str) {
705
+ return str.charAt(0).toUpperCase() + str.slice(1);
706
+ }
{static → assets}/js/grw-finder.js RENAMED
File without changes
{static → assets}/js/rplg.js RENAMED
File without changes
{static → assets}/js/wpac-time.js RENAMED
File without changes
{static → assets}/js/wpac.js RENAMED
File without changes
autoloader.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!defined('ABSPATH')) {
4
+ exit;
5
+ }
6
+
7
+ spl_autoload_register(function ($filename) {
8
+
9
+ $file_path = explode('\\', $filename);
10
+
11
+ if (isset($file_path[count($file_path) - 1 ])) {
12
+ $class_file = strtolower(
13
+ $file_path[count($file_path) - 1]
14
+ );
15
+
16
+ $class_file = str_ireplace('_', '-', $class_file);
17
+ $class_file = "class-$class_file.php";
18
+ }
19
+
20
+ $fully_qualified_path = trailingslashit(
21
+ dirname(__FILE__)
22
+ );
23
+
24
+ for ($i = 1; $i < count($file_path) - 1; $i ++) {
25
+ $dir = strtolower($file_path[$i]);
26
+ $dir = str_ireplace('_', '-', $dir);
27
+ $fully_qualified_path .= trailingslashit($dir);
28
+ }
29
+ $fully_qualified_path .= $class_file;
30
+
31
+ if (file_exists($fully_qualified_path)) {
32
+ include_once($fully_qualified_path);
33
+ }
34
+ });
grw-finder.php DELETED
@@ -1,69 +0,0 @@
1
- <div class="form-group">
2
- <h4><?php echo __('Enter Place ID of your Google location. If you don\'t know this, you can simply find it by <a href="' . admin_url('options-general.php?page=grw&grw_tab=fig') . '" target="_blank">this instruction</a>.', 'grw'); ?></h4>
3
- <input type="text" class="grw-place-id" value="" placeholder="Place ID" />
4
- <small class="grw-error"></small>
5
- </div>
6
-
7
- <div class="form-group">
8
- <select class="grw-lang">
9
- <option value=""><?php echo __('Choose language before connecting', 'grw'); ?></option>
10
- <option value="ar">Arabic</option>
11
- <option value="bg">Bulgarian</option>
12
- <option value="bn">Bengali</option>
13
- <option value="ca">Catalan</option>
14
- <option value="cs">Czech</option>
15
- <option value="da">Danish</option>
16
- <option value="de">German</option>
17
- <option value="el">Greek</option>
18
- <option value="en">English</option>
19
- <!--option value="en-AU">English (Australian)</option>
20
- <option value="en-GB">English (Great Britain)</option-->
21
- <option value="es">Spanish</option>
22
- <option value="eu">Basque</option>
23
- <option value="eu">Basque</option>
24
- <option value="fa">Farsi</option>
25
- <option value="fi">Finnish</option>
26
- <option value="fil">Filipino</option>
27
- <option value="fr">French</option>
28
- <option value="gl">Galician</option>
29
- <option value="gu">Gujarati</option>
30
- <option value="hi">Hindi</option>
31
- <option value="hr">Croatian</option>
32
- <option value="hu">Hungarian</option>
33
- <option value="id">Indonesian</option>
34
- <option value="it">Italian</option>
35
- <option value="iw">Hebrew</option>
36
- <option value="ja">Japanese</option>
37
- <option value="kn">Kannada</option>
38
- <option value="ko">Korean</option>
39
- <option value="lt">Lithuanian</option>
40
- <option value="lv">Latvian</option>
41
- <option value="ml">Malayalam</option>
42
- <option value="mr">Marathi</option>
43
- <option value="nl">Dutch</option>
44
- <option value="no">Norwegian</option>
45
- <option value="pl">Polish</option>
46
- <option value="pt">Portuguese</option>
47
- <option value="pt-BR">Portuguese (Brazil)</option>
48
- <option value="pt-PT">Portuguese (Portugal)</option>
49
- <option value="ro">Romanian</option>
50
- <option value="ru">Russian</option>
51
- <option value="sk">Slovak</option>
52
- <option value="sl">Slovenian</option>
53
- <option value="sr">Serbian</option>
54
- <option value="sv">Swedish</option>
55
- <option value="ta">Tamil</option>
56
- <option value="te">Telugu</option>
57
- <option value="th">Thai</option>
58
- <option value="tl">Tagalog</option>
59
- <option value="tr">Turkish</option>
60
- <option value="uk">Ukrainian</option>
61
- <option value="vi">Vietnamese</option>
62
- <option value="zh-CN">Chinese (Simplified)</option>
63
- <option value="zh-TW">Chinese (Traditional)</option>
64
- </select>
65
- </div>
66
-
67
- <div class="form-group">
68
- <button class="grw-connect-btn btn btn-block btn-primary"><?php echo __('Connect Google', 'grw'); ?></button>
69
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
grw-options.php DELETED
@@ -1,140 +0,0 @@
1
- <?php global $wp_version; if (version_compare($wp_version, '3.5', '>=')) { wp_enqueue_media(); ?>
2
- <div class="form-group">
3
- <img id="<?php echo $this->get_field_id('place_photo_img'); ?>" src="<?php echo $place_photo; ?>" alt="<?php echo $place_name; ?>" class="grw-place-photo-img" style="display:<?php if ($place_photo) { ?>inline-block<?php } else { ?>none<?php } ?>;width:32px;height:32px;border-radius:50%;">
4
- <a id="<?php echo $this->get_field_id('place_photo_btn'); ?>" href="#" class="grw-place-photo-btn"><?php echo __('Change Place photo', 'grw'); ?></a>
5
- <input type="hidden" id="<?php echo $this->get_field_id('place_photo'); ?>" name="<?php echo $this->get_field_name('place_photo'); ?>" value="<?php echo $place_photo; ?>" class="grw-place-photo" tabindex="2"/>
6
- </div>
7
- <?php } ?>
8
-
9
- <div class="form-group">
10
- <input type="text" id="<?php echo $this->get_field_id('place_name'); ?>" name="<?php echo $this->get_field_name('place_name'); ?>" value="<?php echo $place_name; ?>" class="grw-google-place-name" placeholder="<?php echo __('Google Place Name', 'grw'); ?>" readonly />
11
- </div>
12
-
13
- <div class="form-group">
14
- <input type="text" id="<?php echo $this->get_field_id('place_id'); ?>" name="<?php echo $this->get_field_name('place_id'); ?>" value="<?php echo $place_id; ?>" class="grw-google-place-id" placeholder="<?php echo __('Google Place ID', 'grw'); ?>" readonly />
15
- </div>
16
-
17
- <div class="form-group">
18
- <input type="text" id="<?php echo $this->get_field_id('reviews_lang'); ?>" name="<?php echo $this->get_field_name('reviews_lang'); ?>" value="<?php echo $reviews_lang; ?>" class="grw-place-lang" placeholder="<?php echo __('Language', 'grw'); ?>" readonly />
19
- </div>
20
-
21
- <?php if (isset($title)) { ?>
22
- <div class="form-group">
23
- <label><?php echo __('Title', 'grw'); ?></label>
24
- <input type="text" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" value="<?php echo $title; ?>"/>
25
- </div>
26
- <?php } ?>
27
-
28
- <div class="form-group">
29
- <label><?php echo __('Pagination', 'grw'); ?></label>
30
- <input type="text" id="<?php echo $this->get_field_id('pagination'); ?>" name="<?php echo $this->get_field_name('pagination'); ?>" value="<?php echo $pagination; ?>"/>
31
- </div>
32
-
33
- <div class="form-group">
34
- <label><?php echo __('Characters before \'read more\' link', 'grw'); ?></label>
35
- <input type="text" id="<?php echo $this->get_field_id('text_size'); ?>" name="<?php echo $this->get_field_name('text_size'); ?>" value="<?php echo $text_size; ?>"/>
36
- </div>
37
-
38
- <div class="form-group">
39
- <label for="<?php echo $this->get_field_id('max_width'); ?>"><?php echo __('Widget width', 'grw'); ?></label>
40
- <input id="<?php echo $this->get_field_id('max_width'); ?>" name="<?php echo $this->get_field_name('max_width'); ?>" value="<?php echo $max_width; ?>" type="text" />
41
- </div>
42
-
43
- <div class="form-group">
44
- <label for="<?php echo $this->get_field_id('max_height'); ?>"><?php echo __('Widget height', 'grw'); ?></label>
45
- <input id="<?php echo $this->get_field_id('max_height'); ?>" name="<?php echo $this->get_field_name('max_height'); ?>" value="<?php echo $max_height; ?>" type="text" />
46
- </div>
47
-
48
- <div class="form-group">
49
- <label>
50
- <input id="<?php echo $this->get_field_id('refresh_reviews'); ?>" name="<?php echo $this->get_field_name('refresh_reviews'); ?>" type="checkbox" value="1" <?php checked('1', $refresh_reviews); ?>/>
51
- <?php echo __('Refresh reviews', 'grw'); ?>
52
- <span class="rplg-quest rplg-toggle" title="Click to help">?</span>
53
- <div style="display:none">
54
- The plugin uses the Google Places API to get your reviews. <b>The API only returns the 5 most helpful reviews (it's a limitation of Google, not the plugin)</b>. This option calls the Places API once in three days (to avoid a Google Billing) to check for a new reviews and if there are, adds to the plugin.<br><br>Also if you see the new reviews on Google map, but after some time it's not added to the plugin, it means that Google does not include these reviews to the API and the plugin can't get this.<br><br>If you need to get all reviews, please use <a href="https://richplugins.com/business-reviews-bundle-wordpress-plugin" target="_blank">the Business plugin</a> which uses a Google My Business API, but this GMB API is available only for verified Google business owner accounts.
55
- </div>
56
- </label>
57
- </div>
58
-
59
- <div class="form-group">
60
- <label>
61
- <input id="<?php echo $this->get_field_id('hide_based_on'); ?>" name="<?php echo $this->get_field_name('hide_based_on'); ?>" type="checkbox" value="1" <?php checked('1', $hide_based_on); ?>/>
62
- <?php echo __('Hide \'Based on ... reviews\'', 'grw'); ?>
63
- </label>
64
- </div>
65
-
66
- <div class="form-group">
67
- <label>
68
- <input id="<?php echo $this->get_field_id('hide_reviews'); ?>" name="<?php echo $this->get_field_name('hide_reviews'); ?>" type="checkbox" value="1" <?php checked('1', $hide_reviews); ?>/>
69
- <?php echo __('Hide reviews, leave only rating header', 'grw'); ?>
70
- </label>
71
- </div>
72
-
73
- <div class="form-group">
74
- <label>
75
- <input id="<?php echo $this->get_field_id('centered'); ?>" name="<?php echo $this->get_field_name('centered'); ?>" type="checkbox" value="1" <?php checked('1', $centered); ?>/>
76
- <?php echo __('Place by center (only if Width is set)', 'grw'); ?>
77
- </label>
78
- </div>
79
-
80
- <div class="form-group">
81
- <label>
82
- <input id="<?php echo $this->get_field_id('dark_theme'); ?>" name="<?php echo $this->get_field_name('dark_theme'); ?>" type="checkbox" value="1" <?php checked('1', $dark_theme); ?>/>
83
- <?php echo __('Dark background', 'grw'); ?>
84
- </label>
85
- </div>
86
-
87
- <div class="rplg-options-toggle rplg-toggle"><?php echo __('Advance Options', 'grw'); ?></div>
88
- <div class="rplg-options" style="display:none">
89
- <div class="form-group">
90
- <label>
91
- <input id="<?php echo $this->get_field_id('lazy_load_img'); ?>" name="<?php echo $this->get_field_name('lazy_load_img'); ?>" type="checkbox" value="1" <?php checked('1', $lazy_load_img); ?>/>
92
- <?php echo __('Lazy load images', 'grw'); ?>
93
- </label>
94
- </div>
95
-
96
- <div class="form-group">
97
- <label>
98
- <input id="<?php echo $this->get_field_id('reduce_avatars_size'); ?>" name="<?php echo $this->get_field_name('reduce_avatars_size'); ?>" type="checkbox" value="1" <?php checked('1', $reduce_avatars_size); ?>/>
99
- <?php echo __('Reduce avatars size', 'grw'); ?>
100
- <span class="rplg-quest rplg-toggle" title="Click to help">?</span>
101
- <div style="display:none">
102
- By default the Google Places API returns the reviewer's avatars of 128px in size, this option reduces the size to 50px.
103
- </div>
104
- </label>
105
- </div>
106
-
107
- <div class="form-group">
108
- <label>
109
- <input id="<?php echo $this->get_field_id('def_reviews_link'); ?>" name="<?php echo $this->get_field_name('def_reviews_link'); ?>" type="checkbox" value="1" <?php checked('1', $def_reviews_link); ?>/>
110
- <?php echo __('Use default reviews link', 'grw'); ?>
111
- <span class="rplg-quest rplg-toggle" title="Click to help">?</span>
112
- <div style="display:none">
113
- If the direct link to all reviews <b>https://search.google.com/local/reviews?placeid=&lt;PLACE_ID&gt;</b> does not work with your Google place, please use this option to use the default reviews link to Google map.
114
- </div>
115
- </label>
116
- </div>
117
-
118
- <div class="form-group">
119
- <label>
120
- <input id="<?php echo $this->get_field_id('open_link'); ?>" name="<?php echo $this->get_field_name('open_link'); ?>" type="checkbox" value="1" <?php checked('1', $open_link); ?>/>
121
- <?php echo __('Open links in new Window', 'grw'); ?>
122
- </label>
123
- </div>
124
-
125
- <div class="form-group">
126
- <label>
127
- <input id="<?php echo $this->get_field_id('nofollow_link'); ?>" name="<?php echo $this->get_field_name('nofollow_link'); ?>" type="checkbox" value="1" <?php checked('1', $nofollow_link); ?>/>
128
- <?php echo __('Use no follow links', 'grw'); ?>
129
- </label>
130
- </div>
131
- </div>
132
-
133
- <div class="form-group">
134
- <div class="rplg-pro">
135
- <?php echo __('Try more features in the Business version: ', 'grw'); ?>
136
- <a href="https://richplugins.com/business-reviews-bundle-wordpress-plugin" target="_blank">
137
- <?php echo __('Upgrade to Business', 'grw'); ?>
138
- </a>
139
- </div>
140
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
grw-reviews-helper.php DELETED
@@ -1,149 +0,0 @@
1
- <?php
2
- function grw_place($rating, $place, $place_img, $reviews, $dark_theme, $hide_based_on, $show_powered = true) {
3
- ?>
4
- <div class="wp-google-left">
5
- <img src="<?php echo $place_img; ?>" alt="<?php echo $place->name; ?>" width="50" height="50" title="<?php echo $place->name; ?>">
6
- </div>
7
- <div class="wp-google-right">
8
- <div class="wp-google-name">
9
- <?php $place_name_content = '<span>' . $place->name . '</span>';
10
- echo grw_anchor($place->url, '', $place_name_content, true, true); ?>
11
- </div>
12
- <div>
13
- <span class="wp-google-rating"><?php echo $rating; ?></span>
14
- <span class="wp-google-stars"><?php grw_stars($rating); ?></span>
15
- </div>
16
- <?php if (!$hide_based_on && isset($place->review_count)) { ?>
17
- <div class="wp-google-powered"><?php echo vsprintf(__('Based on %s reviews', 'grw'), grw_array($place->review_count)); ?></div>
18
- <?php } ?>
19
- <?php if ($show_powered) { ?>
20
- <div class="wp-google-powered">
21
- <img src="<?php echo GRW_PLUGIN_URL; ?>/static/img/powered_by_google_on_<?php if ($dark_theme) { ?>non_<?php } ?>white.png" alt="powered by Google" width="144" height="18" title="powered by Google">
22
- </div>
23
- <?php } ?>
24
- </div>
25
- <?php
26
- }
27
-
28
- function grw_place_reviews($place, $reviews, $place_id, $text_size, $pagination, $reduce_avatars_size, $open_link, $nofollow_link, $lazy_load_img, $def_reviews_link, $is_admin = false) {
29
- ?>
30
- <div class="wp-google-reviews">
31
- <?php
32
- $hr = false;
33
- if (count($reviews) > 0) {
34
- $i = 0;
35
- foreach ($reviews as $review) {
36
- if ($pagination > 0 && $pagination <= $i++) {
37
- $hr = true;
38
- }
39
- ?>
40
- <div class="wp-google-review<?php if ($hr) { echo ' wp-google-hide'; } if ($is_admin && $review->hide != '') { echo ' wp-review-hidden'; } ?>">
41
- <div class="wp-google-left">
42
- <?php
43
- $default_avatar = GRW_GOOGLE_AVATAR;
44
- if (strlen($review->profile_photo_url) > 0) {
45
- $profile_photo_url = $review->profile_photo_url;
46
- } else {
47
- $profile_photo_url = $default_avatar;
48
- }
49
- if ($reduce_avatars_size) {
50
- $profile_photo_url = str_replace('s128', 's50', $profile_photo_url);
51
- $default_avatar = str_replace('s128', 's50', $default_avatar);
52
- }
53
- grw_image($profile_photo_url, $review->author_name, $lazy_load_img, $default_avatar);
54
- ?>
55
- </div>
56
- <div class="wp-google-right">
57
- <?php
58
- if (strlen($review->author_url) > 0) {
59
- grw_anchor($review->author_url, 'wp-google-name', $review->author_name, $open_link, $nofollow_link);
60
- } else {
61
- if (strlen($review->author_name) > 0) {
62
- $author_name = $review->author_name;
63
- } else {
64
- $author_name = __('Google User', 'grw');
65
- }
66
- ?><div class="wp-google-name"><?php echo $author_name; ?></div><?php
67
- }
68
- ?>
69
- <div class="wp-google-time" data-time="<?php echo $review->time; ?>"><?php echo gmdate("H:i d M y", $review->time); ?></div>
70
- <div class="wp-google-feedback">
71
- <span class="wp-google-stars"><?php echo grw_stars($review->rating); ?></span>
72
- <span class="wp-google-text"><?php echo grw_trim_text($review->text, $text_size); ?></span>
73
- </div>
74
- <?php if ($is_admin) {
75
- echo '<a href="#" class="wp-review-hide" data-id=' . $review->id . '>' . ($review->hide == '' ? 'Hide' : 'Show') . ' review</a>';
76
- } ?>
77
- </div>
78
- </div>
79
- <?php
80
- }
81
- }
82
- ?>
83
- </div>
84
- <?php if ($pagination > 0 && $hr) { ?>
85
- <a class="wp-google-url" href="#" onclick="return rplg_next_reviews.call(this, 'google', <?php echo $pagination; ?>);">
86
- <?php echo __('Next Reviews', 'grw'); ?>
87
- </a>
88
- <?php } else {
89
- $reviews_link = $def_reviews_link ? $place->url : 'https://search.google.com/local/reviews?placeid=' . $place_id;
90
- grw_anchor($reviews_link, 'wp-google-url', __('See All Reviews', 'grw'), true, true);
91
- }
92
- }
93
-
94
- function grw_stars($rating) {
95
- ?><span class="wp-stars"><?php
96
- foreach (array(1,2,3,4,5) as $val) {
97
- $score = $rating - $val;
98
- if ($score >= 0) {
99
- ?><span class="wp-star"><svg width="17" height="17" viewBox="0 0 1792 1792"><path d="M1728 647q0 22-26 48l-363 354 86 500q1 7 1 20 0 21-10.5 35.5t-30.5 14.5q-19 0-40-12l-449-236-449 236q-22 12-40 12-21 0-31.5-14.5t-10.5-35.5q0-6 2-20l86-500-364-354q-25-27-25-48 0-37 56-46l502-73 225-455q19-41 49-41t49 41l225 455 502 73q56 9 56 46z" fill="#e7711b"></path></svg></span><?php
100
- } else if ($score > -1 && $score < 0) {
101
- ?><span class="wp-star"><svg width="17" height="17" viewBox="0 0 1792 1792"><path d="M1250 957l257-250-356-52-66-10-30-60-159-322v963l59 31 318 168-60-355-12-66zm452-262l-363 354 86 500q5 33-6 51.5t-34 18.5q-17 0-40-12l-449-236-449 236q-23 12-40 12-23 0-34-18.5t-6-51.5l86-500-364-354q-32-32-23-59.5t54-34.5l502-73 225-455q20-41 49-41 28 0 49 41l225 455 502 73q45 7 54 34.5t-24 59.5z" fill="#e7711b"></path></svg></span><?php
102
- } else {
103
- ?><span class="wp-star"><svg width="17" height="17" viewBox="0 0 1792 1792"><path d="M1201 1004l306-297-422-62-189-382-189 382-422 62 306 297-73 421 378-199 377 199zm527-357q0 22-26 48l-363 354 86 500q1 7 1 20 0 50-41 50-19 0-40-12l-449-236-449 236q-22 12-40 12-21 0-31.5-14.5t-10.5-35.5q0-6 2-20l86-500-364-354q-25-27-25-48 0-37 56-46l502-73 225-455q19-41 49-41t49 41l225 455 502 73q56 9 56 46z" fill="#ccc"></path></svg></span><?php
104
- }
105
- }
106
- ?></span><?php
107
- }
108
-
109
- function grw_anchor($url, $class, $text, $open_link, $nofollow_link) {
110
- echo '<a href="' . $url . '"' . ($class ? ' class="' . $class . '"' : '') . ($open_link ? ' target="_blank"' : '') . ' rel="' . ($nofollow_link ? 'nofollow ' : '') . 'noopener">' . $text . '</a>';
111
- }
112
-
113
- function grw_image($src, $alt, $lazy, $def_ava = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', $atts = '') {
114
- ?><img <?php if ($lazy) { ?>src="<?php echo $def_ava; ?>" data-<?php } ?>src="<?php echo $src; ?>" class="rplg-review-avatar<?php if ($lazy) { ?> rplg-blazy<?php } ?>" alt="<?php echo $alt; ?>" width="50" height="50" title="<?php echo $alt; ?>" onerror="if(this.src!='<?php echo $def_ava; ?>')this.src='<?php echo $def_ava; ?>';" <?php echo $atts; ?>><?php
115
- }
116
-
117
- function grw_trim_text($text, $size) {
118
- if ($size > 0 && grw_strlen($text) > $size) {
119
- $sub_text = grw_substr($text, 0, $size);
120
- $idx = grw_strrpos($sub_text, ' ') + 1;
121
-
122
- if ($idx < 1 || $size - $idx > ($size / 2)) {
123
- $idx = $size;
124
- }
125
- if ($idx > 0) {
126
- $visible_text = grw_substr($text, 0, $idx - 1);
127
- $invisible_text = grw_substr($text, $idx - 1, grw_strlen($text));
128
- }
129
- echo $visible_text;
130
- if (grw_strlen($invisible_text) > 0) {
131
- ?><span>... </span><span class="wp-more"><?php echo $invisible_text; ?></span><span class="wp-more-toggle"><?php echo __('read more', 'grw'); ?></span><?php
132
- }
133
- } else {
134
- echo $text;
135
- }
136
- }
137
-
138
- function grw_strlen($str) {
139
- return function_exists('mb_strlen') ? mb_strlen($str, 'UTF-8') : strlen($str);
140
- }
141
-
142
- function grw_strrpos($haystack, $needle, $offset = 0) {
143
- return function_exists('mb_strrpos') ? mb_strrpos($haystack, $needle, $offset, 'UTF-8') : strrpos($haystack, $needle, $offset);
144
- }
145
-
146
- function grw_substr($str, $start, $length = NULL) {
147
- return function_exists('mb_substr') ? mb_substr($str, $start, $length, 'UTF-8') : substr($str, $start, $length);
148
- }
149
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
grw-reviews.php DELETED
@@ -1,127 +0,0 @@
1
- <?php
2
- wp_register_script('rplg_js', plugins_url('/static/js/rplg.js', __FILE__));
3
- wp_enqueue_script('rplg_js', plugins_url('/static/js/rplg.js', __FILE__));
4
-
5
- if ($lazy_load_img) {
6
- wp_register_script('rplg_blazy', plugins_url('/static/js/blazy.min.js', __FILE__));
7
- wp_enqueue_script('rplg_blazy', plugins_url('/static/js/blazy.min.js', __FILE__));
8
- }
9
-
10
- include_once(dirname(__FILE__) . '/grw-reviews-helper.php');
11
-
12
- $reviews_where = ' AND hide = \'\'';
13
- if (strlen($reviews_lang) > 0) {
14
- $reviews_where = $reviews_where . ' AND language = \'' . $reviews_lang . '\'';
15
- }
16
-
17
- $place = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . $wpdb->prefix . "grp_google_place WHERE place_id = %s", $place_id));
18
- $reviews = $wpdb->get_results($wpdb->prepare("SELECT * FROM " . $wpdb->prefix . "grp_google_review WHERE google_place_id = %d" . $reviews_where . " ORDER BY time DESC", $place->id));
19
-
20
- $rating = 0;
21
- if ($place->rating > 0) {
22
- $rating = $place->rating;
23
- } else if (count($reviews) > 0) {
24
- foreach ($reviews as $review) {
25
- $rating = $rating + $review->rating;
26
- }
27
- $rating = round($rating / count($reviews), 1);
28
- }
29
- $rating = number_format((float)$rating, 1, '.', '');
30
- $place_img = strlen($place_photo) > 0 ? $place_photo : (strlen($place->photo) > 0 ? $place->photo : $place->icon);
31
-
32
- if (is_numeric($max_width)) {
33
- $max_width = $max_width . 'px';
34
- }
35
- if (is_numeric($max_height)) {
36
- $max_height = $max_height . 'px';
37
- }
38
-
39
- $style = '';
40
- if (isset($max_width) && strlen($max_width) > 0) {
41
- $style .= 'width:' . $max_width . '!important;';
42
- }
43
- if (isset($max_height) && strlen($max_height) > 0) {
44
- $style .= 'height:' . $max_height . '!important;overflow-y:auto!important;';
45
- }
46
- if ($centered) {
47
- $style .= 'margin:0 auto!important;';
48
- }
49
-
50
- if ($refresh_reviews) {
51
- $schedule_step = 60 * 60 * 24;
52
- $args = array($place_id);
53
- if (strlen($reviews_lang) > 0) {
54
- array_push($args, $reviews_lang);
55
- }
56
- $schedule_cache_key = 'grw_refresh_reviews_' . join('_', $args);
57
- if (get_transient($schedule_cache_key) === false) {
58
- wp_schedule_single_event(time() + $schedule_step, 'grw_refresh_reviews', array($args));
59
- set_transient($schedule_cache_key, $schedule_cache_key, $schedule_step + 60 * 10);
60
- }
61
- }
62
-
63
- if ($view_mode == 'list' || $view_mode == '') { ?>
64
-
65
- <div class="wp-gr wpac"<?php if ($style) { ?> style="<?php echo $style;?>"<?php } ?>>
66
- <div class="wp-google-list<?php if ($dark_theme) { ?> wp-dark<?php } ?>">
67
- <div class="wp-google-place">
68
- <?php grw_place($rating, $place, $place_img, $reviews, $dark_theme, $hide_based_on); ?>
69
- </div>
70
- <?php if (!$hide_reviews) { ?>
71
- <div class="wp-google-content-inner">
72
- <?php grw_place_reviews($place, $reviews, $place_id, $text_size, $pagination, $reduce_avatars_size, $open_link, $nofollow_link, $lazy_load_img, $def_reviews_link); ?>
73
- </div>
74
- <?php } ?>
75
- </div>
76
- </div>
77
-
78
- <?php } else { ?>
79
-
80
- <div class="wp-gr wpac">
81
- <script type="text/javascript">
82
- function grw_badge_init(el) {
83
- var btn = el.querySelector('.wp-google-badge'),
84
- form = el.querySelector('.wp-google-form');
85
-
86
- var wpac = document.createElement('div');
87
- wpac.className = 'wp-gr wpac';
88
- wpac.appendChild(form);
89
- document.body.appendChild(wpac);
90
-
91
- btn.onclick = function() {
92
- form.style.display='block';
93
- };
94
- }
95
- </script>
96
- <div class="wp-google-badge<?php if ($view_mode == 'badge') { ?> wp-google-badge-fixed<?php } ?>">
97
- <div class="wp-google-border"></div>
98
- <div class="wp-google-badge-btn">
99
- <svg viewBox="0 0 512 512" height="44" width="44"><g fill="none" fill-rule="evenodd"><path d="M482.56 261.36c0-16.73-1.5-32.83-4.29-48.27H256v91.29h127.01c-5.47 29.5-22.1 54.49-47.09 71.23v59.21h76.27c44.63-41.09 70.37-101.59 70.37-173.46z" fill="#4285f4"/><path d="M256 492c63.72 0 117.14-21.13 156.19-57.18l-76.27-59.21c-21.13 14.16-48.17 22.53-79.92 22.53-61.47 0-113.49-41.51-132.05-97.3H45.1v61.15c38.83 77.13 118.64 130.01 210.9 130.01z" fill="#34a853"/><path d="M123.95 300.84c-4.72-14.16-7.4-29.29-7.4-44.84s2.68-30.68 7.4-44.84V150.01H45.1C29.12 181.87 20 217.92 20 256c0 38.08 9.12 74.13 25.1 105.99l78.85-61.15z" fill="#fbbc05"/><path d="M256 113.86c34.65 0 65.76 11.91 90.22 35.29l67.69-67.69C373.03 43.39 319.61 20 256 20c-92.25 0-172.07 52.89-210.9 130.01l78.85 61.15c18.56-55.78 70.59-97.3 132.05-97.3z" fill="#ea4335"/><path d="M20 20h472v472H20V20z"/></g></svg>
100
- <div class="wp-google-badge-score">
101
- <div><?php echo __('Google Rating', 'grw'); ?></div>
102
- <span class="wp-google-rating"><?php echo $rating; ?></span>
103
- <span class="wp-google-stars"><?php grw_stars($rating); ?></span>
104
- </div>
105
- </div>
106
- </div>
107
- <div class="wp-google-form" style="display:none">
108
- <div class="wp-google-head">
109
- <div class="wp-google-head-inner">
110
- <?php grw_place($rating, $place, $place_img, $reviews, $dark_theme, $hide_based_on, false); ?>
111
- </div>
112
- <button class="wp-google-close" type="button" onclick="this.parentNode.parentNode.style.display='none'">×</button>
113
- </div>
114
- <div class="wp-google-body"></div>
115
- <div class="wp-google-content">
116
- <div class="wp-google-content-inner">
117
- <?php grw_place_reviews($place, $reviews, $place_id, $text_size, $pagination, $reduce_avatars_size, $open_link, $nofollow_link, $lazy_load_img, $def_reviews_link); ?>
118
- </div>
119
- </div>
120
- <div class="wp-google-footer">
121
- <img src="<?php echo GRW_PLUGIN_URL; ?>/static/img/powered_by_google_on_<?php if ($dark_theme) { ?>non_<?php } ?>white.png" alt="powered by Google" width="144" height="18" title="powered by Google">
122
- </div>
123
- </div>
124
- <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="" onload="(function(el) { document.addEventListener('DOMContentLoaded', function() { grw_badge_init(el); }); })(this.parentNode);" style="display:none">
125
- </div>
126
-
127
- <?php } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
grw-setting.php DELETED
@@ -1,401 +0,0 @@
1
- <?php
2
-
3
- if (!current_user_can('manage_options')) {
4
- die('The account you\'re logged in to doesn\'t have permission to access this page.');
5
- }
6
-
7
- function grw_has_valid_nonce() {
8
- $nonce_actions = array('grw_reset', 'grw_settings', 'grw_active', 'grw_advance');
9
- $nonce_form_prefix = 'grw-form_nonce_';
10
- $nonce_action_prefix = 'grw-wpnonce_';
11
- foreach ($nonce_actions as $key => $value) {
12
- if (isset($_POST[$nonce_form_prefix.$value])) {
13
- check_admin_referer($nonce_action_prefix.$value, $nonce_form_prefix.$value);
14
- return true;
15
- }
16
- }
17
- return false;
18
- }
19
-
20
- function grw_debug() {
21
- global $wpdb;
22
- $places = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "grp_google_place");
23
- $places_error = $wpdb->last_error;
24
- $reviews = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "grp_google_review");
25
- $reviews_error = $wpdb->last_error; ?>
26
-
27
- DB Places: <?php echo print_r($places); ?>
28
-
29
- DB Places error: <?php echo $places_error; ?>
30
-
31
- DB Reviews: <?php echo print_r($reviews); ?>
32
-
33
- DB Reviews error: <?php echo $reviews_error;
34
- }
35
-
36
- if (!empty($_POST)) {
37
- $nonce_result_check = grw_has_valid_nonce();
38
- if ($nonce_result_check === false) {
39
- die('Unable to save changes. Make sure you are accessing this page from the Wordpress dashboard.');
40
- }
41
- }
42
-
43
- // Reset
44
- if (isset($_POST['reset_all'])) {
45
- grw_reset(isset($_POST['reset_db']));
46
- unset($_POST);
47
- ?>
48
- <div class="wrap">
49
- <h3><?php echo __('Google Reviews Widget Reset', 'grw'); ?></h3>
50
- <form method="POST" action="?page=grw">
51
- <?php wp_nonce_field('grw-wpnonce_grw_reset', 'grw-form_nonce_grw_reset'); ?>
52
- <p><?php echo __('Google Reviews Widget has been reset successfully.', 'grw') ?></p>
53
- <ul style="list-style: circle;padding-left:20px;">
54
- <li><?php echo __('Local settings for the plugin were removed.', 'grw') ?></li>
55
- </ul>
56
- <p>
57
- <?php echo __('If you wish to reinstall, you can do that now.', 'grw') ?>
58
- <a href="?page=grw">&nbsp;<?php echo __('Reinstall', 'grw') ?></a>
59
- </p>
60
- </form>
61
- </div>
62
- <?php
63
- die();
64
- }
65
-
66
- // Post fields that require verification.
67
- $valid_fields = array(
68
- 'grw_active' => array(
69
- 'key_name' => 'grw_active',
70
- 'values' => array('Disable', 'Enable')
71
- ));
72
-
73
- // Check POST fields and remove bad input.
74
- foreach ($valid_fields as $key) {
75
-
76
- if (isset($_POST[$key['key_name']]) ) {
77
-
78
- // SANITIZE first
79
- $_POST[$key['key_name']] = trim(sanitize_text_field($_POST[$key['key_name']]));
80
-
81
- // Validate
82
- if (isset($key['regexp']) && $key['regexp']) {
83
- if (!preg_match($key['regexp'], $_POST[$key['key_name']])) {
84
- unset($_POST[$key['key_name']]);
85
- }
86
-
87
- } else if (isset($key['type']) && $key['type'] == 'int') {
88
- if (!intval($_POST[$key['key_name']])) {
89
- unset($_POST[$key['key_name']]);
90
- }
91
-
92
- } else {
93
- $valid = false;
94
- $vals = $key['values'];
95
- foreach ($vals as $val) {
96
- if ($_POST[$key['key_name']] == $val) {
97
- $valid = true;
98
- }
99
- }
100
- if (!$valid) {
101
- unset($_POST[$key['key_name']]);
102
- }
103
- }
104
- }
105
- }
106
-
107
- if (isset($_POST['grw_active']) && isset($_GET['grw_active'])) {
108
- update_option('grw_active', ($_GET['grw_active'] == '1' ? '1' : '0'));
109
- }
110
-
111
- if (isset($_POST['grw_setting'])) {
112
- update_option('grw_google_api_key', trim($_POST['grw_google_api_key']));
113
- }
114
-
115
- if (isset($_POST['create_db'])) {
116
- grw_install_db();
117
- }
118
-
119
- if (isset($_POST['install'])) {
120
- grw_reset(true);
121
- grw_activate();
122
- }
123
-
124
- wp_register_style('rplg_setting_css', plugins_url('/static/css/rplg-setting.css', __FILE__));
125
- wp_enqueue_style('rplg_setting_css', plugins_url('/static/css/rplg-setting.css', __FILE__));
126
-
127
- wp_register_style('rplg_review_css', plugins_url('/static/css/google-review.css', __FILE__));
128
- wp_enqueue_style('rplg_review_css', plugins_url('/static/css/google-review.css', __FILE__));
129
-
130
- wp_enqueue_script('jquery');
131
-
132
- $tab = isset($_GET['grw_tab']) && strlen($_GET['grw_tab']) > 0 ? $_GET['grw_tab'] : 'about';
133
- $grw_enabled = get_option('grw_active') == '1';
134
- $grw_google_api_key = get_option('grw_google_api_key');
135
- ?>
136
-
137
- <span class="rplg-version"><?php echo vsprintf(__('Free Version: %s', 'grw'), grw_array(esc_html(GRW_VERSION))); ?></span>
138
-
139
- <div class="rplg-setting">
140
-
141
- <div class="rplg-page-title">
142
- <img src="<?php echo GRW_PLUGIN_URL . '/static/img/google.png'; ?>" alt="Google"> Reviews Widget
143
- </div>
144
-
145
- <div class="rplg-settings-workspace">
146
-
147
- <div data-nav-tabs="">
148
- <div class="nav-tab-wrapper">
149
- <a href="#about" class="nav-tab<?php if ($tab == 'about') { ?> nav-tab-active<?php } ?>"><?php echo __('About', 'grw'); ?></a>
150
- <a href="#setting" class="nav-tab<?php if ($tab == 'setting') { ?> nav-tab-active<?php } ?>"><?php echo __('Settings', 'grw'); ?></a>
151
- <a href="#shortcode" class="nav-tab<?php if ($tab == 'shortcode') { ?> nav-tab-active<?php } ?>"><?php echo __('Shortcode', 'grw'); ?></a>
152
- <a href="#reviews" class="nav-tab<?php if ($tab == 'reviews') { ?> nav-tab-active<?php } ?>"><?php echo __('Reviews', 'grw'); ?></a>
153
- <a href="#fig" class="nav-tab<?php if ($tab == 'fig') { ?> nav-tab-active<?php } ?>"><?php echo __('Full Installation Guide', 'grw'); ?></a>
154
- <a href="#support" class="nav-tab<?php if ($tab == 'support') { ?> nav-tab-active<?php } ?>"><?php echo __('Support', 'grw'); ?></a>
155
- <a href="#advance" class="nav-tab<?php if ($tab == 'advance') { ?> nav-tab-active<?php } ?>"><?php echo __('Advance', 'grw'); ?></a>
156
- </div>
157
-
158
- <div id="about" class="tab-content" style="display:<?php echo $tab == 'about' ? 'block' : 'none'?>;">
159
- <h3>Google Reviews Widget for WordPress</h3>
160
- <div class="rplg-flex-row">
161
- <div class="rplg-flex-col">
162
- <span>Google Reviews plugin is an easy and fast way to integrate Google business reviews right into your WordPress website. This plugin works instantly and keep all Google places and reviews in WordPress database thus it has no depend on external services.</span>
163
- <p style="font-size:20px;text-align:center"><b><u>Please read '<a href="<?php echo admin_url('options-general.php?page=grw&grw_tab=fig'); ?>">Full Installation Guide</a>' to completely understand how it works and set up the plugin</u></b>.</p>
164
- <p>Also you can find most common answers and solutions for most common questions and issues in next tabs.</p>
165
- <div class="rplg-alert rplg-alert-success">
166
- <strong>Try more features in the Business version</strong>: Merge Google, Facebook and Yelp reviews, Beautiful themes (Slider, Grid, Trust Badges), Shortcode support, Rich Snippets, Rating filter, Any sorting, Include/Exclude words filter, Hide/Show any elements, Priority support and many others.
167
- <a class="button-primary button" href="https://richplugins.com/business-reviews-bundle-wordpress-plugin" target="_blank" style="margin-left:10px">Upgrade to Business</a>
168
- </div>
169
- <br>
170
- <div class="rplg-socials">
171
- <div id="fb-root"></div>
172
- <script>(function(d, s, id) {
173
- var js, fjs = d.getElementsByTagName(s)[0];
174
- if (d.getElementById(id)) return;
175
- js = d.createElement(s); js.id = id;
176
- js.src = "//connect.facebook.net/en_EN/sdk.js#xfbml=1&version=v2.6&appId=1501100486852897";
177
- fjs.parentNode.insertBefore(js, fjs);
178
- }(document, 'script', 'facebook-jssdk'));</script>
179
- <div class="fb-like" data-href="https://richplugins.com/" data-layout="button_count" data-action="like" data-show-faces="true" data-share="false"></div>
180
- <a href="https://twitter.com/richplugins?ref_src=twsrc%5Etfw" class="twitter-follow-button" data-show-count="false">Follow @richplugins</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
181
- <div class="g-plusone" data-size="medium" data-annotation="inline" data-width="200" data-href="https://plus.google.com/101080686931597182099"></div>
182
- <script type="text/javascript">
183
- window.___gcfg = { lang: 'en-US' };
184
- (function () {
185
- var po = document.createElement('script');
186
- po.type = 'text/javascript';
187
- po.async = true;
188
- po.src = 'https://apis.google.com/js/plusone.js';
189
- var s = document.getElementsByTagName('script')[0];
190
- s.parentNode.insertBefore(po, s);
191
- })();
192
- </script>
193
- </div>
194
- </div>
195
- <div class="rplg-flex-col">
196
- <iframe width="100%" height="315" src="https://www.youtube.com/embed/KhcDgjxYrNs" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
197
- </div>
198
- </div>
199
- </div>
200
-
201
- <div id="setting" class="tab-content" style="display:<?php echo $tab == 'setting' ? 'block' : 'none'?>;">
202
- <h3>General Settings</h3>
203
- <form method="post" action="?page=grw&amp;grw_tab=setting&amp;grw_active=<?php echo (string)((int)($grw_enabled != true)); ?>">
204
- <div class="rplg-field">
205
- <div class="rplg-field-label">
206
- <label>The plugin is currently <b><?php echo $grw_enabled ? 'enabled' : 'disabled' ?></b></label>
207
- </div>
208
- <div class="wp-review-field-option">
209
- <?php wp_nonce_field('grw-wpnonce_grw_active', 'grw-form_nonce_grw_active'); ?>
210
- <input type="submit" name="grw_active" class="button" value="<?php echo $grw_enabled ? __('Disable', 'grw') : __('Enable', 'grw'); ?>" />
211
- </div>
212
- </div>
213
- </form>
214
- <form method="POST" action="?page=grw&amp;grw_tab=setting" enctype="multipart/form-data">
215
- <?php wp_nonce_field('grw-wpnonce_grw_settings', 'grw-form_nonce_grw_settings'); ?>
216
- <div class="rplg-field">
217
- <div class="rplg-field-label">
218
- <label>Google Places API key</label>
219
- </div>
220
- <div class="wp-review-field-option">
221
- <input type="text" id="grw_google_api_key" name="grw_google_api_key" class="regular-text" value="<?php echo esc_attr($grw_google_api_key); ?>">
222
- <div style="padding-top:15px">
223
- <input type="submit" value="Save" name="grw_setting" class="button" />
224
- </div>
225
- </div>
226
- </div>
227
- <div class="rplg-field">
228
- <div class="rplg-field-label">
229
- <label></label>
230
- </div>
231
- <div class="wp-review-field-option">
232
- <p>If you do not know how to create Google API key, please read: <a href="<?php echo admin_url('options-general.php?page=grw&grw_tab=fig'); ?>">Full Installation Guide</a></p>
233
- </div>
234
- </div>
235
- </form>
236
- </div>
237
-
238
- <div id="shortcode" class="tab-content" style="display:<?php echo $tab == 'shortcode' ? 'block' : 'none'?>;">
239
- <h3>Shortcode</h3>
240
- <div class="rplg-flex-row">
241
- <div class="rplg-flex-col3">
242
- <div class="widget-content">
243
- <?php $grw_widget = new Goog_Reviews_Widget; $grw_widget->form(array()); ?>
244
- </div>
245
- </div>
246
- <div class="rplg-flex-col6">
247
- <div class="shortcode-content">
248
- <textarea id="rplg_shortcode" style="display:block;width:100%;height:200px;padding:10px" onclick="if (rplg_shortcode.value.indexOf('[grw')==0){window.rplg_shortcode.select();document.execCommand('copy');window.rplg_shortcode_msg.innerHTML='Shortcode copied, please paste it to the page content';}" readonly>Connect Google place to show the shortcode</textarea>
249
- <p id="rplg_shortcode_msg">After shortcode created, click by it to copy</p>
250
- </div>
251
- </div>
252
- </div>
253
- </div>
254
-
255
- <div id="reviews" class="tab-content" style="display:<?php echo $tab == 'reviews' ? 'block' : 'none'?>;">
256
- <h3>Reviews</h3>
257
- <div class="wp-gr">
258
- <div class="rplg-flex-row">
259
- <div class="rplg-flex-col3">
260
- <div class="wp-google-list">
261
- <?php
262
- global $wpdb;
263
- include_once(dirname(__FILE__) . '/grw-reviews-helper.php');
264
- $places = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "grp_google_place");
265
- foreach ($places as $place) {
266
- ?><div class="wp-google-place" data-id="<?php echo $place->id; ?>"><?php
267
- grw_place($place->rating, $place, $place->photo, array(), false, true, false);
268
- ?></div><?php
269
- }
270
- ?>
271
- </div>
272
- </div>
273
- <div class="rplg-flex-col6">
274
- <div class="wp-google-content-inner"></div>
275
- </div>
276
- </div>
277
- </div>
278
- </div>
279
-
280
- <div id="fig" class="tab-content" style="display:<?php echo $tab == 'fig' ? 'block' : 'none'?>;">
281
- <h3>How to connect Google reviews</h3>
282
- <?php include_once(dirname(__FILE__) . '/grw-setting-fig.php'); ?>
283
- </div>
284
-
285
- <div id="support" class="tab-content" style="display:<?php echo $tab == 'support' ? 'block' : 'none'?>;">
286
- <h3>Most Common Questions</h3>
287
- <?php include_once(dirname(__FILE__) . '/grw-setting-support.php'); ?>
288
- </div>
289
-
290
- <div id="advance" class="tab-content" style="display:<?php echo $tab == 'advance' ? 'block' : 'none'?>;">
291
- <h3>Advance Options</h3>
292
- <form method="post" action="?page=grw&amp;grw_tab=advance">
293
- <?php wp_nonce_field('grw-wpnonce_grw_advance', 'grw-form_nonce_grw_advance'); ?>
294
- <div class="rplg-field">
295
- <div class="rplg-field-label">
296
- <label>Re-create the database tables of the plugin (service option)</label>
297
- </div>
298
- <div class="wp-review-field-option">
299
- <input type="submit" value="Re-create Database" name="create_db" onclick="return confirm('Are you sure you want to re-create database tables?')" class="button" />
300
- </div>
301
- </div>
302
- <div class="rplg-field">
303
- <div class="rplg-field-label">
304
- <label><b>Please be careful</b>: this removes all settings, reviews and install the plugin from scratch</label>
305
- </div>
306
- <div class="wp-review-field-option">
307
- <input type="submit" value="Install from scratch" name="install" onclick="return confirm('It will delete all current reviews, are you sure you want to install the plugin from scratch?')" class="button" />
308
- </div>
309
- </div>
310
- <div class="rplg-field">
311
- <div class="rplg-field-label">
312
- <label><b>Please be careful</b>: this removes all plugin-specific settings (and reviews if 'Remove all reviews' checkbox is set)</label>
313
- </div>
314
- <div class="wp-review-field-option">
315
- <input type="submit" value="Delete the plugin" name="reset_all" onclick="return confirm('Are you sure you want to reset all plugin data' + (window.reset_db.checked ? ' including reviews' : '') + '?')" class="button" />
316
- <br><br>
317
- <label>
318
- <input type="checkbox" id="reset_db" name="reset_db"> Remove all reviews
319
- </label>
320
- </div>
321
- </div>
322
- <div id="debug_info" class="rplg-field">
323
- <div class="rplg-field-label">
324
- <label>DEBUG INFORMATION</label>
325
- </div>
326
- <div class="wp-review-field-option">
327
- <input type="button" value="Copy Debug Information" name="reset_all" onclick="window.rplg_debug_info.select();document.execCommand('copy');window.rplg_debug_msg.innerHTML='Debug Information copied, please paste it to your email to support';" class="button" />
328
- <textarea id="rplg_debug_info" style="display:block;width:30em;height:200px;margin-top:10px" onclick="window.rplg_debug_info.select();document.execCommand('copy');window.rplg_debug_msg.innerHTML='Debug Information copied, please paste it to your email to support';" readonly><?php rplg_debug(GRW_VERSION, grw_options(), 'widget_grw_widget'); grw_debug(); ?></textarea>
329
- <p id="rplg_debug_msg"></p>
330
- </div>
331
- </div>
332
- </form>
333
- </div>
334
- </div>
335
-
336
- </div>
337
-
338
- </div>
339
- <script type="text/javascript">
340
- jQuery(document).ready(function($) {
341
- $('a.nav-tab').on('click', function(e) {
342
- var $this = $(this), activeId = $this.attr('href');
343
- $(activeId).show().siblings('.tab-content').hide();
344
- $this.addClass('nav-tab-active').siblings().removeClass('nav-tab-active');
345
- e.preventDefault();
346
- });
347
-
348
- var el = document.body.querySelector('.widget-content'),
349
- elms = '.widget-content input[type="text"][name],' +
350
- '.widget-content input[type="hidden"][name],' +
351
- '.widget-content input[type="checkbox"][name]';
352
-
353
- $(elms).change(function() {
354
- if (!this.getAttribute('name')) return;
355
- if (!el.querySelector('.grw-google-place-id').value) return;
356
-
357
- var args = '',
358
- ctrls = el.querySelectorAll(elms);
359
- for (var i = 0; i < ctrls.length; i++) {
360
- var ctrl = ctrls[i],
361
- match = ctrl.getAttribute('name').match(/\[\]\[(.*?)\]/);
362
- if (match && match.length > 1) {
363
- var name = match[1];
364
- if (ctrl.type == 'checkbox') {
365
- if (ctrl.checked) args += ' ' + name + '=true';
366
- } else {
367
- if (ctrl.value) args += ' ' + name + '=' + '"' + ctrl.value + '"';
368
- }
369
- }
370
- }
371
- window.rplg_shortcode.value = '[grw' + args + ']';
372
- });
373
-
374
- $('.wp-google-place').click(function() {
375
- $.get('<?php echo admin_url('options-general.php?page=grw'); ?>&cf_action=grw_db_reviews&v=' + new Date().getTime(), {
376
- id: $(this).attr('data-id'),
377
- grw_wpnonce: jQuery('#grw_nonce').val()
378
- }, function(res) {
379
- $('.wp-google-content-inner').html(res);
380
- $('.wp-review-hide').click(function() {
381
- var $this = $(this);
382
- $.post('<?php echo admin_url('options-general.php?page=grw'); ?>&cf_action=grw_hide_review', {
383
- id: $this.attr('data-id'),
384
- grw_wpnonce: jQuery('#grw_nonce').val()
385
- }, function(res) {
386
- var parent = $this.parent().parent();
387
- if (res.hide) {
388
- $this.text('show review');
389
- parent.addClass('wp-review-hidden');
390
- } else {
391
- $this.text('hide review');
392
- parent.removeClass('wp-review-hidden');
393
- }
394
- }, 'json');
395
- return false;
396
- });
397
- }, 'html');
398
- return false;
399
- });
400
- });
401
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
grw-widget.php DELETED
@@ -1,200 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Google Reviews Widget
5
- *
6
- * @description: The Google Reviews Widget
7
- * @since : 1.0
8
- */
9
-
10
- //class name start with Goog_ instead Google_ coz it failed with w3c-total-cache plugin
11
- //https://wordpress.org/support/topic/fix-for-fatal-error-require/
12
- class Goog_Reviews_Widget extends WP_Widget {
13
-
14
- public static $widget_fields = array(
15
- 'title' => '',
16
- 'place_name' => '',
17
- 'place_id' => '',
18
- 'place_photo' => '',
19
- 'text_size' => '120',
20
- 'dark_theme' => '',
21
- 'view_mode' => 'list',
22
- 'pagination' => '5',
23
- 'max_width' => '',
24
- 'max_height' => '',
25
- 'refresh_reviews' => true,
26
- 'hide_based_on' => false,
27
- 'hide_reviews' => false,
28
- 'centered' => false,
29
- 'reduce_avatars_size' => true,
30
- 'open_link' => true,
31
- 'nofollow_link' => true,
32
- 'lazy_load_img' => true,
33
- 'def_reviews_link' => false,
34
- 'reviews_lang' => '',
35
- );
36
-
37
- public function __construct() {
38
- parent::__construct(
39
- 'grw_widget', // Base ID
40
- 'Google Reviews Widget', // Name
41
- array(
42
- 'classname' => 'google-reviews-widget',
43
- 'description' => __('Display Google Places Reviews on your website.', 'grw')
44
- )
45
- );
46
-
47
- add_action('wp_enqueue_scripts', array($this, 'grw_frontend_scripts'));
48
- add_action('admin_enqueue_scripts', array($this, 'grw_widget_scripts'));
49
- }
50
-
51
- function grw_frontend_scripts() {
52
- wp_register_script('wpac_time_js', plugins_url('/static/js/wpac-time.js', __FILE__), array(), GRW_VERSION);
53
- wp_enqueue_script('wpac_time_js', plugins_url('/static/js/wpac-time.js', __FILE__));
54
-
55
- wp_register_style('grw_css', plugins_url('/static/css/google-review.css', __FILE__), array(), GRW_VERSION);
56
- wp_enqueue_style('grw_css', plugins_url('/static/css/google-review.css', __FILE__));
57
- }
58
-
59
- function grw_widget_scripts($hook) {
60
- if ($hook == 'widgets.php' || $hook == 'settings_page_grw' || ($hook == 'post.php' && defined('SITEORIGIN_PANELS_VERSION'))) {
61
-
62
- wp_register_style('rplg_wp_css', plugins_url('/static/css/rplg-wp.css', __FILE__), array(), GRW_VERSION);
63
- wp_enqueue_style('rplg_wp_css', plugins_url('/static/css/rplg-wp.css', __FILE__));
64
-
65
- wp_enqueue_script('jquery');
66
-
67
- wp_register_script('wpac_js', plugins_url('/static/js/wpac.js', __FILE__), array(), GRW_VERSION);
68
- wp_enqueue_script('wpac_js', plugins_url('/static/js/wpac.js', __FILE__));
69
-
70
- wp_register_script('grw_finder_js', plugins_url('/static/js/grw-finder.js', __FILE__), array(), GRW_VERSION);
71
- wp_localize_script('grw_finder_js', 'grwVars', array(
72
- 'GOOGLE_AVATAR' => GRW_GOOGLE_AVATAR,
73
- 'handlerUrl' => admin_url('options-general.php?page=grw'),
74
- 'actionPrefix' => 'grw'
75
- ));
76
- wp_enqueue_script('grw_finder_js', plugins_url('/static/js/grw-finder.js', __FILE__));
77
- }
78
- }
79
-
80
- function widget($args, $instance) {
81
- global $wpdb;
82
-
83
- if (grw_enabled()) {
84
- extract($args);
85
- foreach (self::$widget_fields as $variable => $value) {
86
- ${$variable} = !isset($instance[$variable]) ? self::$widget_fields[$variable] : esc_attr($instance[$variable]);
87
- }
88
-
89
- echo $before_widget;
90
- if ($place_id) {
91
- if ($title) { ?><h2 class="grw-widget-title widget-title"><?php echo $title; ?></h2><?php }
92
- include(dirname(__FILE__) . '/grw-reviews.php');
93
- if ($view_mode == 'badge') {
94
- ?>
95
- <style>
96
- #<?php echo $this->id; ?> {
97
- margin: 0;
98
- padding: 0;
99
- border: none;
100
- }
101
- </style>
102
- <?php
103
- }
104
- } else { ?>
105
- <div class="grw-error" style="padding:10px;color:#B94A48;background-color:#F2DEDE;border-color:#EED3D7;">
106
- <?php echo __('Please check that this widget <b>Google Reviews</b> has a Google Place ID set.', 'grw'); ?>
107
- </div>
108
- <?php }
109
- echo $after_widget;
110
- }
111
- }
112
-
113
- function update($new_instance, $old_instance) {
114
- $instance = $old_instance;
115
- foreach (self::$widget_fields as $field => $value) {
116
- $instance[$field] = isset($new_instance[$field]) ? strip_tags(stripslashes($new_instance[$field])) : '';
117
- }
118
- return $instance;
119
- }
120
-
121
- function form($instance) {
122
- global $wp_version;
123
- foreach (self::$widget_fields as $field => $value) {
124
- if (array_key_exists($field, self::$widget_fields)) {
125
- ${$field} = !isset($instance[$field]) ? $value : esc_attr($instance[$field]);
126
- }
127
- }
128
-
129
- wp_nonce_field('grw_wpnonce', 'grw_nonce');
130
-
131
- $grw_google_api_key = get_option('grw_google_api_key');
132
- if ($grw_google_api_key) {
133
- ?>
134
- <div id="<?php echo $this->id; ?>" class="rplg-widget"><?php
135
- if (!$place_id) {
136
- include(dirname(__FILE__) . '/grw-finder.php');
137
- } else { ?>
138
- <script type="text/javascript">
139
- jQuery('.grw-tooltip').remove();
140
- </script> <?php
141
- }
142
- include(dirname(__FILE__) . '/grw-options.php'); ?>
143
- </div>
144
- <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" onload="(function(el) { var t = setInterval(function () {if (window.grw_init){grw_init({el: el});clearInterval(t);}}, 200); })(this.parentNode);" style="display:none">
145
- <?php
146
- } else {
147
- ?>
148
- <h4 class="text-left">First of all, please <a href="<?php echo admin_url('options-general.php?page=grw&grw_tab=fig'); ?>">create and save your own Google API Key</a> in the Settings</h4>
149
- <script type="text/javascript">
150
- var apikey = document.querySelectorAll('.grw-apikey');
151
- if (apikey) {
152
- WPacFastjs.onall(apikey, 'change', function() {
153
- if (!this.value) return;
154
- jQuery.post('<?php echo admin_url('options-general.php?page=grw'); ?>&cf_action=' + this.getAttribute('name'), {
155
- key: this.value,
156
- grw_wpnonce: jQuery('#grw_nonce').val()
157
- }, function(res) {
158
- console.log('RESPONSE', res);
159
- }, 'json');
160
- });
161
- }
162
- </script>
163
- <?php
164
- }
165
- ?>
166
- <script type="text/javascript">
167
- function grw_load_js(src, cb) {
168
- var script = document.createElement('script');
169
- script.type = 'text/javascript';
170
- script.src = src;
171
- script.async = 'true';
172
- if (cb) {
173
- script.addEventListener('load', function (e) { cb(null, e); }, false);
174
- }
175
- document.getElementsByTagName('head')[0].appendChild(script);
176
- }
177
-
178
- function grw_load_css(href) {
179
- var link = document.createElement('link');
180
- link.rel = 'stylesheet';
181
- link.href = href;
182
- document.getElementsByTagName('head')[0].appendChild(link);
183
- }
184
-
185
- if (!window.grw_init) {
186
- grw_load_css('<?php echo plugins_url('/static/css/rplg-wp.css?ver=' . GRW_VERSION, __FILE__); ?>');
187
- grw_load_js('<?php echo plugins_url('/static/js/wpac.js?ver=' . GRW_VERSION, __FILE__); ?>', function() {
188
- window.grwVars = {
189
- GOOGLE_AVATAR : '<?php echo GRW_GOOGLE_AVATAR; ?>',
190
- handlerUrl : '<?php echo admin_url('options-general.php?page=grw'); ?>',
191
- actionPrefix : 'grw'
192
- };
193
- grw_load_js('<?php echo plugins_url('/static/js/grw-finder.js?ver=' . GRW_VERSION, __FILE__); ?>');
194
- });
195
- }
196
- </script>
197
- <?php
198
- }
199
- }
200
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
grw.php CHANGED
@@ -3,67 +3,36 @@
3
  Plugin Name: Widget for Google Reviews
4
  Plugin URI: https://richplugins.com/business-reviews-bundle-wordpress-plugin
5
  Description: Instantly Google Places Reviews on your website to increase user confidence and SEO.
 
6
  Author: RichPlugins <support@richplugins.com>
7
- Version: 1.9.9
8
  Author URI: https://richplugins.com
9
  Text Domain: widget-google-reviews
10
  Domain Path: /languages
11
  */
12
 
13
- require(ABSPATH . 'wp-includes/version.php');
14
-
15
- include_once(dirname(__FILE__) . '/api/urlopen.php');
16
- include_once(dirname(__FILE__) . '/helper/debug.php');
17
-
18
- define('GRW_VERSION', '1.9.9');
19
- define('GRW_GOOGLE_PLACE_API', 'https://maps.googleapis.com/maps/api/place/');
20
- define('GRW_GOOGLE_AVATAR', 'https://lh3.googleusercontent.com/-8hepWJzFXpE/AAAAAAAAAAI/AAAAAAAAAAA/I80WzYfIxCQ/s128-c/114307615494839964028.jpg');
21
- define('GRW_PLUGIN_URL', plugins_url(basename(plugin_dir_path(__FILE__ )), basename(__FILE__)));
22
 
23
- function grw_options() {
24
- return array(
25
- 'grw_version',
26
- 'grw_active',
27
- 'grw_google_api_key',
28
- 'grw_language',
29
- 'grw_activation_time',
30
- 'grw_rev_notice_hide',
31
- 'rplg_rev_notice_show',
32
- 'grw_debug_refresh',
33
- );
34
  }
35
 
36
- /*-------------------------------- Widget --------------------------------*/
37
- function grw_setup_widget() {
38
- if (!class_exists('Goog_Reviews_Widget')) {
39
- require 'grw-widget.php';
40
- register_widget('Goog_Reviews_Widget');
41
- }
42
- }
43
- add_action('widgets_init', 'grw_setup_widget');
44
 
45
- /*-------------------------------- Menu --------------------------------*/
46
- function grw_setting_menu() {
47
- add_submenu_page(
48
- 'options-general.php',
49
- 'Google Reviews Widget',
50
- 'Google Reviews Widget',
51
- 'moderate_comments',
52
- 'grw',
53
- 'grw_setting'
54
- );
55
- }
56
- add_action('admin_menu', 'grw_setting_menu', 10);
57
 
58
- function grw_setting() {
59
- include_once(dirname(__FILE__) . '/grw-setting.php');
60
- }
 
61
 
62
  /*-------------------------------- Links --------------------------------*/
63
  function grw_plugin_action_links($links, $file) {
64
  $plugin_file = basename(__FILE__);
65
  if (basename($file) == $plugin_file) {
66
- $settings_link = '<a href="' . admin_url('options-general.php?page=grw&grw_tab=fig') . '">' .
67
  '<span style="background-color:#e7711b;color:#fff;font-weight:bold;padding:0px 8px 2px">' .
68
  'Connect Reviews' .
69
  '</span>' .
@@ -72,7 +41,7 @@ function grw_plugin_action_links($links, $file) {
72
  }
73
  return $links;
74
  }
75
- add_filter('plugin_action_links', 'grw_plugin_action_links', 10, 2);
76
 
77
  /*-------------------------------- Row Meta --------------------------------*/
78
  function grw_plugin_row_meta($input, $file) {
@@ -81,640 +50,16 @@ function grw_plugin_row_meta($input, $file) {
81
  }
82
 
83
  $links = array(
84
- '<a href="' . admin_url('options-general.php?page=grw&grw_tab=fig') . '" target="_blank">' . __('View Documentation', 'grw') . '</a>',
85
  '<a href="' . esc_url('https://richplugins.com/business-reviews-bundle-wordpress-plugin') . '" target="_blank">' . __('Upgrade to Business', 'grw') . ' &raquo;</a>',
86
  );
87
  $input = array_merge($input, $links);
88
  return $input;
89
  }
90
- add_filter('plugin_row_meta', 'grw_plugin_row_meta', 10, 2);
91
-
92
- /*-------------------------------- Activator --------------------------------*/
93
- function grw_check_version() {
94
- if (version_compare(get_option('grw_version'), GRW_VERSION, '<')) {
95
- grw_activate();
96
- }
97
- }
98
- add_action('init', 'grw_check_version');
99
-
100
- function grw_activation($network_wide = false) {
101
- $now = time();
102
- update_option('grw_activation_time', $now);
103
-
104
- add_option('grw_is_multisite', $network_wide);
105
- grw_activate();
106
- }
107
- register_activation_hook(__FILE__, 'grw_activation');
108
-
109
- function grw_activate() {
110
- $network_wide = get_option('grw_is_multisite');
111
- if ($network_wide) {
112
- grw_activate_multisite();
113
- } else {
114
- grw_activate_single_site();
115
- }
116
- }
117
-
118
- function grw_activate_multisite() {
119
- global $wpdb;
120
-
121
- $site_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
122
-
123
- foreach($site_ids as $site_id) {
124
- switch_to_blog($site_id);
125
- grw_activate_single_site();
126
- restore_current_blog();
127
- }
128
- }
129
-
130
- function grw_activate_single_site() {
131
- $current_version = GRW_VERSION;
132
- $last_active_version = get_option('grw_version');
133
-
134
- if (empty($last_active_version)) {
135
- grw_first_install();
136
- update_option('grw_version', $current_version);
137
- } elseif ($last_active_version !== $current_version) {
138
- grw_exist_install($current_version, $last_active_version);
139
- update_option('grw_version', $current_version);
140
- }
141
- }
142
-
143
- function grw_first_install() {
144
- grw_install_db();
145
- add_option('grw_active', '1');
146
- add_option('grw_google_api_key', '');
147
- }
148
-
149
- function grw_exist_install($current_version, $last_active_version) {
150
- global $wpdb;
151
- switch($last_active_version) {
152
- case version_compare($last_active_version, '1.8.2', '<'):
153
- $wpdb->query("ALTER TABLE " . $wpdb->prefix . "grp_google_place ADD review_count INTEGER");
154
- $place_ids = $wpdb->get_col("SELECT place_id FROM " . $wpdb->prefix . "grp_google_place WHERE rating > 0 LIMIT 5");
155
- foreach($place_ids as $place_id) {
156
- grw_refresh_reviews(array($place_id));
157
- }
158
- break;
159
- case version_compare($last_active_version, '1.8.7', '<'):
160
- $row = $wpdb->get_results("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '" . $wpdb->prefix . "grp_google_review' AND column_name = 'hide'");
161
- if(empty($row)){
162
- $wpdb->query("ALTER TABLE " . $wpdb->prefix . "grp_google_review ADD hide VARCHAR(1) DEFAULT '' NOT NULL");
163
- }
164
- break;
165
- }
166
- }
167
-
168
- function grw_install_db() {
169
- global $wpdb;
170
-
171
- $charset_collate = $wpdb->get_charset_collate();
172
-
173
- $sql = "CREATE TABLE IF NOT EXISTS " . $wpdb->prefix . "grp_google_place (".
174
- "id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,".
175
- "place_id VARCHAR(80) NOT NULL,".
176
- "name VARCHAR(255) NOT NULL,".
177
- "photo VARCHAR(255),".
178
- "icon VARCHAR(255),".
179
- "address VARCHAR(255),".
180
- "rating DOUBLE PRECISION,".
181
- "url VARCHAR(255),".
182
- "website VARCHAR(255),".
183
- "review_count INTEGER,".
184
- "updated BIGINT(20),".
185
- "PRIMARY KEY (`id`),".
186
- "UNIQUE INDEX grp_place_id (`place_id`)".
187
- ") " . $charset_collate . ";";
188
-
189
- require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
190
-
191
- dbDelta($sql);
192
-
193
- $sql = "CREATE TABLE IF NOT EXISTS " . $wpdb->prefix . "grp_google_review (".
194
- "id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,".
195
- "google_place_id BIGINT(20) UNSIGNED NOT NULL,".
196
- "hash VARCHAR(40) NOT NULL,".
197
- "rating INTEGER NOT NULL,".
198
- "text VARCHAR(10000),".
199
- "time INTEGER NOT NULL,".
200
- "language VARCHAR(10),".
201
- "author_name VARCHAR(255),".
202
- "author_url VARCHAR(255),".
203
- "profile_photo_url VARCHAR(255),".
204
- "hide VARCHAR(1) DEFAULT '' NOT NULL,".
205
- "PRIMARY KEY (`id`),".
206
- "UNIQUE INDEX grp_google_review_hash (`hash`),".
207
- "INDEX grp_google_place_id (`google_place_id`)".
208
- ") " . $charset_collate . ";";
209
-
210
- dbDelta($sql);
211
- }
212
-
213
- function grw_reset($reset_db) {
214
- global $wpdb;
215
-
216
- if (function_exists('is_multisite') && is_multisite()) {
217
- $current_blog_id = get_current_blog_id();
218
- $blog_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
219
- foreach ($blog_ids as $blog_id) {
220
- switch_to_blog($blog_id);
221
- grw_reset_data($reset_db);
222
- }
223
- switch_to_blog($current_blog_id);
224
- } else {
225
- grw_reset_data($reset_db);
226
- }
227
- }
228
-
229
- function grw_reset_data($reset_db) {
230
- global $wpdb;
231
-
232
- foreach (grw_options() as $opt) {
233
- delete_option($opt);
234
- }
235
- if ($reset_db) {
236
- $wpdb->query("DROP TABLE IF EXISTS " . $wpdb->prefix . "grp_google_place;");
237
- $wpdb->query("DROP TABLE IF EXISTS " . $wpdb->prefix . "grp_google_review;");
238
- }
239
- }
240
-
241
- /*-------------------------------- Shortcode --------------------------------*/
242
- function grw_shortcode($atts) {
243
- global $wpdb;
244
-
245
- if (!grw_enabled()) return '';
246
- if (!class_exists('Goog_Reviews_Widget')) return '';
247
-
248
- $shortcode_atts = array();
249
- foreach (Goog_Reviews_Widget::$widget_fields as $field => $value) {
250
- $shortcode_atts[$field] = isset($atts[$field]) ? strip_tags(stripslashes($atts[$field])) : '';
251
- }
252
-
253
- foreach ($shortcode_atts as $variable => $value) {
254
- ${$variable} = esc_attr($shortcode_atts[$variable]);
255
- }
256
-
257
- ob_start();
258
- if (empty($place_id)) {
259
- ?>
260
- <div class="grw-error" style="padding:10px;color:#b94a48;background-color:#f2dede;border-color:#eed3d7;max-width:200px;">
261
- <?php echo __('<b>Google Reviews Widget</b>: required attribute place_id is not defined', 'grw'); ?>
262
- </div>
263
- <?php
264
- } else {
265
- include(dirname(__FILE__) . '/grw-reviews.php');
266
- }
267
- return preg_replace('/[\n\r]/', '', ob_get_clean());
268
- }
269
- add_shortcode("grw", "grw_shortcode");
270
-
271
- /*-------------------------------- Request --------------------------------*/
272
- function grw_request_handler() {
273
- global $wpdb;
274
-
275
- if (!empty($_GET['cf_action'])) {
276
-
277
- switch ($_GET['cf_action']) {
278
- case 'grw_google_api_key':
279
- if (current_user_can('manage_options')) {
280
- if (isset($_POST['grw_wpnonce']) === false) {
281
- $error = __('Unable to call request. Make sure you are accessing this page from the Wordpress dashboard.', 'grw');
282
- $response = compact('error');
283
- } else {
284
- check_admin_referer('grw_wpnonce', 'grw_wpnonce');
285
-
286
- update_option('grw_google_api_key', trim(sanitize_text_field($_POST['key'])));
287
- $status = 'success';
288
- $response = compact('status');
289
-
290
- }
291
- header('Content-type: text/javascript');
292
- echo json_encode($response);
293
- die();
294
- }
295
- break;
296
- case 'grw_search':
297
- if (current_user_can('manage_options')) {
298
- if (isset($_GET['grw_wpnonce']) === false) {
299
- $error = __('Unable to call request. Make sure you are accessing this page from the Wordpress dashboard.', 'grw');
300
- $response = compact('error');
301
- } else {
302
- check_admin_referer('grw_wpnonce', 'grw_wpnonce');
303
-
304
- $grw_google_api_key = get_option('grw_google_api_key');
305
- $url = GRW_GOOGLE_PLACE_API . 'textsearch/json?query=' . $_GET['query'] . '&key=' . $grw_google_api_key;
306
-
307
- $grw_language = get_option('grw_language');
308
- if (strlen($grw_language) > 0) {
309
- $url = $url . '&language=' . $grw_language;
310
- }
311
-
312
- $response = rplg_urlopen($url);
313
-
314
- $response_data = $response['data'];
315
- $response_json = rplg_json_decode($response_data);
316
- $response_results = $response_json->results;
317
-
318
- foreach ($response_results as $result) {
319
- $result->business_photo = grw_business_avatar($result);
320
- }
321
- }
322
- header('Content-type: text/javascript');
323
- echo json_encode($response_results);
324
- die();
325
- }
326
- break;
327
- case 'grw_reviews':
328
- if (current_user_can('manage_options')) {
329
- if (isset($_GET['grw_wpnonce']) === false) {
330
- $error = __('Unable to call request. Make sure you are accessing this page from the Wordpress dashboard.', 'grw');
331
- $response = compact('error');
332
- } else {
333
- check_admin_referer('grw_wpnonce', 'grw_wpnonce');
334
-
335
- $url = grw_api_url($_GET['placeid']);
336
-
337
- $response = rplg_urlopen($url);
338
-
339
- $response_data = $response['data'];
340
- $response_json = rplg_json_decode($response_data);
341
- $response_result = $response_json->result;
342
-
343
- if (isset($response_result)) {
344
- $response_result->business_photo = grw_business_avatar($response_result);
345
- }
346
- }
347
- header('Content-type: text/javascript');
348
- echo json_encode($response_json->result);
349
- die();
350
- }
351
- break;
352
- case 'grw_save':
353
- if (current_user_can('manage_options')) {
354
- if (isset($_POST['grw_wpnonce']) === false) {
355
- $error = __('Unable to call request. Make sure you are accessing this page from the Wordpress dashboard.', 'grw');
356
- $response = compact('error');
357
- } else {
358
- check_admin_referer('grw_wpnonce', 'grw_wpnonce');
359
-
360
- $url = grw_api_url($_POST['placeid'], $_POST['lang']);
361
-
362
- $response = rplg_urlopen($url);
363
-
364
- $response_data = $response['data'];
365
- $response_json = rplg_json_decode($response_data);
366
-
367
- if ($response_json && isset($response_json->result)) {
368
- $response_json->result->business_photo = grw_business_avatar($response_json->result);
369
- grw_save_reviews($response_json->result);
370
- $result = $response_json->result;
371
- $status = 'success';
372
- } else {
373
- $result = $response_json;
374
- $status = 'failed';
375
- }
376
- $response = compact('status', 'result');
377
- }
378
- header('Content-type: text/javascript');
379
- echo json_encode($response);
380
- die();
381
- }
382
- break;
383
- case 'grw_db_reviews':
384
- if (current_user_can('manage_options')) {
385
- if (isset($_GET['grw_wpnonce']) === false) {
386
- $error = __('Unable to call request. Make sure you are accessing this page from the Wordpress dashboard.', 'grw');
387
- $response = compact('error');
388
- } else {
389
- check_admin_referer('grw_wpnonce', 'grw_wpnonce');
390
-
391
- include_once(dirname(__FILE__) . '/grw-reviews-helper.php');
392
-
393
- $reviews = $wpdb->get_results($wpdb->prepare("SELECT * FROM " . $wpdb->prefix . "grp_google_review WHERE google_place_id = %d ORDER BY time DESC", $_GET['id']));
394
-
395
- ob_start();
396
- grw_place_reviews(null, $reviews, 'zzz', 120, false, true, true, true, false, false, true);
397
- $response = ob_get_clean();
398
- }
399
- header('Content-type: text/html');
400
- header('Access-Control-Allow-Origin: *');
401
- echo $response;
402
- die();
403
- }
404
- break;
405
- case 'grw_hide_review':
406
- if (current_user_can('manage_options')) {
407
- if (isset($_POST['grw_wpnonce']) === false) {
408
- $error = __('Unable to call request. Make sure you are accessing this page from the Wordpress dashboard.', 'grw');
409
- $response = compact('error');
410
- } else {
411
- check_admin_referer('grw_wpnonce', 'grw_wpnonce');
412
-
413
- $review = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . $wpdb->prefix . "grp_google_review WHERE id = %d", $_POST['id']));
414
- $hide = $review->hide == '' ? 'y' : '';
415
- $wpdb->update($wpdb->prefix . 'grp_google_review', array('hide' => $hide), array('id' => $_POST['id']));
416
- $response = array('hide' => $hide);
417
- }
418
- header('Content-type: text/javascript');
419
- echo json_encode($response);
420
- die();
421
- }
422
- break;
423
- }
424
- }
425
- }
426
- add_action('init', 'grw_request_handler');
427
-
428
- function grw_save_reviews($place, $min_filter = 0) {
429
- global $wpdb;
430
-
431
- $google_place_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM " . $wpdb->prefix . "grp_google_place WHERE place_id = %s", $place->place_id));
432
- if ($google_place_id) {
433
- $wpdb->update($wpdb->prefix . 'grp_google_place', array(
434
- 'name' => $place->name,
435
- 'photo' => $place->business_photo,
436
- 'rating' => $place->rating,
437
- 'review_count' => isset($place->user_ratings_total) ? $place->user_ratings_total : null
438
- ), array('ID' => $google_place_id));
439
- } else {
440
- $wpdb->insert($wpdb->prefix . 'grp_google_place', array(
441
- 'place_id' => $place->place_id,
442
- 'name' => $place->name,
443
- 'photo' => $place->business_photo,
444
- 'icon' => $place->icon,
445
- 'address' => $place->formatted_address,
446
- 'rating' => isset($place->rating) ? $place->rating : null,
447
- 'url' => isset($place->url) ? $place->url : null,
448
- 'website' => isset($place->website) ? $place->website : null,
449
- 'review_count' => isset($place->user_ratings_total) ? $place->user_ratings_total : null
450
- ));
451
- $google_place_id = $wpdb->insert_id;
452
- }
453
-
454
- if ($place->reviews) {
455
- $reviews = $place->reviews;
456
- foreach ($reviews as $review) {
457
- if ($min_filter > 0 && $min_filter > $review->rating) {
458
- continue;
459
- }
460
-
461
- $google_review_id = 0;
462
- if (isset($review->author_url) && strlen($review->author_url) > 0) {
463
- $google_review_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM " . $wpdb->prefix . "grp_google_review WHERE author_url = %s", $review->author_url));
464
- } else {
465
- $google_review_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM " . $wpdb->prefix . "grp_google_review WHERE time = %s", $review->time));
466
- }
467
-
468
- if ($google_review_id) {
469
- $update_params = array(
470
- 'rating' => $review->rating,
471
- 'text' => $review->text
472
- );
473
- if (isset($review->profile_photo_url)) {
474
- $update_params['profile_photo_url'] = $review->profile_photo_url;
475
- }
476
- $wpdb->update($wpdb->prefix . 'grp_google_review', $update_params, array('id' => $google_review_id));
477
- } else {
478
- $wpdb->insert($wpdb->prefix . 'grp_google_review', array(
479
- 'google_place_id' => $google_place_id,
480
- 'hash' => $review->time, //TODO: workaround to support old versions
481
- 'rating' => $review->rating,
482
- 'text' => $review->text,
483
- 'time' => $review->time,
484
- 'language' => $review->language,
485
- 'author_name' => $review->author_name,
486
- 'author_url' => isset($review->author_url) ? $review->author_url : null,
487
- 'profile_photo_url' => isset($review->profile_photo_url) ? $review->profile_photo_url : null
488
- ));
489
- }
490
- }
491
- }
492
- }
493
-
494
- /*-------------------------------- Refresh Reviews --------------------------------*/
495
- function grw_refresh_reviews($args) {
496
- $google_api_key = get_option('grw_google_api_key');
497
- if (!$google_api_key || strlen($google_api_key) < 1) {
498
- return;
499
- }
500
-
501
- $place_id = $args[0];
502
- $reviews_lang = isset($args[1]) ? $args[1] : '';
503
-
504
- $url = grw_api_url($place_id, $reviews_lang);
505
-
506
- $response = rplg_urlopen($url);
507
-
508
- $response_data = $response['data'];
509
- $response_json = rplg_json_decode($response_data);
510
-
511
- if ($response_json && isset($response_json->result)) {
512
- $response_json->result->business_photo = grw_business_avatar($response_json->result);
513
- grw_save_reviews($response_json->result);
514
- }
515
- delete_transient('grw_refresh_reviews_' . join('_', $args));
516
- }
517
- add_action('grw_refresh_reviews', 'grw_refresh_reviews');
518
-
519
- /*-------------------------------- Init language --------------------------------*/
520
- function grw_lang_init() {
521
- $plugin_dir = basename(dirname(__FILE__));
522
- load_plugin_textdomain('grw', false, $plugin_dir . '/languages');
523
- }
524
- add_action('plugins_loaded', 'grw_lang_init');
525
-
526
- /*-------------------------------- Leave review --------------------------------*/
527
- function grw_admin_notice() {
528
- if (!is_admin()) return;
529
 
530
- $activation_time = get_option('grw_activation_time');
531
-
532
- if ($activation_time == '') {
533
- $activation_time = time() - 86400*2;
534
- update_option('grw_activation_time', $activation_time);
535
- }
536
-
537
- $rev_notice = isset($_GET['grw_rev_notice']) ? $_GET['grw_rev_notice'] : '';
538
- if ($rev_notice == 'later') {
539
- $activation_time = time() - 86400*2;
540
- update_option('grw_activation_time', $activation_time);
541
- update_option('grw_rev_notice_hide', 'later');
542
- } else if ($rev_notice == 'never') {
543
- update_option('grw_rev_notice_hide', 'never');
544
- }
545
 
546
- $rev_notice_hide = get_option('grw_rev_notice_hide');
547
- $rev_notice_show = get_option('rplg_rev_notice_show');
548
-
549
- if ($rev_notice_show == '' || $rev_notice_show == 'grw') {
550
-
551
- if ($rev_notice_hide != 'never' && $activation_time < (time() - 86400*3)) {
552
- update_option('rplg_rev_notice_show', 'grw');
553
- $class = 'notice notice-info is-dismissible';
554
- $url = remove_query_arg(array('taction', 'tid', 'sortby', 'sortdir', 'opt'));
555
- $url_later = esc_url(add_query_arg('grw_rev_notice', 'later', $url));
556
- $url_never = esc_url(add_query_arg('grw_rev_notice', 'never', $url));
557
-
558
- $notice = '<p style="font-weight:normal;color:#156315">Hey, I am happy to see that you\'ve been using our <b>Google Reviews Widget</b> plugin for a while now – that’s awesome!<br>Could you please do me a BIG favor and give it a 5-star rating on WordPress?<br><br>--<br>Thanks!<br>Daniel K.<br></p><ul style="font-weight:bold;"><li><a href="https://wordpress.org/support/plugin/widget-google-reviews/reviews/#new-post" target="_blank">OK, you deserve it</a></li><li><a href="' . $url_later . '">Not now, maybe later</a></li><li><a href="' . $url_never . '">Do not remind me again</a></li></ul><p>By the way, if you have been thinking about upgrading to the <a href="https://richplugins.com/business-reviews-bundle-wordpress-plugin" target="_blank">Business</a> version, here is a 25% off onboard coupon -> <b>business25off</b></p>';
559
-
560
- printf('<div class="%1$s"><p>%2$s</p></div>', esc_attr($class), $notice);
561
- } else {
562
- update_option('rplg_rev_notice_show', '');
563
- }
564
-
565
- }
566
- }
567
- add_action('admin_notices', 'grw_admin_notice');
568
-
569
- /*-------------------------------- Helpers --------------------------------*/
570
- function grw_enabled() {
571
- global $id, $post;
572
-
573
- $active = get_option('grw_active');
574
- if (empty($active) || $active === '0') { return false; }
575
- return true;
576
- }
577
-
578
- function grw_api_url($placeid, $reviews_lang = '') {
579
- $url = GRW_GOOGLE_PLACE_API . 'details/json?placeid=' . $placeid . '&key=' . get_option('grw_google_api_key');
580
-
581
- $grw_language = strlen($reviews_lang) > 0 ? $reviews_lang : get_option('grw_language');
582
- if (strlen($grw_language) > 0) {
583
- $url = $url . '&language=' . $grw_language;
584
- }
585
- return $url;
586
- }
587
-
588
- function grw_business_avatar($response_result_json) {
589
- if (isset($response_result_json->photos)) {
590
- $request_url = add_query_arg(
591
- array(
592
- 'photoreference' => $response_result_json->photos[0]->photo_reference,
593
- 'key' => get_option('grw_google_api_key'),
594
- 'maxwidth' => '300',
595
- 'maxheight' => '300',
596
- ),
597
- 'https://maps.googleapis.com/maps/api/place/photo'
598
- );
599
- $response = rplg_urlopen($request_url);
600
- foreach ($response['headers'] as $header) {
601
- if (strpos($header, 'Location: ') !== false) {
602
- return str_replace('Location: ', '', $header);
603
- }
604
- }
605
- }
606
- return null;
607
- }
608
-
609
- function grw_array($params=null) {
610
- if (!is_array($params)) {
611
- $params = func_get_args();
612
- $params = array_slice($params, 0);
613
- }
614
- return $params;
615
- }
616
-
617
- if (!function_exists('esc_html')) {
618
- function esc_html( $text ) {
619
- $safe_text = wp_check_invalid_utf8( $text );
620
- $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES );
621
- return apply_filters( 'esc_html', $safe_text, $text );
622
- }
623
- }
624
-
625
- if (!function_exists('esc_attr')) {
626
- function esc_attr( $text ) {
627
- $safe_text = wp_check_invalid_utf8( $text );
628
- $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES );
629
- return apply_filters( 'attribute_escape', $safe_text, $text );
630
- }
631
- }
632
-
633
- /**
634
- * JSON ENCODE for PHP < 5.2.0
635
- */
636
- if (!function_exists('json_encode')) {
637
-
638
- function json_encode($data) {
639
- return cfjson_encode($data);
640
- }
641
-
642
- function cfjson_encode_string($str) {
643
- if(is_bool($str)) {
644
- return $str ? 'true' : 'false';
645
- }
646
-
647
- return str_replace(
648
- array(
649
- '\\'
650
- , '"'
651
- //, '/'
652
- , "\n"
653
- , "\r"
654
- )
655
- , array(
656
- '\\\\'
657
- , '\"'
658
- //, '\/'
659
- , '\n'
660
- , '\r'
661
- )
662
- , $str
663
- );
664
- }
665
-
666
- function cfjson_encode($arr) {
667
- $json_str = '';
668
- if (is_array($arr)) {
669
- $pure_array = true;
670
- $array_length = count($arr);
671
- for ( $i = 0; $i < $array_length ; $i++) {
672
- if (!isset($arr[$i])) {
673
- $pure_array = false;
674
- break;
675
- }
676
- }
677
- if ($pure_array) {
678
- $json_str = '[';
679
- $temp = array();
680
- for ($i=0; $i < $array_length; $i++) {
681
- $temp[] = sprintf("%s", cfjson_encode($arr[$i]));
682
- }
683
- $json_str .= implode(',', $temp);
684
- $json_str .="]";
685
- }
686
- else {
687
- $json_str = '{';
688
- $temp = array();
689
- foreach ($arr as $key => $value) {
690
- $temp[] = sprintf("\"%s\":%s", $key, cfjson_encode($value));
691
- }
692
- $json_str .= implode(',', $temp);
693
- $json_str .= '}';
694
- }
695
- }
696
- else if (is_object($arr)) {
697
- $json_str = '{';
698
- $temp = array();
699
- foreach ($arr as $k => $v) {
700
- $temp[] = '"'.$k.'":'.cfjson_encode($v);
701
- }
702
- $json_str .= implode(',', $temp);
703
- $json_str .= '}';
704
- }
705
- else if (is_string($arr)) {
706
- $json_str = '"'. cfjson_encode_string($arr) . '"';
707
- }
708
- else if (is_numeric($arr)) {
709
- $json_str = $arr;
710
- }
711
- else if (is_bool($arr)) {
712
- $json_str = $arr ? 'true' : 'false';
713
- }
714
- else {
715
- $json_str = '"'. cfjson_encode_string($arr) . '"';
716
- }
717
- return $json_str;
718
- }
719
- }
720
  ?>
3
  Plugin Name: Widget for Google Reviews
4
  Plugin URI: https://richplugins.com/business-reviews-bundle-wordpress-plugin
5
  Description: Instantly Google Places Reviews on your website to increase user confidence and SEO.
6
+ Version: 2.0
7
  Author: RichPlugins <support@richplugins.com>
 
8
  Author URI: https://richplugins.com
9
  Text Domain: widget-google-reviews
10
  Domain Path: /languages
11
  */
12
 
13
+ namespace WP_Rplg_Google_Reviews;
 
 
 
 
 
 
 
 
14
 
15
+ if (!defined('ABSPATH')) {
16
+ exit;
 
 
 
 
 
 
 
 
 
17
  }
18
 
19
+ require(ABSPATH . 'wp-includes/version.php');
 
 
 
 
 
 
 
20
 
21
+ define('GRW_VERSION' , '2.0');
22
+ define('GRW_PLUGIN_FILE' , __FILE__);
23
+ define('GRW_PLUGIN_URL' , plugins_url(basename(plugin_dir_path(__FILE__ )), basename(__FILE__)));
24
+ define('GRW_ASSETS_URL' , GRW_PLUGIN_URL . '/assets/');
 
 
 
 
 
 
 
 
25
 
26
+ define('GRW_GOOGLE_PLACE_API' , 'https://maps.googleapis.com/maps/api/place/');
27
+ define('GRW_GOOGLE_AVATAR' , 'https://lh3.googleusercontent.com/-8hepWJzFXpE/AAAAAAAAAAI/AAAAAAAAAAA/I80WzYfIxCQ/s128-c/114307615494839964028.jpg');
28
+
29
+ require_once __DIR__ . '/autoloader.php';
30
 
31
  /*-------------------------------- Links --------------------------------*/
32
  function grw_plugin_action_links($links, $file) {
33
  $plugin_file = basename(__FILE__);
34
  if (basename($file) == $plugin_file) {
35
+ $settings_link = '<a href="' . admin_url('admin.php?page=grw-builder') . '">' .
36
  '<span style="background-color:#e7711b;color:#fff;font-weight:bold;padding:0px 8px 2px">' .
37
  'Connect Reviews' .
38
  '</span>' .
41
  }
42
  return $links;
43
  }
44
+ add_filter('plugin_action_links', 'WP_Rplg_Google_Reviews\\grw_plugin_action_links', 10, 2);
45
 
46
  /*-------------------------------- Row Meta --------------------------------*/
47
  function grw_plugin_row_meta($input, $file) {
50
  }
51
 
52
  $links = array(
53
+ '<a href="' . admin_url('admin.php?page=grw-support') . '" target="_blank">' . __('View Documentation', 'grw') . '</a>',
54
  '<a href="' . esc_url('https://richplugins.com/business-reviews-bundle-wordpress-plugin') . '" target="_blank">' . __('Upgrade to Business', 'grw') . ' &raquo;</a>',
55
  );
56
  $input = array_merge($input, $links);
57
  return $input;
58
  }
59
+ add_filter('plugin_row_meta', 'WP_Rplg_Google_Reviews\\grw_plugin_row_meta', 10, 2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
+ /*-------------------------------- Plugin init --------------------------------*/
62
+ $grw = new Includes\Plugin();
63
+ $grw->register();
 
 
 
 
 
 
 
 
 
 
 
 
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  ?>
helper/debug.php DELETED
@@ -1,51 +0,0 @@
1
- <?php
2
-
3
- if (!function_exists('rplg_debug')) {
4
-
5
- function rplg_debug($version, $options, $widget_name) {
6
- global $wp_version; ?>
7
- URL: <?php echo esc_url(get_option('siteurl')); ?>
8
-
9
- PHP Version: <?php echo esc_html(phpversion()); ?>
10
-
11
- WP Version: <?php echo esc_html($wp_version); ?>
12
-
13
- Active Theme:
14
- <?php
15
- if (!function_exists('wp_get_theme')) {
16
- $theme = get_theme(get_current_theme());
17
- echo esc_html($theme['Name'] . ' ' . $theme['Version']);
18
- } else {
19
- $theme = wp_get_theme();
20
- echo esc_html($theme->Name . ' ' . $theme->Version);
21
- }
22
- ?>
23
-
24
- URLOpen Method: <?php echo esc_html(rplg_url_method()); ?>
25
-
26
- URLOpen allow: <?php $urlopen = rplg_json_urlopen('https://graph.facebook.com/2/ratings');
27
- echo ($urlopen && $urlopen->error) ? strlen($urlopen->error->message) > 0 : false; ?>
28
-
29
- Plugin Version: <?php echo esc_html($version); ?>
30
-
31
- Settings:
32
- <?php foreach ($options as $opt) {
33
- echo esc_html($opt.': '.get_option($opt)."\n");
34
- }
35
- ?>
36
-
37
- Widgets: <?php $widget = get_option($widget_name); echo ($widget ? print_r($widget) : '')."\n"; ?>
38
-
39
- Plugins:
40
- <?php
41
- foreach (get_plugins() as $key => $plugin) {
42
- $isactive = "";
43
- if (is_plugin_active($key)) {
44
- $isactive = "(active)";
45
- }
46
- echo esc_html($plugin['Name'].' '.$plugin['Version'].' '.$isactive."\n");
47
- }
48
- }
49
-
50
- }
51
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/admin/class-admin-feed-columns.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes\Admin;
4
+
5
+ use WP_Rplg_Google_Reviews\Includes\Post_Types;
6
+
7
+ class Admin_Feed_Columns {
8
+
9
+ private static $plugin_themes = array(
10
+ 'list' => 'List',
11
+ );
12
+
13
+ public function __construct($feed_deserializer) {
14
+ $this->feed_deserializer = $feed_deserializer;
15
+ }
16
+
17
+ public function register() {
18
+ add_filter('get_edit_post_link', array($this, 'change_edit_post_link'), 10, 3);
19
+ add_filter('manage_edit-' . Post_Types::FEED_POST_TYPE . '_columns', array($this, 'get_columns'));
20
+ add_action('manage_' . Post_Types::FEED_POST_TYPE . '_posts_custom_column', array($this, 'render'), 10, 2);
21
+ add_filter('post_row_actions', array($this, 'change_post_row_actions'), 10, 2);
22
+ add_filter('get_the_excerpt', array($this, 'hide_grw_feed_excerpt'), 10, 2);
23
+ }
24
+
25
+ public function change_edit_post_link($link, $id, $context) {
26
+ if (function_exists('get_current_screen')) {
27
+ $screen = get_current_screen();
28
+ if (empty($screen) || $screen->post_type !== Post_Types::FEED_POST_TYPE) {
29
+ return $link;
30
+ }
31
+ return admin_url('admin.php?page=grw-builder&' . Post_Types::FEED_POST_TYPE . '_id=' . $id);
32
+ } else {
33
+ return;
34
+ }
35
+ }
36
+
37
+ public function get_columns($columns) {
38
+ $columns = $columns;
39
+ $columns = array(
40
+ 'cb' => '<input type="checkbox">',
41
+ 'title' => __('Title', 'grw'),
42
+ 'ID' => __('ID', 'grw'),
43
+ 'grw_theme' => __('Theme', 'grw'),
44
+ 'date' => __('Date', 'grw'),
45
+ );
46
+ return $columns;
47
+ }
48
+
49
+ public function render($column_name, $post_id) {
50
+ $args = array();
51
+
52
+ if (isset($_GET['post_status'])) {
53
+ $post_status = sanitize_text_field(wp_unslash($_GET['post_status']));
54
+
55
+ if ($post_status === 'trash') {
56
+ $args['post_status'] = array('trash');
57
+ }
58
+ }
59
+
60
+ $feed = $this->feed_deserializer->get_feed($post_id, $args);
61
+ if (!$feed) {
62
+ return null;
63
+ }
64
+
65
+ $connection = json_decode($feed->post_content);
66
+
67
+ switch ($column_name) {
68
+ case 'ID':
69
+ echo $feed->ID;
70
+ break;
71
+ case 'grw_theme':
72
+ echo isset($connection->options->view_mode) ? self::$plugin_themes[$connection->options->view_mode] : 'List';
73
+ break;
74
+ }
75
+ }
76
+
77
+ public function change_post_row_actions($actions, $post) {
78
+ if (isset($actions) && $post->post_type === Post_Types::FEED_POST_TYPE) {
79
+ $changed_actions = array(
80
+ 'post-id' => '<span class="grw-admin-column-action">ID: ' . $post->ID . '</span>',
81
+ );
82
+ $actions = $changed_actions + $actions;
83
+ }
84
+ return $actions;
85
+ }
86
+
87
+ public function hide_grw_feed_excerpt($excerpt, $post = null) {
88
+ return $post->post_type !== Post_Types::FEED_POST_TYPE ? $excerpt : '';
89
+ }
90
+ }
includes/admin/class-admin-menu.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes\Admin;
4
+
5
+ use WP_Rplg_Google_Reviews\Includes\Post_Types;
6
+
7
+ class Admin_Menu {
8
+
9
+ public function __construct() {
10
+ }
11
+
12
+ public function register() {
13
+ add_action('admin_menu', array($this, 'add_page'));
14
+ add_action('admin_menu', array($this, 'add_subpages'));
15
+ add_filter('submenu_file', array($this, 'remove_submenu_pages'));
16
+ add_filter('admin_body_class', array($this, 'add_admin_body_class'));
17
+ }
18
+
19
+ public function add_page() {
20
+ add_menu_page(
21
+ 'Google Reviews Plugin',
22
+ 'Google Reviews',
23
+ 'edit_posts',
24
+ 'grw',
25
+ '',
26
+ GRW_ASSETS_URL . 'img/menu_icon.png',
27
+ 25
28
+ );
29
+ }
30
+
31
+ public function add_subpages() {
32
+ $builder_page = new Admin_Page(
33
+ 'grw',
34
+ 'Reviews Builder',
35
+ 'Builder',
36
+ 'edit_posts',
37
+ 'grw-builder'
38
+ );
39
+ $builder_page->add_page();
40
+
41
+ $setting_page = new Admin_Page(
42
+ 'grw',
43
+ 'Settings',
44
+ 'Settings',
45
+ 'manage_options',
46
+ 'grw-settings'
47
+ );
48
+ $setting_page->add_page();
49
+
50
+ $setting_page = new Admin_Page(
51
+ 'grw',
52
+ 'Support',
53
+ 'Support',
54
+ 'manage_options',
55
+ 'grw-support'
56
+ );
57
+ $setting_page->add_page();
58
+ }
59
+
60
+ public function remove_submenu_pages($submenu_file) {
61
+ global $plugin_page;
62
+
63
+ $hidden_pages = array(
64
+ 'grw-builder',
65
+ );
66
+
67
+ if ($plugin_page && in_array($plugin_page, $hidden_pages)) {
68
+ $submenu_file = 'edit.php?post_type=' . Post_Types::FEED_POST_TYPE;
69
+ }
70
+
71
+ foreach ($hidden_pages as $page) {
72
+ remove_submenu_page('grw', $page);
73
+ }
74
+
75
+ return $submenu_file;
76
+ }
77
+
78
+ public function add_admin_body_class($classes) {
79
+ $current_screen = get_current_screen();
80
+
81
+ if (empty($current_screen)) {
82
+ return;
83
+ }
84
+
85
+ if (strpos($current_screen->id, 'grw') !== false) {
86
+ $classes .= ' grw-admin ';
87
+ }
88
+ return $classes;
89
+ }
90
+
91
+ }
includes/admin/class-admin-notice.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes\Admin;
4
+
5
+ class Admin_Notice {
6
+
7
+ private static $plugin_notices = array(
8
+ 'settings_active_0' => 'Plugin disabled successfully.',
9
+ 'settings_active_1' => 'Plugin enabled successfully.',
10
+ 'settings_save' => 'Settings saved successfully.',
11
+ 'settings_create_db' => 'Database re-created successfully.',
12
+ 'settings_reset' => 'Settings deleted successfully.',
13
+ 'settings_install' => 'Plugin installed from scratch successfully.',
14
+ 'settings_reset_all' => 'All data including settings and reviews deleted successfully.',
15
+ );
16
+
17
+ public function register() {
18
+ add_filter('removable_query_args', array($this, 'remove_query_args'));
19
+ add_action('admin_notices', array($this, 'parse_notices_from_url'));
20
+ add_action('admin_notices', array($this, 'render_notices'));
21
+ }
22
+
23
+ public function remove_query_args($args) {
24
+ return array_merge($args, array('grw_notice'));
25
+ }
26
+
27
+ public function parse_notices_from_url() {
28
+ if (!isset($_GET['grw_notice'])) {
29
+ return;
30
+ }
31
+
32
+ $this->notice_id = sanitize_text_field(wp_unslash($_GET['grw_notice']));
33
+ }
34
+
35
+ public function render_notices() {
36
+ if (empty($this->notice_id) || !$this->is_valid_screen()) {
37
+ return;
38
+ }
39
+
40
+ if (doing_action('admin_notices') && $this->needs_repositioned()) {
41
+ add_action('grw_admin_notices', array($this, 'render_notices'));
42
+ return;
43
+ }
44
+
45
+ ?>
46
+ <div class="notice notice-success is-dismissible">
47
+ <p><?php echo $this->notice_id != 'custom_msg' ? self::$plugin_notices[$this->notice_id] : get_option('grw_notice_msg'); ?></p>
48
+ </div>
49
+ <?php
50
+
51
+ $this->notice_id = '';
52
+ }
53
+
54
+ protected function is_valid_screen($screen_id = '') {
55
+ if ($screen_id === '') {
56
+ $screen = get_current_screen();
57
+ $screen_id = $screen->id;
58
+ }
59
+
60
+ return ($screen_id === 'dashboard' || $screen_id === 'plugins' || strpos($screen_id, 'grw') !== false) ? true : false;
61
+ }
62
+
63
+ protected function needs_repositioned($screen_id = '') {
64
+ if ($screen_id === '') {
65
+ $screen = get_current_screen();
66
+ $screen_id = $screen->id;
67
+ }
68
+
69
+ $screen_ids = array('google-reviews_page_grw-settings');
70
+ return in_array($screen_id, $screen_ids) ? true : false;
71
+ }
72
+
73
+ }
includes/admin/class-admin-page.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes\Admin;
4
+
5
+ class Admin_Page {
6
+
7
+ public function __construct($parent_slug, $page_title, $menu_title, $capability, $menu_slug) {
8
+ $this->parent_slug = $parent_slug;
9
+ $this->page_title = $page_title;
10
+ $this->menu_title = $menu_title;
11
+ $this->capability = $capability;
12
+ $this->menu_slug = $menu_slug;
13
+ }
14
+
15
+ public function add_page() {
16
+ add_submenu_page(
17
+ $this->parent_slug,
18
+ $this->page_title,
19
+ $this->menu_title,
20
+ $this->capability,
21
+ $this->menu_slug,
22
+ array($this, 'render')
23
+ );
24
+ }
25
+
26
+ public function render() {
27
+ echo '<div class="grw-admin-page">';
28
+ do_action("grw_admin_page_{$this->menu_slug}");
29
+ echo '</div>';
30
+ }
31
+ }
includes/admin/class-admin-rev.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes\Admin;
4
+
5
+ class Admin_Rev {
6
+
7
+ public function register() {
8
+ add_action('admin_notices', array($this, 'leaverev'));
9
+ }
10
+
11
+ public function leaverev() {
12
+ $activation_time = get_option('grw_activation_time');
13
+
14
+ if ($activation_time == '') {
15
+ $activation_time = time() - 86400*3;
16
+ update_option('grw_activation_time', $activation_time);
17
+ }
18
+
19
+ $rev_notice = isset($_GET['grw_rev_notice']) ? $_GET['grw_rev_notice'] : '';
20
+ if ($rev_notice == 'later') {
21
+ $activation_time = time() - 86400*3;
22
+ update_option('grw_activation_time', $activation_time);
23
+ update_option('grw_rev_notice_hide', 'later');
24
+ } else if ($rev_notice == 'never') {
25
+ update_option('grw_rev_notice_hide', 'never');
26
+ }
27
+
28
+ $rev_notice_hide = get_option('grw_rev_notice_hide');
29
+ $rev_notice_show = get_option('rplg_rev_notice_show');
30
+
31
+ if ($rev_notice_show == '' || $rev_notice_show == 'grw') {
32
+
33
+ if ($rev_notice_hide != 'never' && $activation_time < (time() - 86400*5)) {
34
+ update_option('rplg_rev_notice_show', 'grw');
35
+ $class = 'notice notice-info is-dismissible';
36
+ $url = remove_query_arg(array('taction', 'tid', 'sortby', 'sortdir', 'opt'));
37
+ $url_later = esc_url(add_query_arg('grw_rev_notice', 'later', $url));
38
+ $url_never = esc_url(add_query_arg('grw_rev_notice', 'never', $url));
39
+
40
+ $notice = '<p style="font-weight:normal;">' .
41
+ 'Hey, I am happy to see that you\'ve been using our <b>Google Reviews Widget</b> plugin for a while now – that’s awesome!<br>' .
42
+ 'Could you please do me a BIG favor and give it a 5-star rating on WordPress?<br><br>' .
43
+ '-- Thanks! Daniel K.' .
44
+ '</p>' .
45
+ '<p>' .
46
+ '<a href="https://wordpress.org/support/plugin/widget-google-reviews/reviews/#new-post" style="text-decoration:none;" target="_blank">' .
47
+ '<button class="button button-primary" style="margin-right:5px;">OK, you deserve it</button>' .
48
+ '</a>' .
49
+ '<a href="' . $url_later . '" style="text-decoration:none;">' .
50
+ '<button class="button button-secondary">Not now, maybe later</button>' .
51
+ '</a>' .
52
+ '<a href="' . $url_never . '" style="text-decoration:none;">' .
53
+ '<button class="button button-secondary" style="float:right;">Do not remind me again</button>' .
54
+ '</a>' .
55
+ '</p>' .
56
+ '<p style="color:#999;font-size:12px;">' .
57
+ 'By the way, if you have been thinking about upgrading to the ' .
58
+ '<a href="https://richplugins.com/business-reviews-bundle-wordpress-plugin" target="_blank">Business</a> ' .
59
+ 'version, here is a 25% off onboard coupon -> <b>business25off</b>' .
60
+ '</p>';
61
+
62
+ printf('<div class="%1$s" style="position:fixed;top:50px;right:20px;padding-right:30px;z-index:2;margin-left:20px">%2$s</div>', esc_attr($class), $notice);
63
+ } else {
64
+ update_option('rplg_rev_notice_show', '');
65
+ }
66
+
67
+ }
68
+ }
69
+ }
includes/admin/class-admin-tophead.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes\Admin;
4
+
5
+ class Admin_Tophead {
6
+
7
+ public function register() {
8
+ add_action('wp_after_admin_bar_render', array($this, 'render'));
9
+ }
10
+
11
+ public function render() {
12
+ $current_screen = get_current_screen();
13
+
14
+ if (empty($current_screen)) {
15
+ return;
16
+ }
17
+
18
+ if (strpos($current_screen->id, 'grw') !== false) {
19
+
20
+ $current_screen->render_screen_meta();
21
+
22
+ ?>
23
+ <div class="grw-tophead">
24
+ <div class="grw-tophead-title">
25
+ <!--span class="grw-tophead-logo" style="position: relative; margin-right: 10px; vertical-align: middle">
26
+ <svg width="32" height="32" viewBox="0 0 1792 1792"><path d="M1728 647q0 22-26 48l-363 354 86 500q1 7 1 20 0 21-10.5 35.5t-30.5 14.5q-19 0-40-12l-449-236-449 236q-22 12-40 12-21 0-31.5-14.5t-10.5-35.5q0-6 2-20l86-500-364-354q-25-27-25-48 0-37 56-46l502-73 225-455q19-41 49-41t49 41l225 455 502 73q56 9 56 46z" fill="#FABB08"></path></svg>
27
+ <svg width="18" height="18" viewBox="-5 -5 10 10" style="position: absolute;bottom: 2px;right: 4px;outline: 2px solid #fff;border-radius: 50%;background: #fff;">
28
+ <defs>
29
+ <path id="a" d="M 3 0 A 3.1 3.1 0 0 0 0 -3 L 0 -5 A 5 5 0 0 1 5 0"/>
30
+ </defs>
31
+ <use xlink:href="#a" fill="#4285F4" transform="rotate(45)"/>
32
+ <use xlink:href="#a" fill="#34A853" transform="rotate(135)"/>
33
+ <use xlink:href="#a" fill="#FABB08" transform="rotate(225)"/>
34
+ <use xlink:href="#a" fill="#E94135" transform="rotate(315)"/>
35
+ </svg>
36
+ <svg width="12" height="12" viewBox="0 0 512 512" style="position: absolute; bottom: 7px; right: 9px; width: 8px; height: 8px; border-radius: 50%;"><path fill="#34A853" d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z" style="
37
+ "></path></svg>
38
+ </span!-->
39
+ <img src="<?php esc_attr_e(GRW_ASSETS_URL . 'img/logo.png') ?>" alt="logo">
40
+ Google Reviews
41
+ </div>
42
+ <span class="rplg-version">Free Version: <?php echo GRW_VERSION; ?></span>
43
+ </div>
44
+ <?php
45
+ }
46
+ }
47
+ }
includes/class-activator.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ use WP_Rplg_Google_Reviews\Includes\Core\Database;
6
+
7
+ class Activator {
8
+
9
+ public function __construct(Database $database) {
10
+ $this->database = $database;
11
+ }
12
+
13
+ public function options() {
14
+ return array(
15
+ 'grw_version',
16
+ 'grw_active',
17
+ 'grw_google_api_key',
18
+ 'grw_language',
19
+ 'grw_activation_time',
20
+ 'grw_rev_notice_hide',
21
+ 'rplg_rev_notice_show',
22
+ 'grw_debug_refresh',
23
+ );
24
+ }
25
+
26
+ public function register() {
27
+ add_action('init', array($this, 'check_version'));
28
+ }
29
+
30
+ public function check_version() {
31
+ if (version_compare(get_option('grw_version'), GRW_VERSION, '<')) {
32
+ $this->activate();
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Activates the plugin on a multisite
38
+ *
39
+ * @since 2.0.0
40
+ */
41
+ public function activate() {
42
+ $network_wide = get_option('grw_is_multisite');
43
+ if ($network_wide) {
44
+ $this->activate_multisite();
45
+ } else {
46
+ $this->activate_single_site();
47
+ }
48
+ }
49
+
50
+ private function activate_multisite() {
51
+ global $wpdb;
52
+
53
+ $site_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
54
+
55
+ foreach($site_ids as $site_id) {
56
+ switch_to_blog($site_id);
57
+ $this->activate_single_site();
58
+ restore_current_blog();
59
+ }
60
+ }
61
+
62
+ private function activate_single_site() {
63
+ $current_version = GRW_VERSION;
64
+ $last_active_version = get_option('grw_version');
65
+
66
+ if (empty($last_active_version)) {
67
+ $this->first_install();
68
+ update_option('grw_version', $current_version);
69
+ } elseif ($last_active_version !== $current_version) {
70
+ $this->exist_install($current_version, $last_active_version);
71
+ update_option('grw_version', $current_version);
72
+ }
73
+ }
74
+
75
+ private function first_install() {
76
+ $this->database->create();
77
+
78
+ add_option('grw_active', '1');
79
+ add_option('grw_google_api_key', '');
80
+ }
81
+
82
+ private function exist_install($current_version, $last_active_version) {
83
+ global $wpdb;
84
+
85
+ switch($last_active_version) {
86
+ case version_compare($last_active_version, '1.8.2', '<'):
87
+ $wpdb->query("ALTER TABLE " . $wpdb->prefix . Database::BUSINESS_TABLE . " ADD review_count INTEGER");
88
+ $place_ids = $wpdb->get_col("SELECT place_id FROM " . $wpdb->prefix . Database::BUSINESS_TABLE . " WHERE rating > 0 LIMIT 5");
89
+ foreach($place_ids as $place_id) {
90
+ //TODO: grw_refresh_reviews(array($place_id));
91
+ }
92
+ break;
93
+ case version_compare($last_active_version, '1.8.7', '<'):
94
+ $row = $wpdb->get_results(
95
+ "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS " .
96
+ "WHERE table_name = '" . $wpdb->prefix . Database::REVIEW_TABLE . "' AND column_name = 'hide'"
97
+ );
98
+ if(empty($row)){
99
+ $wpdb->query("ALTER TABLE " . $wpdb->prefix . Database::REVIEW_TABLE . " ADD hide VARCHAR(1) DEFAULT '' NOT NULL");
100
+ }
101
+ break;
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Creates the plugin database on a multisite
107
+ *
108
+ * @since 2.0.0
109
+ */
110
+ public function create_db() {
111
+ $network_wide = get_option('grw_is_multisite');
112
+ if ($network_wide) {
113
+ $this->create_db_multisite();
114
+ } else {
115
+ $this->create_db_single_site();
116
+ }
117
+ }
118
+
119
+ private function create_db_multisite() {
120
+ global $wpdb;
121
+
122
+ $site_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
123
+
124
+ foreach($site_ids as $site_id) {
125
+ switch_to_blog($site_id);
126
+ $this->create_db_single_site();
127
+ restore_current_blog();
128
+ }
129
+ }
130
+
131
+ private function create_db_single_site() {
132
+ $this->database->create();
133
+ }
134
+
135
+ /**
136
+ * Drops the plugin database on a multisite
137
+ *
138
+ * @since 2.0.0
139
+ */
140
+ public function drop_db($multisite = false) {
141
+ $network_wide = get_option('grw_is_multisite');
142
+ if ($multisite && $network_wide) {
143
+ $this->drop_db_multisite();
144
+ } else {
145
+ $this->drop_db_single_site();
146
+ }
147
+ }
148
+
149
+ private function drop_db_multisite() {
150
+ global $wpdb;
151
+
152
+ $site_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
153
+
154
+ foreach($site_ids as $site_id) {
155
+ switch_to_blog($site_id);
156
+ $this->drop_db_single_site();
157
+ restore_current_blog();
158
+ }
159
+ }
160
+
161
+ private function drop_db_single_site() {
162
+ $this->database->drop();
163
+ }
164
+
165
+ /**
166
+ * Delete all options of the plugin on a multisite
167
+ *
168
+ * @since 2.0.0
169
+ */
170
+ public function delete_all_options($multisite = false) {
171
+ $network_wide = get_option('grw_is_multisite');
172
+ if ($multisite && $network_wide) {
173
+ $this->delete_all_options_multisite();
174
+ } else {
175
+ $this->delete_all_options_single_site();
176
+ }
177
+ }
178
+
179
+ private function delete_all_options_multisite() {
180
+ global $wpdb;
181
+
182
+ $site_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
183
+
184
+ foreach($site_ids as $site_id) {
185
+ switch_to_blog($site_id);
186
+ $this->delete_all_options_single_site();
187
+ restore_current_blog();
188
+ }
189
+ }
190
+
191
+ private function delete_all_options_single_site() {
192
+ foreach ($this->options() as $opt) {
193
+ delete_option($opt);
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Delete all feeds of the plugin on a multisite
199
+ *
200
+ * @since 2.0.0
201
+ */
202
+ public function delete_all_feeds($multisite = false) {
203
+ $network_wide = get_option('grw_is_multisite');
204
+ if ($multisite && $network_wide) {
205
+ $this->delete_all_feeds_multisite();
206
+ } else {
207
+ $this->delete_all_feeds_single_site();
208
+ }
209
+ }
210
+
211
+ private function delete_all_feeds_multisite() {
212
+ global $wpdb;
213
+
214
+ $site_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
215
+
216
+ foreach($site_ids as $site_id) {
217
+ switch_to_blog($site_id);
218
+ $this->delete_all_feeds_single_site();
219
+ restore_current_blog();
220
+ }
221
+ }
222
+
223
+ private function delete_all_feeds_single_site() {
224
+ $args = array(
225
+ 'post_type' => Post_Types::FEED_POST_TYPE,
226
+ 'post_status' => array('any', 'trash'),
227
+ 'posts_per_page' => -1,
228
+ 'fields' => 'ids',
229
+ );
230
+
231
+ $query = new \WP_Query($args);
232
+ $grw_posts = $query->posts;
233
+
234
+ if (!empty($grw_posts)) {
235
+ foreach ($grw_posts as $grw_post) {
236
+ wp_delete_post($grw_post, true);
237
+ }
238
+ }
239
+ }
240
+
241
+ }
includes/class-assets.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ class Assets {
6
+
7
+ private $url;
8
+ private $version;
9
+ private $suffix;
10
+
11
+ private static $css_assets = array(
12
+ 'feedbuilder' => 'css/feedbuilder',
13
+ 'grw-admin-css' => 'css/admin',
14
+ 'grw-rplg-css' => 'css/rplg-wp',
15
+ 'grw-setting-css' => 'css/rplg-setting',
16
+ 'grw-css' => 'css/google-review',
17
+ );
18
+
19
+ private static $js_assets = array(
20
+ 'grw-admin-js' => 'js/admin',
21
+ 'feedbuilder' => 'js/feedbuilder',
22
+ 'grw-time-js' => 'js/wpac-time',
23
+ 'grw-wpac-js' => 'js/wpac',
24
+ 'blazy-js' => 'js/blazy.min',
25
+ 'grw-js' => 'js/rplg',
26
+ );
27
+
28
+ public function __construct($url, $version) {
29
+ $this->url = $url;
30
+ $this->version = $version;
31
+ $this->suffix = '';
32
+ }
33
+
34
+ public function register() {
35
+ if (is_admin()) {
36
+ add_action('admin_enqueue_scripts', array($this, 'register_styles'));
37
+ add_action('admin_enqueue_scripts', array($this, 'register_scripts'));
38
+ add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_styles'));
39
+ add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
40
+ } else {
41
+ add_action('wp_enqueue_scripts', array($this, 'register_styles'));
42
+ add_action('wp_enqueue_scripts', array($this, 'register_scripts'));
43
+ $grw_demand_assets = get_option('grw_demand_assets');
44
+ if (!$grw_demand_assets || $grw_demand_assets != 'true') {
45
+ add_action('wp_enqueue_scripts', array($this, 'enqueue_public_styles'));
46
+ add_action('wp_enqueue_scripts', array($this, 'enqueue_public_scripts'));
47
+ }
48
+ }
49
+ }
50
+
51
+ public function register_styles() {
52
+ $this->register_styles_loop(array('feedbuilder', 'grw-admin-css', 'grw-rplg-css', 'grw-setting-css', 'grw-css'));
53
+ }
54
+
55
+ public function register_scripts() {
56
+ $this->register_scripts_loop(array('grw-admin-js', 'feedbuilder', 'grw-time-js', 'grw-wpac-js', 'blazy-js', 'grw-js'));
57
+ }
58
+
59
+ public function enqueue_admin_styles() {
60
+ wp_enqueue_style('feedbuilder');
61
+ wp_enqueue_style('grw-admin-css');
62
+ wp_enqueue_style('grw-rplg-css');
63
+ wp_enqueue_style('grw-setting-css');
64
+ wp_enqueue_style('grw-css');
65
+ }
66
+
67
+ public function enqueue_admin_scripts() {
68
+ wp_enqueue_script('jquery');
69
+ wp_enqueue_script('jquery-ui-core');
70
+ wp_enqueue_script('jquery-ui-draggable');
71
+ wp_enqueue_script('jquery-ui-sortable');
72
+
73
+ wp_enqueue_script('grw-wpac-js');
74
+ wp_enqueue_script('grw-admin-js');
75
+
76
+ wp_localize_script('feedbuilder', 'GRW_VARS', array(
77
+ 'googleAPIKey' => get_option('grw_google_api_key'),
78
+ 'GOOGLE_AVATAR' => GRW_GOOGLE_AVATAR,
79
+ 'handlerUrl' => admin_url('options-general.php?page=grw'),
80
+ 'supportUrl' => admin_url('admin.php?page=grw-support'),
81
+ 'actionPrefix' => 'grw',
82
+ 'wordpress' => true,
83
+ ));
84
+ wp_enqueue_script('feedbuilder');
85
+
86
+ wp_enqueue_script('grw-time-js');
87
+ wp_enqueue_script('blazy-js');
88
+ wp_enqueue_script('grw-js');
89
+ }
90
+
91
+ public function enqueue_public_styles() {
92
+ wp_enqueue_style('grw-css');
93
+ }
94
+
95
+ public function enqueue_public_scripts() {
96
+ wp_enqueue_script('grw-time-js');
97
+ //wp_enqueue_script('blazy-js');
98
+ wp_enqueue_script('grw-js');
99
+ }
100
+
101
+ public function get_public_styles() {
102
+ return array($this->get_css_asset('grw-css'));
103
+ }
104
+
105
+ public function get_public_scripts() {
106
+ return array(
107
+ $this->get_js_asset('grw-time-js'),
108
+ $this->get_js_asset('blazy-js'),
109
+ $this->get_js_asset('grw-js'),
110
+ );
111
+ }
112
+
113
+ private function register_styles_loop($styles) {
114
+ foreach ($styles as $style) {
115
+ wp_register_style($style, $this->get_css_asset($style), array(), $this->version);
116
+ }
117
+ }
118
+
119
+ private function register_scripts_loop($scripts) {
120
+ foreach ($scripts as $script) {
121
+ wp_register_script($script, $this->get_js_asset($script), array(), $this->version);
122
+ }
123
+ }
124
+
125
+ private function get_css_asset($asset) {
126
+ return $this->url . self::$css_assets[$asset] . $this->suffix . '.css';
127
+ }
128
+
129
+ private function get_js_asset($asset) {
130
+ return $this->url . self::$js_assets[$asset] . $this->suffix . '.js';
131
+ }
132
+
133
+ }
includes/class-builder-page.php ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ use WP_Rplg_Google_Reviews\Includes\Core\Core;
6
+
7
+ class Builder_Page {
8
+
9
+ public function __construct(Feed_Deserializer $feed_deserializer, Core $core, View $view) {
10
+ $this->feed_deserializer = $feed_deserializer;
11
+ $this->core = $core;
12
+ $this->view = $view;
13
+ }
14
+
15
+ public function register() {
16
+ add_action('grw_admin_page_grw-builder', array($this, 'init'));
17
+ }
18
+
19
+ public function init() {
20
+ if (isset($_GET['grw_notice'])) {
21
+ $this->add_admin_notice();
22
+ }
23
+
24
+ $feed = null;
25
+ if (isset($_GET[Post_Types::FEED_POST_TYPE . '_id'])) {
26
+ $feed = $this->feed_deserializer->get_feed(sanitize_text_field(wp_unslash($_GET[Post_Types::FEED_POST_TYPE . '_id'])));
27
+ }
28
+
29
+ $this->render($feed);
30
+ }
31
+
32
+ public function add_admin_notice($notice_code = 0) {
33
+
34
+ }
35
+
36
+ public function render($feed) {
37
+ global $wp_version;
38
+ if (version_compare($wp_version, '3.5', '>=')) {
39
+ wp_enqueue_media();
40
+ }
41
+
42
+ wp_nonce_field('grw_wpnonce', 'grw_nonce');
43
+
44
+ $feed_id = '';
45
+ $feed_post_title = '';
46
+ $feed_content = '';
47
+ $feed_inited = false;
48
+ $businesses = null;
49
+ $reviews = null;
50
+
51
+ if ($feed != null) {
52
+ $feed_id = $feed->ID;
53
+ $feed_post_title = $feed->post_title;
54
+ $feed_content = trim($feed->post_content);
55
+
56
+ $data = $this->core->get_reviews($feed, true);
57
+ $businesses = $data['businesses'];
58
+ $reviews = $data['reviews'];
59
+ $options = $data['options'];
60
+ if (isset($businesses) && count($businesses) || isset($reviews) && count($reviews)) {
61
+ $feed_inited = true;
62
+ }
63
+ }
64
+
65
+ ?>
66
+ <div class="grw-builder">
67
+ <form method="post" action="<?php echo esc_url(admin_url('admin-post.php?action=' . Post_Types::FEED_POST_TYPE . '_save')); ?>">
68
+ <input type="hidden" name="<?php echo Post_Types::FEED_POST_TYPE; ?>[post_id]" value="<?php echo esc_attr($feed_id); ?>">
69
+ <input type="hidden" name="<?php echo Post_Types::FEED_POST_TYPE; ?>[current_url]" value="<?php echo home_url($_SERVER['REQUEST_URI']); ?>">
70
+ <div class="grw-builder-workspace">
71
+ <div class="grw-toolbar">
72
+ <div class="grw-toolbar-title">
73
+ <input id="grw_title" class="grw-toolbar-title-input" type="text" name="<?php echo Post_Types::FEED_POST_TYPE; ?>[title]" value="<?php if (isset($feed_post_title)) { echo $feed_post_title; } ?>" placeholder="Enter a widget name" maxlength="255" autofocus>
74
+ </div>
75
+ <div class="grw-toolbar-control">
76
+ <?php if ($feed_inited) { ?>
77
+ <label>
78
+ <span id="grw_sc_msg">Shortcode </span>
79
+ <input id="grw_sc" type="text" value="[grw id=&quot;<?php echo esc_attr($feed_id); ?>&quot;]" data-grw-shortcode="[grw id=&quot;<?php echo esc_attr($feed_id); ?>&quot;]" onclick="this.select(); document.execCommand('copy'); window.grw_sc_msg.innerHTML = 'Shortcode Copied! ';" readonly/>
80
+ </label>
81
+ <div class="grw-toolbar-options">
82
+ <label title="Sometimes, you need to use this shortcode in PHP, for instance in header.php or footer.php files, in this case use this option"><input type="checkbox" onclick="var el = window.grw_sc; if (this.checked) { el.value = '&lt;?php echo do_shortcode( \'' + el.getAttribute('data-grw-shortcode') + '\' ); ?&gt;'; } else { el.value = el.getAttribute('data-grw-shortcode'); } el.select();document.execCommand('copy'); window.grw_sc_msg.innerHTML = 'Shortcode Copied! ';"/>Use in PHP</label>
83
+ </div>
84
+ <?php } ?>
85
+ <button id="grw_save" type="submit" class="button button-primary">Save & Update</button>
86
+ </div>
87
+ </div>
88
+ <div class="grw-builder-preview">
89
+ <textarea id="grw-builder-connection" name="<?php echo Post_Types::FEED_POST_TYPE; ?>[content]" style="display:none"><?php echo $feed_content; ?></textarea>
90
+ <?php
91
+ if ($feed_inited) {
92
+ echo $this->view->render($feed_id, $businesses, $reviews, $options, true);
93
+ } else {
94
+ ?>To show reviews in this preview, firstly connect it on the right menu (CONNECT GOOGLE) and click
95
+ '<b>Save & Update</b>' button. Then you can use this created widget on a sidebar or through a shortcode.<?php
96
+ }
97
+ ?>
98
+ </div>
99
+ </div>
100
+ <div id="grw-builder-option" class="grw-builder-options"></div>
101
+ </form>
102
+ </div>
103
+ <script>
104
+ jQuery(document).ready(function($) {
105
+ function grw_builder_init_listener(attempts) {
106
+ if (!window.grw_builder_init) {
107
+ if (attempts > 0) {
108
+ setTimeout(function() { grw_builder_init_listener(attempts - 1); }, 200);
109
+ }
110
+ return;
111
+ }
112
+ grw_builder_init($, {
113
+ el: '#grw-builder-option',
114
+ use_gpa: true,
115
+ <?php if (strlen($feed_content) > 0) { ?>
116
+ conns: <?php echo $feed_content; ?>
117
+ <?php } ?>
118
+ });
119
+ }
120
+ grw_builder_init_listener(20);
121
+ });
122
+ </script>
123
+ <style>
124
+ .update-nag { display: none; }
125
+ </style>
126
+ <?php
127
+ }
128
+ }
includes/class-deactivator.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ class Deactivator {
6
+
7
+ public function deactivate() {
8
+
9
+ }
10
+
11
+ }
includes/class-debug-info.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ use WP_Rplg_Google_Reviews\Includes\Core\Database;
6
+
7
+ class Debug_Info {
8
+
9
+ public function __construct(Activator $activator) {
10
+ $this->activator = $activator;
11
+ }
12
+
13
+ public function render() {
14
+ global $wpdb;
15
+ global $wp_version;
16
+
17
+ ?>
18
+
19
+ URL: <?php echo esc_url(get_option('siteurl')); ?>
20
+
21
+ PHP Version: <?php echo esc_html(phpversion()); ?>
22
+
23
+ WP Version: <?php echo esc_html($wp_version); ?>
24
+
25
+ Active Theme:
26
+ <?php
27
+ if (!function_exists('wp_get_theme')) {
28
+ $theme = get_theme(get_current_theme());
29
+ echo esc_html($theme['Name'] . ' ' . $theme['Version']);
30
+ } else {
31
+ $theme = wp_get_theme();
32
+ echo esc_html($theme->Name . ' ' . $theme->Version);
33
+ }
34
+ ?>
35
+
36
+ Outgoing HTTPS requests: <?php
37
+ $res = wp_remote_get('https://app.trust.reviews/checkconn');
38
+ $body = wp_remote_retrieve_body($res);
39
+ echo ($body && $body == 'success') ? 1 : 'Outgoing HTTPS requests are closed'; ?>
40
+
41
+ Plugin Version: <?php echo esc_html(GRW_VERSION); ?>
42
+
43
+ Settings:
44
+ <?php foreach ($this->activator->options() as $opt) {
45
+ echo esc_html($opt.': '.get_option($opt)."\n");
46
+ }
47
+ ?>
48
+
49
+ Widgets: <?php $widget = get_option('widget_grw_widget'); echo ($widget ? print_r($widget) : '')."\n"; ?>
50
+
51
+ Plugins:
52
+ <?php
53
+ foreach (get_plugins() as $key => $plugin) {
54
+ $isactive = "";
55
+ if (is_plugin_active($key)) {
56
+ $isactive = "(active)";
57
+ }
58
+ echo esc_html($plugin['Name'].' '.$plugin['Version'].' '.$isactive."\n");
59
+ }
60
+ ?>
61
+
62
+ ------------ Feeds ------------
63
+
64
+ <?php
65
+ $wp_query = new \WP_Query();
66
+ $wp_query->query(array(
67
+ 'post_type' => Post_Types::FEED_POST_TYPE,
68
+ 'fields' => array('ID', 'post_title', 'post_content'),
69
+ 'posts_per_page' => 300,
70
+ 'no_found_rows' => true,
71
+ ));
72
+ $feeds = $wp_query->posts;
73
+ foreach ($feeds as $feed) {
74
+ echo $feed->ID . " " . $feed->post_title . ": " . $feed->post_content . "\r\n\r\n";
75
+ }
76
+ ?>
77
+
78
+ <?php
79
+ $places = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . Database::BUSINESS_TABLE);
80
+ $places_error = $wpdb->last_error;
81
+ $reviews = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . Database::REVIEW_TABLE);
82
+ $reviews_error = $wpdb->last_error; ?>
83
+
84
+ ------------ Places ------------
85
+
86
+ <?php if (isset($places_error) && strlen($places_error) > 0) { echo 'DB Places error: ' . $places_error; } ?>
87
+
88
+ <?php echo print_r($places); ?>
89
+
90
+
91
+ ------------ Reviews ------------
92
+
93
+ <?php if (isset($reviews_error) && strlen($reviews_error) > 0) { echo 'DB Reviews error: ' . $reviews_error; } ?>
94
+
95
+ <?php echo print_r($reviews);
96
+
97
+ }
98
+
99
+ }
includes/class-feed-deserializer.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ class Feed_Deserializer {
6
+
7
+ public function __construct(\WP_Query $wp_query) {
8
+ $this->wp_query = $wp_query;
9
+ }
10
+
11
+ public function get_feed($post_id, $args = array()) {
12
+ $default_args = array(
13
+ 'post_type' => Post_Types::FEED_POST_TYPE,
14
+ 'p' => $post_id,
15
+ 'posts_per_page' => 1,
16
+ 'no_found_rows' => true,
17
+ );
18
+
19
+ $args = wp_parse_args($args, $default_args);
20
+ $this->wp_query->query($args);
21
+
22
+ if (!$this->wp_query->have_posts()) {
23
+ return false;
24
+ }
25
+
26
+ return $this->wp_query->posts[0];
27
+ }
28
+
29
+ public function get_feed_count($args = array()) {
30
+ $default_args = array(
31
+ 'post_type' => Post_Types::FEED_POST_TYPE,
32
+ 'posts_per_page' => -1,
33
+ 'no_found_rows' => true,
34
+ );
35
+
36
+ $args = wp_parse_args($args, $default_args);
37
+ $this->wp_query->query($args);
38
+
39
+ if (!$this->wp_query->have_posts()) {
40
+ return 0;
41
+ }
42
+
43
+ return count($this->wp_query->posts);
44
+ }
45
+
46
+ }
includes/class-feed-old.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ class Feed_Old {
6
+
7
+ public static $widget_fields = array(
8
+ 'place_name' => '',
9
+ 'place_id' => '',
10
+ 'place_photo' => '',
11
+ 'text_size' => '120',
12
+ 'dark_theme' => '',
13
+ 'view_mode' => 'list',
14
+ 'pagination' => '5',
15
+ 'max_width' => '',
16
+ 'max_height' => '',
17
+ 'refresh_reviews' => true,
18
+ 'hide_based_on' => false,
19
+ 'hide_reviews' => false,
20
+ 'centered' => false,
21
+ 'reduce_avatars_size' => true,
22
+ 'open_link' => true,
23
+ 'nofollow_link' => true,
24
+ 'lazy_load_img' => true,
25
+ 'def_reviews_link' => false,
26
+ 'reviews_lang' => '',
27
+ );
28
+
29
+ public function __construct() {
30
+ }
31
+
32
+ public function get_feed($id, $params) {
33
+ $feed_content = array();
34
+ $conn = array();
35
+ $opts = array();
36
+
37
+ foreach (self::$widget_fields as $variable => $value) {
38
+ if ($variable == 'place_id' || $variable == 'place_name' || $variable == 'place_photo' || $variable == 'reviews_lang') {
39
+ $key = str_replace('place_', '', $variable);
40
+ $key = str_replace('reviews_', '', $key);
41
+ $conn[$key] = !isset($params[$variable]) ? self::$widget_fields[$variable] : esc_attr($params[$variable]);
42
+ } elseif ($variable == 'refresh_reviews') {
43
+ $conn['refresh'] = isset($params[$variable]) && $params[$variable] == true ? true : false;
44
+ } else {
45
+ $opts[$variable] = !isset($params[$variable]) ? self::$widget_fields[$variable] : esc_attr($params[$variable]);
46
+ }
47
+ }
48
+
49
+ $conn['platform'] = 'google';
50
+ $feed_content['connections'] = array($conn);
51
+ $feed_content['options'] = $opts;
52
+
53
+ return (object) array('ID' => $id, 'post_content' => json_encode($feed_content));
54
+ }
55
+ }
includes/class-feed-page.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ class Feed_Page {
6
+
7
+ public function __construct(Feed_Deserializer $feed_deserializer) {
8
+ $this->feed_deserializer = $feed_deserializer;
9
+ }
10
+
11
+ public function register() {
12
+ add_filter('views_edit-' . Post_Types::FEED_POST_TYPE, array($this, 'render'), 20);
13
+ }
14
+
15
+ public function render() {
16
+ $feed_count = $this->feed_deserializer->get_feed_count();
17
+ ?>
18
+ <div class="grw-admin-feeds">
19
+ <a class="button button-primary" href="<?php echo admin_url('admin.php'); ?>?page=grw-builder">Create Widget</a>
20
+ <?php if ($feed_count < 1) { ?>
21
+ <h3 style="display:inline;vertical-align:middle;"> - First of all, create a widget to connect and show Google reviews through a shortcode or sidebar widget</h3>
22
+ <?php } ?>
23
+ </div>
24
+ <?php
25
+ }
26
+ }
includes/class-feed-serializer.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ class Feed_Serializer {
6
+
7
+ public function __construct() {
8
+ add_action('admin_post_' . Post_Types::FEED_POST_TYPE . '_save', array($this, 'feed_save'), 30);
9
+ }
10
+
11
+ public function feed_save() {
12
+
13
+ $raw_data_array = wp_unslash($_POST[Post_Types::FEED_POST_TYPE]);
14
+
15
+ $post_id = wp_insert_post(array(
16
+ 'ID' => $raw_data_array['post_id'],
17
+ 'post_title' => $raw_data_array['title'],
18
+ 'post_content' => $raw_data_array['content'],
19
+ 'post_type' => Post_Types::FEED_POST_TYPE,
20
+ 'post_status' => 'publish',
21
+ ));
22
+
23
+ // NOT: $referer = empty(wp_get_referer()) ? $raw_data_array['current_url'] : wp_get_referer();
24
+ // COZ: Fatal error: Can't use function return value in write context in .../includes/class-feed-serializer.php on line ...
25
+ $referer = wp_get_referer();
26
+ $referer = empty($referer) ? $raw_data_array['current_url'] : wp_get_referer();
27
+
28
+ wp_safe_redirect(
29
+ add_query_arg(array(
30
+ Post_Types::FEED_POST_TYPE . '_id' => $post_id,
31
+ ), $referer)
32
+ );
33
+ exit;
34
+ }
35
+
36
+ }
includes/class-feed-shortcode.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ use WP_Rplg_Google_Reviews\Includes\Core\Core;
6
+
7
+ class Feed_Shortcode {
8
+
9
+ public function __construct(Feed_Deserializer $feed_deserializer, Assets $assets, Core $core, View $view, Feed_Old $feed_old) {
10
+ $this->feed_deserializer = $feed_deserializer;
11
+ $this->assets = $assets;
12
+ $this->core = $core;
13
+ $this->view = $view;
14
+ $this->feed_old = $feed_old;
15
+ }
16
+
17
+ public function register() {
18
+ add_shortcode('grw', array($this, 'init'));
19
+ }
20
+
21
+ public function init($atts) {
22
+ if (get_option('grw_active') === '0') {
23
+ return '';
24
+ }
25
+
26
+ if (isset($atts['place_id']) && strlen($atts['place_id']) > 0) {
27
+ $feed = $this->feed_old->get_feed($atts['place_id'], $atts);
28
+
29
+ } else {
30
+ $atts = shortcode_atts(array('id' => 0), $atts, 'grw');
31
+ $feed = $this->feed_deserializer->get_feed($atts['id']);
32
+
33
+ if (!$feed) {
34
+ return null;
35
+ }
36
+ }
37
+
38
+ $grw_demand_assets = get_option('grw_demand_assets');
39
+ if ($grw_demand_assets || $grw_demand_assets == 'true') {
40
+ $this->assets->enqueue_public_styles();
41
+ $this->assets->enqueue_public_scripts();
42
+ }
43
+
44
+ $data = $this->core->get_reviews($feed);
45
+ return $this->view->render($feed->ID, $data['businesses'], $data['reviews'], $data['options']);
46
+ }
47
+ }
includes/class-feed-widget.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ use WP_Rplg_Google_Reviews\Includes\Core\Core;
6
+
7
+ class Feed_Widget extends \WP_Widget {
8
+
9
+ public static $static_core;
10
+
11
+ public static $static_view;
12
+
13
+ public static $static_assets;
14
+
15
+ public static $static_feed_deserializer;
16
+
17
+ public static $static_feed_old;
18
+
19
+ public function __construct() {
20
+ parent::__construct(
21
+ 'grw_widget',
22
+ __('Google Reviews Widget', 'grw'),
23
+ array(
24
+ 'classname' => 'google-reviews-widget',
25
+ 'description' => __('Display Google Places Reviews on your website.', 'grw'),
26
+ )
27
+ );
28
+
29
+ $this->core = self::$static_core;
30
+ $this->view = self::$static_view;
31
+ $this->assets = self::$static_assets;
32
+ $this->feed_deserializer = self::$static_feed_deserializer;
33
+ $this->feed_old = self::$static_feed_old;
34
+ }
35
+
36
+ public function widget($args, $instance) {
37
+ if (get_option('grw_active') === '0') {
38
+ return;
39
+ }
40
+
41
+ if (isset($instance['place_id']) && strlen($instance['place_id']) > 0) {
42
+ $feed = $this->feed_old->get_feed($this->id, $instance);
43
+
44
+ } else {
45
+ if (!isset($instance['feed_id']) || strlen($instance['feed_id']) < 1) {
46
+ return null;
47
+ }
48
+
49
+ $feed = $this->feed_deserializer->get_feed($instance['feed_id']);
50
+
51
+ if (!$feed) {
52
+ return null;
53
+ }
54
+ }
55
+
56
+ $grw_demand_assets = get_option('grw_demand_assets');
57
+ if ($grw_demand_assets || $grw_demand_assets == 'true') {
58
+ $this->assets->enqueue_public_styles();
59
+ $this->assets->enqueue_public_scripts();
60
+ }
61
+
62
+ $data = $this->core->get_reviews($feed);
63
+
64
+ echo $args['before_widget'];
65
+
66
+ if (!empty($instance['title'])) {
67
+ echo $args['before_title'] . esc_html($instance['title']) . $args['after_title'];
68
+ }
69
+
70
+ $businesses = $data['businesses'];
71
+ $reviews = $data['reviews'];
72
+ $options = $data['options'];
73
+ if (count($businesses) > 0 || count($reviews) > 0) {
74
+ echo $this->view->render($feed->ID, $businesses, $reviews, $options);
75
+ }
76
+
77
+ echo $args['after_widget'];
78
+ }
79
+
80
+ public function form($instance) {
81
+ $wp_query = new \WP_Query();
82
+ $wp_query->query(array(
83
+ 'post_type' => Post_Types::FEED_POST_TYPE,
84
+ 'posts_per_page' => 100,
85
+ 'no_found_rows' => true,
86
+ ));
87
+ $feeds = $wp_query->posts;
88
+
89
+ ?>
90
+ <p>
91
+ <label for="<?php echo esc_attr($this->get_field_id('title')); ?>">
92
+ <?php esc_html_e('Title:', 'grw'); ?>
93
+ </label>
94
+ <input
95
+ type="text"
96
+ id="<?php echo esc_attr($this->get_field_id('title')); ?>"
97
+ class="widefat"
98
+ name="<?php echo esc_attr($this->get_field_name('title')); ?>"
99
+ value="<?php if (isset($instance['title'])) { echo esc_attr($instance['title']); } ?>"
100
+ >
101
+ </p>
102
+ <p>
103
+ <label for="<?php echo esc_attr($this->get_field_id('feed_id')); ?>">
104
+ <?php esc_html_e('Feed:', 'grw'); ?>
105
+ </label>
106
+
107
+ <select
108
+ id="<?php echo esc_attr($this->get_field_id('feed_id')); ?>"
109
+ name="<?php echo esc_attr($this->get_field_name('feed_id')); ?>"
110
+ style="display:block;width:100%"
111
+ >
112
+ <option value="">Select Feed</option>
113
+ <?php foreach ($feeds as $feed) : ?>
114
+ <option
115
+ value="<?php echo esc_attr($feed->ID); ?>"
116
+ <?php if (isset($instance['feed_id'])) { selected($feed->ID, $instance['feed_id']); } ?>
117
+ >
118
+ <?php echo esc_html('ID ' . $feed->ID . ': ' . $feed->post_title); ?>
119
+ </option>
120
+ <?php endforeach; ?>
121
+
122
+ </select>
123
+ </p>
124
+ <?php
125
+ }
126
+
127
+ public function update($new_instance, $old_instance) {
128
+ $instance = $old_instance;
129
+ $instance['title'] = sanitize_text_field($new_instance['title']);
130
+ $instance['feed_id'] = sanitize_text_field($new_instance['feed_id']);
131
+ return $instance;
132
+ }
133
+ }
includes/class-plugin-settings.php ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ class Plugin_Settings {
6
+
7
+ public function __construct(Debug_Info $debug_info) {
8
+ $this->debug_info = $debug_info;
9
+ }
10
+
11
+ public function register() {
12
+ add_action('grw_admin_page_grw-settings', array($this, 'init'));
13
+ add_action('grw_admin_page_grw-settings', array($this, 'render'));
14
+ }
15
+
16
+ public function init() {
17
+
18
+ }
19
+
20
+ public function render() {
21
+
22
+ $tab = isset($_GET['grw_tab']) && strlen($_GET['grw_tab']) > 0 ? sanitize_text_field(wp_unslash($_GET['grw_tab'])) : 'active';
23
+
24
+ $grw_enabled = get_option('grw_active') == '1';
25
+ $grw_demand_assets = get_option('grw_demand_assets');
26
+ $grw_minified_assets = get_option('grw_minified_assets');
27
+
28
+ $grw_google_api_key = get_option('grw_google_api_key');
29
+
30
+ $grw_latest_version = get_option('grw_latest_version');
31
+
32
+ $milliseconds = round(microtime(true) * 1000);
33
+ ?>
34
+
35
+ <div class="grw-page-title">
36
+ Settings
37
+ </div>
38
+
39
+ <?php do_action('grw_admin_notices'); ?>
40
+
41
+ <div class="grw-settings-workspace">
42
+
43
+ <div data-nav-tabs="">
44
+
45
+ <div class="nav-tab-wrapper">
46
+ <a href="#grw-general" class="nav-tab<?php if ($tab == 'active') { ?> nav-tab-active<?php } ?>">General</a>
47
+ <a href="#grw-google" class="nav-tab<?php if ($tab == 'google') { ?> nav-tab-active<?php } ?>">Google</a>
48
+ <a href="#grw-advance" class="nav-tab<?php if ($tab == 'advance') { ?> nav-tab-active<?php } ?>">Advance</a>
49
+ </div>
50
+
51
+ <div id="grw-general" class="tab-content" style="display:<?php echo $tab == 'active' ? 'block' : 'none'?>;">
52
+ <h3>General Settings</h3>
53
+ <form method="post" action="<?php echo esc_url(admin_url('admin-post.php?action=grw_settings_save&grw_tab=active&active=' . (string)((int)($grw_enabled != true)))); ?>">
54
+ <div class="grw-field">
55
+ <div class="grw-field-label">
56
+ <label>Google Reviews plugin is currently <b><?php echo $grw_enabled ? 'enabled' : 'disabled' ?></b></label>
57
+ </div>
58
+ <div class="wp-review-field-option">
59
+ <?php wp_nonce_field('grw-wpnonce_active', 'grw-form_nonce_active'); ?>
60
+ <input type="submit" name="active" class="button" value="<?php echo $grw_enabled ? 'Disable' : 'Enable'; ?>" />
61
+ </div>
62
+ </div>
63
+ <div class="grw-field">
64
+ <div class="grw-field-label">
65
+ <label>Load assets on demand</label>
66
+ </div>
67
+ <div class="wp-review-field-option">
68
+ <label>
69
+ <input type="hidden" name="grw_demand_assets" value="false">
70
+ <input type="checkbox" id="grw_demand_assets" name="grw_demand_assets" value="true" <?php checked('true', $grw_demand_assets); ?>>
71
+ Load static assets (JavaScripts/CSS) only on pages where reviews are showing
72
+ </label>
73
+ </div>
74
+ </div>
75
+ <div class="grw-field">
76
+ <div class="grw-field-label">
77
+ <label>Minify and assemble assets</label>
78
+ </div>
79
+ <div class="wp-review-field-option">
80
+ <label>
81
+ <input type="hidden" name="grw_minified_assets" value="false">
82
+ <input type="checkbox" id="grw_minified_assets" name="grw_minified_assets" value="true" <?php checked('true', $grw_minified_assets); ?>>
83
+ Minify and assemble static assets (JavaScripts/CSS) to single style and script files
84
+ </label>
85
+ <div style="padding-top:15px">
86
+ <input type="submit" value="Save" name="save" class="button" />
87
+ </div>
88
+ </div>
89
+ </div>
90
+ </form>
91
+ </div>
92
+
93
+ <div id="grw-google" class="tab-content" style="display:<?php echo $tab == 'google' ? 'block' : 'none'?>;">
94
+ <h3>Google</h3>
95
+ <form method="post" action="<?php echo esc_url(admin_url('admin-post.php?action=grw_settings_save&grw_tab=google')); ?>">
96
+ <?php wp_nonce_field('grw-wpnonce_save', 'grw-form_nonce_save'); ?>
97
+ <div class="grw-field">
98
+ <div class="grw-field-label">
99
+ <label>Google Places API key</label>
100
+ </div>
101
+ <div class="wp-review-field-option">
102
+ <input type="text" id="grw_google_api_key" name="grw_google_api_key" class="regular-text" value="<?php echo esc_attr($grw_google_api_key); ?>">
103
+ <p>If you do not know how to create Google API key, please read: <a href="<?php echo admin_url('admin.php?page=grw-support&grw_tab=fig'); ?>">Full Installation Guide</a></p>
104
+ <div style="padding-top:15px">
105
+ <input type="submit" value="Save" name="save" class="button" />
106
+ </div>
107
+ </div>
108
+ </div>
109
+ </form>
110
+ </div>
111
+
112
+ <div id="grw-advance" class="tab-content" style="display:<?php echo $tab == 'advance' ? 'block' : 'none'?>;">
113
+ <h3>Advance</h3>
114
+ <form method="post" action="<?php echo esc_url(admin_url('admin-post.php?action=grw_settings_save&grw_tab=advance')); ?>">
115
+ <div class="grw-field">
116
+ <div class="grw-field-label">
117
+ <label>Re-create the database tables of the plugin (service option)</label>
118
+ </div>
119
+ <div class="wp-review-field-option">
120
+ <?php wp_nonce_field('grw-wpnonce_create_db', 'grw-form_nonce_create_db'); ?>
121
+ <input type="submit" value="Re-create Database" name="create_db" onclick="return confirm('Are you sure you want to re-create database tables?')" class="button" />
122
+ </div>
123
+ </div>
124
+ <div class="grw-field">
125
+ <div class="grw-field-label">
126
+ <label><b>Please be careful</b>: this removes all settings, reviews, feeds and install the plugin from scratch</label>
127
+ </div>
128
+ <div class="wp-review-field-option">
129
+ <?php wp_nonce_field('grw-wpnonce_create_db', 'grw-form_nonce_create_db'); ?>
130
+ <input type="submit" value="Install from scratch" name="install" onclick="return confirm('It will delete all current feeds, are you sure you want to install from scratch the plugin?')" class="button" />
131
+ <p><label><input type="checkbox" id="install_multisite" name="install_multisite"> For all sites (WP Multisite)</label></p>
132
+ </div>
133
+ </div>
134
+ <div class="grw-field">
135
+ <div class="grw-field-label">
136
+ <label><b>Please be careful</b>: this removes all plugin-specific settings, reviews and feeds</label>
137
+ </div>
138
+ <div class="wp-review-field-option">
139
+ <?php wp_nonce_field('grw-wpnonce_reset_all', 'grw-form_nonce_reset_all'); ?>
140
+ <input type="submit" value="Delete All Data" name="reset_all" onclick="return confirm('Are you sure you want to reset all plugin data including feeds?')" class="button" />
141
+ <p><label><input type="checkbox" id="reset_all_multisite" name="reset_all_multisite"> For all sites (WP Multisite)</label></p>
142
+ </div>
143
+ </div>
144
+ <div id="debug_info" class="grw-field">
145
+ <div class="grw-field-label">
146
+ <label>Debug information</label>
147
+ </div>
148
+ <div class="wp-review-field-option">
149
+ <input type="button" value="Copy Debug Information" name="reset_all" onclick="window.grw_debug_info.select();document.execCommand('copy');window.grw_debug_msg.innerHTML='Debug Information copied, please paste it to your email to support';" class="button" />
150
+ <textarea id="grw_debug_info" style="display:block;width:30em;height:250px;margin-top:10px" onclick="window.grw_debug_info.select();document.execCommand('copy');window.grw_debug_msg.innerHTML='Debug Information copied, please paste it to your email to support';" readonly><?php $this->debug_info->render(); ?></textarea>
151
+ <p id="grw_debug_msg"></p>
152
+ </div>
153
+ </div>
154
+ </form>
155
+ </div>
156
+
157
+ </div>
158
+
159
+ </div>
160
+ <?php
161
+ }
162
+
163
+ }
includes/class-plugin-support.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ class Plugin_Support {
6
+
7
+ public function __construct() {
8
+ }
9
+
10
+ public function register() {
11
+ add_action('grw_admin_page_grw-support', array($this, 'init'));
12
+ add_action('grw_admin_page_grw-support', array($this, 'render'));
13
+ }
14
+
15
+ public function init() {
16
+
17
+ }
18
+
19
+ public function render() {
20
+
21
+ $tab = isset($_GET['grw_tab']) && strlen($_GET['grw_tab']) > 0 ? sanitize_text_field(wp_unslash($_GET['grw_tab'])) : 'welcome';
22
+
23
+ ?>
24
+ <div class="grw-page-title">
25
+ Support and Troubleshooting
26
+ </div>
27
+
28
+ <div class="grw-support-workspace">
29
+
30
+ <div data-nav-tabs="">
31
+
32
+ <div class="nav-tab-wrapper">
33
+ <a href="#welcome" class="nav-tab<?php if ($tab == 'welcome') { ?> nav-tab-active<?php } ?>">
34
+ <?php echo __('Welcome', 'grw'); ?>
35
+ </a>
36
+ <a href="#fig" class="nav-tab<?php if ($tab == 'fig') { ?> nav-tab-active<?php } ?>">
37
+ <?php echo __('Full Installation Guide', 'grw'); ?>
38
+ </a>
39
+ <a href="#support" class="nav-tab<?php if ($tab == 'support') { ?> nav-tab-active<?php } ?>">
40
+ <?php echo __('Support', 'grw'); ?>
41
+ </a>
42
+ </div>
43
+
44
+ <div id="welcome" class="tab-content" style="display:<?php echo $tab == 'welcome' ? 'block' : 'none'?>;">
45
+ <h3>Google Reviews Widget for WordPress</h3>
46
+ <div class="rplg-flex-row">
47
+ <div class="rplg-flex-col">
48
+ <span>Google Reviews plugin is an easy and fast way to integrate Google business reviews right into your WordPress website. This plugin works instantly and keep all Google places and reviews in WordPress database thus it has no depend on external services.</span>
49
+ <p style="font-size:20px;text-align:center"><b><u>Please read '<a href="<?php echo admin_url('admin.php?page=grw-support&grw_tab=fig'); ?>">Full Installation Guide</a>' to completely understand how it works and set up the plugin</u></b>.</p>
50
+ <p>Also you can find most common answers and solutions for most common questions and issues in next tabs.</p>
51
+ <div class="rplg-alert rplg-alert-success">
52
+ <strong>Try more features in the Business version</strong>: Merge Google, Facebook and Yelp reviews, Beautiful themes (Slider, Grid, Trust Badges), Shortcode support, Rich Snippets, Rating filter, Any sorting, Include/Exclude words filter, Hide/Show any elements, Priority support and many others.
53
+ <a class="button-primary button" href="https://richplugins.com/business-reviews-bundle-wordpress-plugin" target="_blank" style="margin-left:10px">Upgrade to Business</a>
54
+ </div>
55
+ <br>
56
+ <div class="rplg-socials">
57
+ <div id="fb-root"></div>
58
+ <script>(function(d, s, id) {
59
+ var js, fjs = d.getElementsByTagName(s)[0];
60
+ if (d.getElementById(id)) return;
61
+ js = d.createElement(s); js.id = id;
62
+ js.src = "//connect.facebook.net/en_EN/sdk.js#xfbml=1&version=v2.6&appId=1501100486852897";
63
+ fjs.parentNode.insertBefore(js, fjs);
64
+ }(document, 'script', 'facebook-jssdk'));</script>
65
+ <div class="fb-like" data-href="https://richplugins.com/" data-layout="button_count" data-action="like" data-show-faces="true" data-share="false"></div>
66
+ <a href="https://twitter.com/richplugins?ref_src=twsrc%5Etfw" class="twitter-follow-button" data-show-count="false">Follow @richplugins</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
67
+ <div class="g-plusone" data-size="medium" data-annotation="inline" data-width="200" data-href="https://plus.google.com/101080686931597182099"></div>
68
+ <script type="text/javascript">
69
+ window.___gcfg = { lang: 'en-US' };
70
+ (function () {
71
+ var po = document.createElement('script');
72
+ po.type = 'text/javascript';
73
+ po.async = true;
74
+ po.src = 'https://apis.google.com/js/plusone.js';
75
+ var s = document.getElementsByTagName('script')[0];
76
+ s.parentNode.insertBefore(po, s);
77
+ })();
78
+ </script>
79
+ </div>
80
+ </div>
81
+ <div class="rplg-flex-col">
82
+ <iframe width="100%" height="315" src="https://www.youtube.com/embed/Wbst-UBgXXk" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
83
+ </div>
84
+ </div>
85
+ </div>
86
+
87
+ <div id="fig" class="tab-content" style="display:<?php echo $tab == 'fig' ? 'block' : 'none'?>;">
88
+ <h3>How to connect Google reviews</h3>
89
+ <?php include_once(dirname(GRW_PLUGIN_FILE) . '/includes/page-setting-fig.php'); ?>
90
+ </div>
91
+
92
+ <div id="support" class="tab-content" style="display:<?php echo $tab == 'support' ? 'block' : 'none'?>;">
93
+ <h3>Most Common Questions</h3>
94
+ <?php include_once(dirname(GRW_PLUGIN_FILE) . '/includes/page-setting-support.php'); ?>
95
+ </div>
96
+
97
+ </div>
98
+ </div>
99
+ <?php
100
+ }
101
+ }
includes/class-plugin.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ use WP_Rplg_Google_Reviews\Includes\Admin\Admin_Menu;
6
+ use WP_Rplg_Google_Reviews\Includes\Admin\Admin_Tophead;
7
+ use WP_Rplg_Google_Reviews\Includes\Admin\Admin_Notice;
8
+ use WP_Rplg_Google_Reviews\Includes\Admin\Admin_Feed_Columns;
9
+ use WP_Rplg_Google_Reviews\Includes\Admin\Admin_Rev;
10
+
11
+ use WP_Rplg_Google_Reviews\Includes\Core\Core;
12
+ use WP_Rplg_Google_Reviews\Includes\Core\Connect_Google;
13
+ use WP_Rplg_Google_Reviews\Includes\Core\Database;
14
+
15
+ final class Plugin {
16
+
17
+ protected $name;
18
+ protected $version;
19
+ protected $activator;
20
+
21
+ public function __construct() {
22
+ $this->name = 'widget-google-reviews';
23
+ $this->version = GRW_VERSION;
24
+ }
25
+
26
+ public function register() {
27
+ register_activation_hook(GRW_PLUGIN_FILE, array($this, 'activate'));
28
+ register_deactivation_hook(GRW_PLUGIN_FILE, array($this, 'deactivate'));
29
+
30
+ add_action('plugins_loaded', array($this, 'register_services'));
31
+ }
32
+
33
+ public function register_services() {
34
+ $this->init_language();
35
+
36
+ $database = new Database();
37
+
38
+ $activator = new Activator($database);
39
+ $activator->register();
40
+
41
+ $debug_info = new Debug_Info($activator);
42
+
43
+ $assets = new Assets(GRW_ASSETS_URL, $this->version);
44
+ $assets->register();
45
+
46
+ $post_types = new Post_Types();
47
+ $post_types->register();
48
+
49
+ $feed_deserializer = new Feed_Deserializer(new \WP_Query());
50
+
51
+ $feed_page = new Feed_Page($feed_deserializer);
52
+ $feed_page->register();
53
+
54
+ $core = new Core();
55
+
56
+ $view = new View();
57
+
58
+ $builder_page = new Builder_Page($feed_deserializer, $core, $view);
59
+ $builder_page->register();
60
+
61
+ $feed_old = new Feed_Old();
62
+
63
+ $feed_shortcode = new Feed_Shortcode($feed_deserializer, $assets, $core, $view, $feed_old);
64
+ $feed_shortcode->register();
65
+
66
+ Feed_Widget::$static_feed_deserializer = $feed_deserializer;
67
+ Feed_Widget::$static_core = $core;
68
+ Feed_Widget::$static_view = $view;
69
+ Feed_Widget::$static_assets = $assets;
70
+ Feed_Widget::$static_feed_old = $feed_old;
71
+ add_action('widgets_init', function() {
72
+ register_widget('WP_Rplg_Google_Reviews\Includes\Feed_Widget');
73
+ });
74
+
75
+ $connect_google = new Connect_Google();
76
+
77
+ if (is_admin()) {
78
+ $feed_serializer = new Feed_Serializer();
79
+
80
+ $admin_notice = new Admin_Notice();
81
+ $admin_notice->register();
82
+
83
+ $admin_menu = new Admin_Menu();
84
+ $admin_menu->register();
85
+
86
+ $admin_tophead = new Admin_Tophead();
87
+ $admin_tophead->register();
88
+
89
+ $admin_feed_columns = new Admin_Feed_Columns($feed_deserializer);
90
+ $admin_feed_columns->register();
91
+
92
+ $settings_save = new Settings_Save($activator);
93
+ $settings_save->register();
94
+
95
+ $plugin_settings = new Plugin_Settings($debug_info);
96
+ $plugin_settings->register();
97
+
98
+ $plugin_support = new Plugin_Support();
99
+ $plugin_support->register();
100
+
101
+ $admin_rev = new Admin_Rev();
102
+ $admin_rev->register();
103
+ }
104
+ }
105
+
106
+ public function init_language() {
107
+ load_plugin_textdomain('grw', false, basename(dirname(GRW_PLUGIN_FILE)) . '/languages');
108
+ }
109
+
110
+ public function activate($network_wide = false) {
111
+ $now = time();
112
+ update_option('grw_activation_time', $now);
113
+
114
+ add_option('grw_is_multisite', $network_wide);
115
+
116
+ $activator = new Activator(new Database());
117
+ $activator->activate();
118
+ }
119
+
120
+ public function deactivate() {
121
+ $deactivator = new Deactivator();
122
+ $deactivator->deactivate();
123
+ }
124
+ }
includes/class-post-types.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ class Post_Types {
6
+
7
+ const FEED_POST_TYPE = 'grw_feed';
8
+
9
+ public function register() {
10
+ add_action('init', array($this, 'register_post_types'));
11
+ }
12
+
13
+ public function register_post_types() {
14
+ $this->register_feed_post_type();
15
+ }
16
+
17
+ public function register_feed_post_type() {
18
+ $labels = array(
19
+ 'name' => _x('Reviews widgets', 'Post Type General Name', 'grw'),
20
+ 'singular_name' => _x('Reviews widget', 'Post Type Singular Name', 'grw'),
21
+ 'menu_name' => __('Reviews widgets', 'grw'),
22
+ 'name_admin_bar' => __('Reviews widget', 'grw'),
23
+ 'archives' => __('Reviews Feed Archives', 'grw'),
24
+ 'attributes' => __('Reviews Feed Attributes', 'grw'),
25
+ 'parent_item_colon' => __('Parent Reviews Feed:', 'grw'),
26
+ 'all_items' => __('Widgets', 'grw'),
27
+ 'add_new_item' => __('Add New Reviews Feed', 'grw'),
28
+ 'add_new' => __('Add Reviews Feed', 'grw'),
29
+ 'new_item' => __('New Reviews Feed', 'grw'),
30
+ 'edit_item' => __('Edit Reviews Feed', 'grw'),
31
+ 'update_item' => __('Update Reviews Feed', 'grw'),
32
+ 'view_item' => __('View Reviews Feed', 'grw'),
33
+ 'view_items' => __('View Reviews Feeds', 'grw'),
34
+ 'search_items' => __('Search Reviews Widgets', 'grw'),
35
+ 'not_found' => __('Not found', 'grw'),
36
+ 'not_found_in_trash' => __('Not found in Trash', 'grw'),
37
+ 'featured_image' => __('Featured Image', 'grw'),
38
+ 'set_featured_image' => __('Set featured image', 'grw'),
39
+ 'remove_featured_image' => __('Remove featured image', 'grw'),
40
+ 'use_featured_image' => __('Use as featured image', 'grw'),
41
+ 'insert_into_item' => __('Insert into item', 'grw'),
42
+ 'uploaded_to_this_item' => __('Uploaded to this item', 'grw'),
43
+ 'items_list' => __('Reviews Feeds list', 'grw'),
44
+ 'items_list_navigation' => __('Reviews Feeds list navigation', 'grw'),
45
+ 'filter_items_list' => __('Filter items list', 'grw'),
46
+ );
47
+
48
+ $args = array(
49
+ 'label' => __('Reviews Feed', 'grw'),
50
+ 'labels' => $labels,
51
+ 'supports' => array('title'),
52
+ 'taxonomies' => array(),
53
+ 'hierarchical' => false,
54
+ 'public' => false,
55
+ 'show_in_rest' => false,
56
+ 'show_ui' => true,
57
+ 'show_in_menu' => 'grw',
58
+ 'show_in_admin_bar' => false,
59
+ 'show_in_nav_menus' => false,
60
+ 'can_export' => true,
61
+ 'has_archive' => false,
62
+ 'exclude_from_search' => true,
63
+ 'publicly_queryable' => false,
64
+ 'capabilities' => array('create_posts' => 'do_not_allow'),
65
+ 'map_meta_cap' => true,
66
+ );
67
+
68
+ register_post_type(self::FEED_POST_TYPE, $args);
69
+ }
70
+ }
includes/class-settings-save.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ use WP_Rplg_Google_Reviews\Includes\Core\Database;
6
+
7
+ class Settings_Save {
8
+
9
+ public function __construct(Activator $activator) {
10
+ $this->activator = $activator;
11
+ }
12
+
13
+ public function register() {
14
+ add_action('admin_post_grw_settings_save', array($this, 'save_from_post_array'));
15
+ }
16
+
17
+ public function save_from_post_array() {
18
+ global $wpdb;
19
+
20
+ if (!function_exists('wp_nonce_field')) {
21
+ function wp_nonce_field() {}
22
+ }
23
+
24
+ if (!current_user_can('manage_options')) {
25
+ die('The account you\'re logged in to doesn\'t have permission to access this page.');
26
+ }
27
+
28
+ if (!empty($_POST)) {
29
+ $nonce_result_check = $this->check_nonce();
30
+ if ($nonce_result_check === false) {
31
+ die('Unable to save changes. Make sure you are accessing this page from the Wordpress dashboard.');
32
+ }
33
+ }
34
+
35
+ $notice_code = null;
36
+
37
+ if (isset($_POST['active']) && isset($_GET['active'])) {
38
+ $active = $_GET['active'] == '1' ? '1' : '0';
39
+ update_option('grw_active', $active);
40
+ $notice_code = 'settings_active_' . $active;
41
+ }
42
+
43
+ if (isset($_POST['save'])) {
44
+ $fields = array('grw_demand_assets', 'grw_minified_assets', 'grw_google_api_key');
45
+ foreach ($fields as $key => $value) {
46
+ if (isset($_POST[$value])) {
47
+ update_option($value, trim(sanitize_text_field(wp_unslash($_POST[$value]))));
48
+ }
49
+ }
50
+ $notice_code = 'settings_save';
51
+ }
52
+
53
+ if (isset($_POST['create_db'])) {
54
+ $this->activator->create_db();
55
+ $notice_code = 'settings_create_db';
56
+ }
57
+
58
+ if (isset($_POST['install'])) {
59
+ $install_multisite = sanitize_text_field(wp_unslash($_POST['install_multisite']));
60
+ $this->activator->drop_db($install_multisite);
61
+ $this->activator->delete_all_options($install_multisite);
62
+ $this->activator->delete_all_feeds($install_multisite);
63
+ $this->activator->activate();
64
+ $notice_code = 'settings_install';
65
+ }
66
+
67
+ if (isset($_POST['reset_all'])) {
68
+ $reset_all_multisite = sanitize_text_field(wp_unslash($_POST['reset_all_multisite']));
69
+ $this->activator->drop_db($reset_all_multisite);
70
+ $this->activator->delete_all_options($reset_all_multisite);
71
+ $this->activator->delete_all_feeds($reset_all_multisite);
72
+ $notice_code = 'settings_reset_all';
73
+ }
74
+
75
+ $this->redirect_to_tab($notice_code);
76
+ }
77
+
78
+ public function redirect_to_tab($notice_code = '') {
79
+ if (empty($_GET['grw_tab'])) {
80
+ wp_safe_redirect(wp_get_referer());
81
+ exit;
82
+ }
83
+
84
+ $tab = sanitize_text_field(wp_unslash($_GET['grw_tab']));
85
+
86
+ $query_args = array(
87
+ 'grw_tab' => $tab,
88
+ );
89
+
90
+ if (!empty($notice_code)) {
91
+ $query_args['grw_notice'] = $notice_code;
92
+ }
93
+
94
+ wp_safe_redirect(add_query_arg($query_args, wp_get_referer()));
95
+ exit;
96
+ }
97
+
98
+ private function check_nonce() {
99
+ $nonce_actions = array('active', 'save', 'create_db', 'reset', 'reset_all');
100
+ $nonce_form_prefix = 'grw-form_nonce_';
101
+ $nonce_action_prefix = 'grw-wpnonce_';
102
+ foreach ($nonce_actions as $key => $value) {
103
+ if (isset($_POST[$nonce_form_prefix.$value])) {
104
+ check_admin_referer($nonce_action_prefix.$value, $nonce_form_prefix.$value);
105
+ return true;
106
+ }
107
+ }
108
+ return false;
109
+ }
110
+
111
+ }
includes/class-view.php ADDED
@@ -0,0 +1,321 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes;
4
+
5
+ class View {
6
+
7
+ public function render($feed_id, $businesses, $reviews, $options, $is_admin = false) {
8
+ ob_start();
9
+
10
+ if ($options->lazy_load_img) {
11
+ wp_enqueue_script('blazy-js');
12
+ }
13
+
14
+ $max_width = $options->max_width;
15
+ if (is_numeric($max_width)) {
16
+ $max_width = $max_width . 'px';
17
+ }
18
+ $max_height = $options->max_height;
19
+ if (is_numeric($max_height)) {
20
+ $max_height = $max_height . 'px';
21
+ }
22
+
23
+ $style = '';
24
+ if (isset($max_width) && strlen($max_width) > 0) {
25
+ $style .= 'width:' . $max_width . '!important;';
26
+ }
27
+ if (isset($max_height) && strlen($max_height) > 0) {
28
+ $style .= 'height:' . $max_height . '!important;overflow-y:auto!important;';
29
+ }
30
+ if ($options->centered) {
31
+ $style .= 'margin:0 auto!important;';
32
+ }
33
+
34
+ ?>
35
+ <div class="wp-gr wpac"<?php if ($style) { ?> style="<?php echo $style;?>"<?php } ?>>
36
+ <?php
37
+ switch ($options->view_mode) {
38
+ case 'badge':
39
+ $this->render_badge($businesses, $reviews, $options);
40
+ break;
41
+ case 'list':
42
+ $this->render_list($businesses, $reviews, $options, $is_admin);
43
+ break;
44
+ default:
45
+ $this->render_list($businesses, $reviews, $options, $is_admin);
46
+ }
47
+ ?>
48
+ </div>
49
+ <?php
50
+ return preg_replace('/[\n\r]|(>)\s+(<)/', '$1$2', ob_get_clean());
51
+ }
52
+
53
+ private function render_list($businesses, $reviews, $options, $is_admin = false) {
54
+ ?>
55
+ <div class="wp-google-list<?php if ($options->dark_theme) { ?> wp-dark<?php } ?>">
56
+ <?php foreach ($businesses as $business) { ?>
57
+ <div class="wp-google-place">
58
+ <?php $this->grw_place(
59
+ $business->rating,
60
+ $business,
61
+ $business->photo,
62
+ $reviews,
63
+ $options->dark_theme,
64
+ $options->hide_based_on
65
+ ); ?>
66
+ </div>
67
+ <?php }
68
+ if (!$options->hide_reviews) { ?>
69
+ <div class="wp-google-content-inner">
70
+ <?php
71
+ $this->grw_place_reviews(
72
+ $business,
73
+ $reviews,
74
+ $business->id,
75
+ $options->text_size,
76
+ $options->pagination,
77
+ $options->reviewer_avatar_size,
78
+ $options->open_link,
79
+ $options->nofollow_link,
80
+ $options->lazy_load_img,
81
+ $options->google_def_rev_link,
82
+ $is_admin
83
+ );
84
+ ?>
85
+ </div>
86
+ <?php } ?>
87
+ </div>
88
+ <?php
89
+ }
90
+
91
+ private function render_badge($businesses, $reviews, $options) {
92
+ ?>
93
+ <script type="text/javascript">
94
+ function grw_badge_init(el) {
95
+ var btn = el.querySelector('.wp-google-badge'),
96
+ form = el.querySelector('.wp-google-form');
97
+
98
+ var wpac = document.createElement('div');
99
+ wpac.className = 'wp-gr wpac';
100
+ wpac.appendChild(form);
101
+ document.body.appendChild(wpac);
102
+
103
+ btn.onclick = function() {
104
+ form.style.display='block';
105
+ };
106
+ }
107
+ </script>
108
+ <?php foreach ($businesses as $business) { ?>
109
+ <div class="wp-google-badge<?php if ($options->view_mode == 'badge') { ?> wp-google-badge-fixed<?php } ?>">
110
+ <div class="wp-google-border"></div>
111
+ <div class="wp-google-badge-btn">
112
+ <svg viewBox="0 0 512 512" height="44" width="44"><g fill="none" fill-rule="evenodd"><path d="M482.56 261.36c0-16.73-1.5-32.83-4.29-48.27H256v91.29h127.01c-5.47 29.5-22.1 54.49-47.09 71.23v59.21h76.27c44.63-41.09 70.37-101.59 70.37-173.46z" fill="#4285f4"/><path d="M256 492c63.72 0 117.14-21.13 156.19-57.18l-76.27-59.21c-21.13 14.16-48.17 22.53-79.92 22.53-61.47 0-113.49-41.51-132.05-97.3H45.1v61.15c38.83 77.13 118.64 130.01 210.9 130.01z" fill="#34a853"/><path d="M123.95 300.84c-4.72-14.16-7.4-29.29-7.4-44.84s2.68-30.68 7.4-44.84V150.01H45.1C29.12 181.87 20 217.92 20 256c0 38.08 9.12 74.13 25.1 105.99l78.85-61.15z" fill="#fbbc05"/><path d="M256 113.86c34.65 0 65.76 11.91 90.22 35.29l67.69-67.69C373.03 43.39 319.61 20 256 20c-92.25 0-172.07 52.89-210.9 130.01l78.85 61.15c18.56-55.78 70.59-97.3 132.05-97.3z" fill="#ea4335"/><path d="M20 20h472v472H20V20z"/></g></svg>
113
+ <div class="wp-google-badge-score">
114
+ <div><?php echo __('Google Rating', 'grw'); ?></div>
115
+ <span class="wp-google-rating"><?php echo $business->rating; ?></span>
116
+ <span class="wp-google-stars"><?php $this->grw_stars($business->rating); ?></span>
117
+ </div>
118
+ </div>
119
+ </div>
120
+ <?php } ?>
121
+ <div class="wp-google-form" style="display:none">
122
+ <?php foreach ($businesses as $business) { ?>
123
+ <div class="wp-google-head">
124
+ <div class="wp-google-head-inner">
125
+ <?php
126
+ $this->grw_place(
127
+ $business->rating,
128
+ $business,
129
+ $business->photo,
130
+ $reviews,
131
+ $options->dark_theme,
132
+ $options->hide_based_on,
133
+ false
134
+ ); ?>
135
+ </div>
136
+ <button class="wp-google-close" type="button" onclick="this.parentNode.parentNode.style.display='none'">×</button>
137
+ </div>
138
+ <?php } ?>
139
+ <div class="wp-google-body"></div>
140
+ <div class="wp-google-content">
141
+ <div class="wp-google-content-inner">
142
+ <?php
143
+ $this->grw_place_reviews(
144
+ $businesses[0],
145
+ $reviews,
146
+ $businesses[0]->id,
147
+ $options->text_size,
148
+ $options->pagination,
149
+ $options->reviewer_avatar_size,
150
+ $options->open_link,
151
+ $options->nofollow_link,
152
+ $options->lazy_load_img,
153
+ $options->google_def_rev_link
154
+ ); ?>
155
+ </div>
156
+ </div>
157
+ <div class="wp-google-footer">
158
+ <img src="<?php echo GRW_ASSETS_URL; ?>/img/powered_by_google_on_<?php if ($options->dark_theme) { ?>non_<?php } ?>white.png" alt="powered by Google" width="144" height="18" title="powered by Google">
159
+ </div>
160
+ </div>
161
+ <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="" onload="(function(el) { document.addEventListener('DOMContentLoaded', function() { grw_badge_init(el); }); })(this.parentNode);" style="display:none">
162
+ <?php
163
+ }
164
+
165
+ function grw_place($rating, $place, $place_img, $reviews, $dark_theme, $hide_based_on, $show_powered = true) {
166
+ ?>
167
+ <div class="wp-google-left">
168
+ <img src="<?php echo $place_img; ?>" alt="<?php echo $place->name; ?>" width="50" height="50" title="<?php echo $place->name; ?>">
169
+ </div>
170
+ <div class="wp-google-right">
171
+ <div class="wp-google-name">
172
+ <?php $place_name_content = '<span>' . $place->name . '</span>';
173
+ echo $this->grw_anchor($place->url, '', $place_name_content, true, true); ?>
174
+ </div>
175
+ <div>
176
+ <span class="wp-google-rating"><?php echo $rating; ?></span>
177
+ <span class="wp-google-stars"><?php $this->grw_stars($rating); ?></span>
178
+ </div>
179
+ <?php if (!$hide_based_on && isset($place->review_count)) { ?>
180
+ <div class="wp-google-powered"><?php echo vsprintf(__('Based on %s reviews', 'grw'), $this->grw_array($place->review_count)); ?></div>
181
+ <?php } ?>
182
+ <?php if ($show_powered) { ?>
183
+ <div class="wp-google-powered">
184
+ <img src="<?php echo GRW_ASSETS_URL; ?>/img/powered_by_google_on_<?php if ($dark_theme) { ?>non_<?php } ?>white.png" alt="powered by Google" width="144" height="18" title="powered by Google">
185
+ </div>
186
+ <?php } ?>
187
+ </div>
188
+ <?php
189
+ }
190
+
191
+ function grw_place_reviews($place, $reviews, $place_id, $text_size, $pagination, $reviewer_avatar_size, $open_link, $nofollow_link, $lazy_load_img, $google_def_rev_link, $is_admin = false) {
192
+ ?>
193
+ <div class="wp-google-reviews">
194
+ <?php
195
+ $hr = false;
196
+ if (count($reviews) > 0) {
197
+ $i = 0;
198
+ foreach ($reviews as $review) {
199
+ if ($pagination > 0 && $pagination <= $i++) {
200
+ $hr = true;
201
+ }
202
+ ?>
203
+ <div class="wp-google-review<?php if ($hr) { echo ' wp-google-hide'; } if ($is_admin && $review->hide != '') { echo ' wp-review-hidden'; } ?>">
204
+ <div class="wp-google-left">
205
+ <?php
206
+ $default_avatar = GRW_GOOGLE_AVATAR;
207
+ if (strlen($review->author_avatar) > 0) {
208
+ $author_avatar = $review->author_avatar;
209
+ } else {
210
+ $author_avatar = $default_avatar;
211
+ }
212
+ if (isset($reviewer_avatar_size)) {
213
+ $author_avatar = str_replace('s128', 's' . $reviewer_avatar_size, $author_avatar);
214
+ $default_avatar = str_replace('s128', 's' . $reviewer_avatar_size, $default_avatar);
215
+ }
216
+ $this->grw_image($author_avatar, $review->author_name, $lazy_load_img, $default_avatar);
217
+ ?>
218
+ </div>
219
+ <div class="wp-google-right">
220
+ <?php
221
+ if (strlen($review->author_url) > 0) {
222
+ $this->grw_anchor($review->author_url, 'wp-google-name', $review->author_name, $open_link, $nofollow_link);
223
+ } else {
224
+ if (strlen($review->author_name) > 0) {
225
+ $author_name = $review->author_name;
226
+ } else {
227
+ $author_name = __('Google User', 'grw');
228
+ }
229
+ ?><div class="wp-google-name"><?php echo $author_name; ?></div><?php
230
+ }
231
+ ?>
232
+ <div class="wp-google-time" data-time="<?php echo $review->time; ?>"><?php echo gmdate("H:i d M y", $review->time); ?></div>
233
+ <div class="wp-google-feedback">
234
+ <span class="wp-google-stars"><?php echo $this->grw_stars($review->rating); ?></span>
235
+ <span class="wp-google-text"><?php echo $this->grw_trim_text($review->text, $text_size); ?></span>
236
+ </div>
237
+ <?php if ($is_admin) {
238
+ echo '<a href="#" class="wp-review-hide" data-id=' . $review->id . '>' . ($review->hide == '' ? 'Hide' : 'Show') . ' review</a>';
239
+ } ?>
240
+ </div>
241
+ </div>
242
+ <?php
243
+ }
244
+ }
245
+ ?>
246
+ </div>
247
+ <?php if ($pagination > 0 && $hr) { ?>
248
+ <a class="wp-google-url" href="#" onclick="return rplg_next_reviews.call(this, 'google', <?php echo $pagination; ?>);">
249
+ <?php echo __('Next Reviews', 'grw'); ?>
250
+ </a>
251
+ <?php
252
+ } else {
253
+ $reviews_link = $google_def_rev_link ? $place->url : 'https://search.google.com/local/reviews?placeid=' . $place_id;
254
+ $this->grw_anchor($reviews_link, 'wp-google-url', __('See All Reviews', 'grw'), true, true);
255
+ }
256
+ }
257
+
258
+ function grw_stars($rating) {
259
+ ?><span class="wp-stars"><?php
260
+ foreach (array(1,2,3,4,5) as $val) {
261
+ $score = $rating - $val;
262
+ if ($score >= 0) {
263
+ ?><span class="wp-star"><svg width="17" height="17" viewBox="0 0 1792 1792"><path d="M1728 647q0 22-26 48l-363 354 86 500q1 7 1 20 0 21-10.5 35.5t-30.5 14.5q-19 0-40-12l-449-236-449 236q-22 12-40 12-21 0-31.5-14.5t-10.5-35.5q0-6 2-20l86-500-364-354q-25-27-25-48 0-37 56-46l502-73 225-455q19-41 49-41t49 41l225 455 502 73q56 9 56 46z" fill="#e7711b"></path></svg></span><?php
264
+ } else if ($score > -1 && $score < 0) {
265
+ ?><span class="wp-star"><svg width="17" height="17" viewBox="0 0 1792 1792"><path d="M1250 957l257-250-356-52-66-10-30-60-159-322v963l59 31 318 168-60-355-12-66zm452-262l-363 354 86 500q5 33-6 51.5t-34 18.5q-17 0-40-12l-449-236-449 236q-23 12-40 12-23 0-34-18.5t-6-51.5l86-500-364-354q-32-32-23-59.5t54-34.5l502-73 225-455q20-41 49-41 28 0 49 41l225 455 502 73q45 7 54 34.5t-24 59.5z" fill="#e7711b"></path></svg></span><?php
266
+ } else {
267
+ ?><span class="wp-star"><svg width="17" height="17" viewBox="0 0 1792 1792"><path d="M1201 1004l306-297-422-62-189-382-189 382-422 62 306 297-73 421 378-199 377 199zm527-357q0 22-26 48l-363 354 86 500q1 7 1 20 0 50-41 50-19 0-40-12l-449-236-449 236q-22 12-40 12-21 0-31.5-14.5t-10.5-35.5q0-6 2-20l86-500-364-354q-25-27-25-48 0-37 56-46l502-73 225-455q19-41 49-41t49 41l225 455 502 73q56 9 56 46z" fill="#ccc"></path></svg></span><?php
268
+ }
269
+ }
270
+ ?></span><?php
271
+ }
272
+
273
+ function grw_anchor($url, $class, $text, $open_link, $nofollow_link) {
274
+ echo '<a href="' . $url . '"' . ($class ? ' class="' . $class . '"' : '') . ($open_link ? ' target="_blank"' : '') . ' rel="' . ($nofollow_link ? 'nofollow ' : '') . 'noopener">' . $text . '</a>';
275
+ }
276
+
277
+ function grw_image($src, $alt, $lazy, $def_ava = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', $atts = '') {
278
+ ?><img <?php if ($lazy) { ?>src="<?php echo $def_ava; ?>" data-<?php } ?>src="<?php echo $src; ?>" class="rplg-review-avatar<?php if ($lazy) { ?> rplg-blazy<?php } ?>" alt="<?php echo $alt; ?>" width="50" height="50" title="<?php echo $alt; ?>" onerror="if(this.src!='<?php echo $def_ava; ?>')this.src='<?php echo $def_ava; ?>';" <?php echo $atts; ?>><?php
279
+ }
280
+
281
+ function grw_trim_text($text, $size) {
282
+ if ($size > 0 && $this->grw_strlen($text) > $size) {
283
+ $sub_text = $this->grw_substr($text, 0, $size);
284
+ $idx = $this->grw_strrpos($sub_text, ' ') + 1;
285
+
286
+ if ($idx < 1 || $size - $idx > ($size / 2)) {
287
+ $idx = $size;
288
+ }
289
+ if ($idx > 0) {
290
+ $visible_text = $this->grw_substr($text, 0, $idx - 1);
291
+ $invisible_text = $this->grw_substr($text, $idx - 1, $this->grw_strlen($text));
292
+ }
293
+ echo $visible_text;
294
+ if ($this->grw_strlen($invisible_text) > 0) {
295
+ ?><span>... </span><span class="wp-more"><?php echo $invisible_text; ?></span><span class="wp-more-toggle"><?php echo __('read more', 'grw'); ?></span><?php
296
+ }
297
+ } else {
298
+ echo $text;
299
+ }
300
+ }
301
+
302
+ function grw_strlen($str) {
303
+ return function_exists('mb_strlen') ? mb_strlen($str, 'UTF-8') : strlen($str);
304
+ }
305
+
306
+ function grw_strrpos($haystack, $needle, $offset = 0) {
307
+ return function_exists('mb_strrpos') ? mb_strrpos($haystack, $needle, $offset, 'UTF-8') : strrpos($haystack, $needle, $offset);
308
+ }
309
+
310
+ function grw_substr($str, $start, $length = NULL) {
311
+ return function_exists('mb_substr') ? mb_substr($str, $start, $length, 'UTF-8') : substr($str, $start, $length);
312
+ }
313
+
314
+ function grw_array($params=null) {
315
+ if (!is_array($params)) {
316
+ $params = func_get_args();
317
+ $params = array_slice($params, 0);
318
+ }
319
+ return $params;
320
+ }
321
+ }
includes/core/class-connect-google.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes\Core;
4
+
5
+ class Connect_Google {
6
+
7
+ public function __construct() {
8
+ add_action('init', array($this, 'request_handler'));
9
+ add_action('grw_refresh_reviews', array($this, 'grw_refresh_reviews'));
10
+ }
11
+
12
+ public function request_handler() {
13
+ global $wpdb;
14
+
15
+ if (!empty($_GET['cf_action'])) {
16
+
17
+ switch ($_GET['cf_action']) {
18
+
19
+ case 'grw_connect_google':
20
+ if (current_user_can('manage_options')) {
21
+ if (isset($_POST['grw_wpnonce']) === false) {
22
+ $error = __('Unable to call request. Make sure you are accessing this page from the Wordpress dashboard.');
23
+ $response = compact('error');
24
+ } else {
25
+ check_admin_referer('grw_wpnonce', 'grw_wpnonce');
26
+
27
+ $key = sanitize_text_field(wp_unslash($_POST['key']));
28
+ if (strlen($key) > 0) {
29
+ update_option('grw_google_api_key', $key);
30
+ }
31
+ $google_api_key = get_option('grw_google_api_key');
32
+
33
+ $id = sanitize_text_field(wp_unslash($_POST['id']));
34
+ $lang = sanitize_text_field(wp_unslash($_POST['lang']));
35
+ $url = $this->api_url($id, $google_api_key, $lang);
36
+
37
+ $res = wp_remote_get($url);
38
+ $body = wp_remote_retrieve_body($res);
39
+ $body_json = json_decode($body);
40
+
41
+ if ($body_json && isset($body_json->result)) {
42
+ $photo = $this->business_avatar($body_json->result, $google_api_key);
43
+ $body_json->result->business_photo = $photo;
44
+
45
+ $this->save_reviews($body_json->result);
46
+
47
+ $result = array(
48
+ 'id' => $body_json->result->place_id,
49
+ 'name' => $body_json->result->name,
50
+ 'photo' => strlen($photo) ? $photo : $body_json->result->icon,
51
+ 'reviews' => $body_json->result->reviews
52
+ );
53
+ $status = 'success';
54
+ } else {
55
+ $result = $body_json;
56
+ $status = 'failed';
57
+ }
58
+ $response = compact('status', 'result');
59
+ }
60
+ header('Content-type: text/javascript');
61
+ echo json_encode($response);
62
+ die();
63
+ }
64
+ break;
65
+
66
+ case 'grw_hide_review':
67
+ if (current_user_can('manage_options')) {
68
+ if (isset($_POST['grw_wpnonce']) === false) {
69
+ $error = __('Unable to call request. Make sure you are accessing this page from the Wordpress dashboard.', 'grw');
70
+ $response = compact('error');
71
+ } else {
72
+ check_admin_referer('grw_wpnonce', 'grw_wpnonce');
73
+
74
+ $review = $wpdb->get_row(
75
+ $wpdb->prepare(
76
+ "SELECT * FROM " . $wpdb->prefix . Database::REVIEW_TABLE .
77
+ " WHERE id = %d", $_POST['id']
78
+ )
79
+ );
80
+ $hide = $review->hide == '' ? 'y' : '';
81
+ $wpdb->update($wpdb->prefix . Database::REVIEW_TABLE, array('hide' => $hide), array('id' => $_POST['id']));
82
+ delete_transient('grw_feed_' . GRW_VERSION . '_' . $_POST['feed_id'] . '_reviews', false);
83
+ $response = array('hide' => $hide);
84
+ }
85
+ header('Content-type: text/javascript');
86
+ echo json_encode($response);
87
+ die();
88
+ }
89
+ break;
90
+
91
+ }
92
+ }
93
+ }
94
+
95
+ function grw_refresh_reviews($args) {
96
+ $google_api_key = get_option('grw_google_api_key');
97
+ if (!$google_api_key) {
98
+ return;
99
+ }
100
+
101
+ $place_id = $args[0];
102
+ $reviews_lang = $args[1];
103
+
104
+ $url = $this->api_url($place_id, $google_api_key, $reviews_lang);
105
+
106
+ $res = wp_remote_get($url);
107
+ $body = wp_remote_retrieve_body($res);
108
+ $body_json = json_decode($body);
109
+
110
+ if ($body_json && isset($body_json->result)) {
111
+ $photo = $this->business_avatar($body_json->result, $google_api_key);
112
+ $body_json->result->business_photo = $photo;
113
+
114
+ $this->save_reviews($body_json->result);
115
+ }
116
+
117
+ delete_transient('grw_refresh_reviews_' . join('_', $args));
118
+ }
119
+
120
+ function save_reviews($place) {
121
+ global $wpdb;
122
+
123
+ $google_place_id = $wpdb->get_var(
124
+ $wpdb->prepare(
125
+ "SELECT id FROM " . $wpdb->prefix . Database::BUSINESS_TABLE .
126
+ " WHERE place_id = %s", $place->place_id
127
+ )
128
+ );
129
+
130
+ if ($google_place_id) {
131
+
132
+ $update_params = array(
133
+ 'name' => $place->name,
134
+ 'rating' => $place->rating,
135
+ );
136
+ if (isset($place->user_ratings_total)) {
137
+ $update_params['review_count'] = $place->user_ratings_total;
138
+ }
139
+ if (isset($place->business_photo) && strlen($place->business_photo) > 0) {
140
+ $update_params['photo'] = $place->business_photo;
141
+ }
142
+ $wpdb->update($wpdb->prefix . Database::BUSINESS_TABLE, $update_params, array('ID' => $google_place_id));
143
+
144
+ } else {
145
+
146
+ $wpdb->insert($wpdb->prefix . Database::BUSINESS_TABLE, array(
147
+ 'place_id' => $place->place_id,
148
+ 'name' => $place->name,
149
+ 'photo' => $place->business_photo,
150
+ 'icon' => $place->icon,
151
+ 'address' => $place->formatted_address,
152
+ 'rating' => isset($place->rating) ? $place->rating : null,
153
+ 'url' => isset($place->url) ? $place->url : null,
154
+ 'website' => isset($place->website) ? $place->website : null,
155
+ 'review_count' => isset($place->user_ratings_total) ?
156
+ $place->user_ratings_total : (isset($place->reviews) ? count($place->reviews) : null)
157
+ ));
158
+ $google_place_id = $wpdb->insert_id;
159
+ }
160
+
161
+ if ($place->reviews) {
162
+
163
+ $reviews = $place->reviews;
164
+
165
+ foreach ($reviews as $review) {
166
+ $google_review_id = 0;
167
+ if (isset($review->author_url) && strlen($review->author_url) > 0) {
168
+ $google_review_id = $wpdb->get_var(
169
+ $wpdb->prepare(
170
+ "SELECT id FROM " . $wpdb->prefix . Database::REVIEW_TABLE .
171
+ " WHERE author_url = %s", $review->author_url
172
+ )
173
+ );
174
+ } else {
175
+ $google_review_id = $wpdb->get_var(
176
+ $wpdb->prepare(
177
+ "SELECT id FROM " . $wpdb->prefix . Database::REVIEW_TABLE .
178
+ " WHERE time = %s", $review->time
179
+ )
180
+ );
181
+ }
182
+
183
+ if ($google_review_id) {
184
+ $update_params = array(
185
+ 'rating' => $review->rating,
186
+ 'text' => $review->text
187
+ );
188
+ if (isset($review->profile_photo_url)) {
189
+ $update_params['profile_photo_url'] = $review->profile_photo_url;
190
+ }
191
+ $wpdb->update($wpdb->prefix . Database::REVIEW_TABLE, $update_params, array('id' => $google_review_id));
192
+ } else {
193
+ $wpdb->insert($wpdb->prefix . Database::REVIEW_TABLE, array(
194
+ 'google_place_id' => $google_place_id,
195
+ 'hash' => $review->time, //TODO: workaround to support old versions
196
+ 'rating' => $review->rating,
197
+ 'text' => $review->text,
198
+ 'time' => $review->time,
199
+ 'language' => $review->language,
200
+ 'author_name' => $review->author_name,
201
+ 'author_url' => isset($review->author_url) ? $review->author_url : null,
202
+ 'profile_photo_url' => isset($review->profile_photo_url) ? $review->profile_photo_url : null
203
+ ));
204
+ }
205
+ }
206
+ }
207
+ }
208
+
209
+ function api_url($placeid, $google_api_key, $reviews_lang = '') {
210
+ $url = GRW_GOOGLE_PLACE_API . 'details/json?placeid=' . $placeid . '&key=' . $google_api_key;
211
+ if (strlen($reviews_lang) > 0) {
212
+ $url = $url . '&language=' . $reviews_lang;
213
+ }
214
+ return $url;
215
+ }
216
+
217
+ function business_avatar($response_result_json, $google_api_key) {
218
+ if (isset($response_result_json->photos)) {
219
+ $url = add_query_arg(
220
+ array(
221
+ 'photoreference' => $response_result_json->photos[0]->photo_reference,
222
+ 'key' => $google_api_key,
223
+ 'maxwidth' => '300',
224
+ 'maxheight' => '300',
225
+ ),
226
+ 'https://maps.googleapis.com/maps/api/place/photo'
227
+ );
228
+ $res = wp_remote_get($url, array('timeout' => 8));
229
+ if(!is_wp_error($res)) {
230
+ $bits = wp_remote_retrieve_body($res);
231
+ $filename = $response_result_json->place_id . '.jpg';
232
+ $upload = wp_upload_bits($filename, null, $bits);
233
+ return $upload['url'];
234
+ }
235
+ }
236
+ return null;
237
+ }
238
+
239
+ }
includes/core/class-core.php ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes\Core;
4
+
5
+ class Core {
6
+
7
+ public function __construct() {
8
+ }
9
+
10
+ public static function get_default_options() {
11
+ return array(
12
+ 'view_mode' => 'list',
13
+ 'pagination' => '10',
14
+ 'text_size' => '',
15
+ 'disable_user_link' => false,
16
+ 'hide_based_on' => false,
17
+ 'hide_reviews' => false,
18
+
19
+ 'header_merge_social' => false,
20
+ 'header_hide_social' => false,
21
+
22
+ 'dark_theme' => false,
23
+ 'centered' => false,
24
+ 'max_width' => '',
25
+ 'max_height' => '',
26
+
27
+ 'open_link' => true,
28
+ 'nofollow_link' => true,
29
+ 'lazy_load_img' => true,
30
+ 'google_def_rev_link' => false,
31
+ 'reviewer_avatar_size' => 56,
32
+ 'reviews_limit' => '',
33
+ 'cache' => 12,
34
+ );
35
+ }
36
+
37
+ public function get_reviews($feed, $is_admin = false) {
38
+ $connection = json_decode($feed->post_content);
39
+
40
+ if ($is_admin) {
41
+ return $this->get_data($connection, $is_admin);
42
+ }
43
+
44
+ $cache_time = isset($connection->options->cache) ? $connection->options->cache : null;
45
+ $data_cache_key = 'grw_feed_' . GRW_VERSION . '_' . $feed->ID . '_reviews';
46
+ $connection_cache_key = 'grw_feed_' . GRW_VERSION . '_' . $feed->ID . '_options';
47
+
48
+ $data = get_transient($data_cache_key);
49
+ $cached_connection = get_transient($connection_cache_key);
50
+ $serialized_connection = serialize($connection);
51
+
52
+ if ($data === false || $serialized_connection !== $cached_connection || !$cache_time) {
53
+ $expiration = $cache_time;
54
+ switch ($expiration) {
55
+ case '1':
56
+ $expiration = 3600;
57
+ break;
58
+ case '3':
59
+ $expiration = 3600 * 3;
60
+ break;
61
+ case '6':
62
+ $expiration = 3600 * 6;
63
+ break;
64
+ case '12':
65
+ $expiration = 3600 * 12;
66
+ break;
67
+ case '24':
68
+ $expiration = 3600 * 24;
69
+ break;
70
+ case '48':
71
+ $expiration = 3600 * 48;
72
+ break;
73
+ case '168':
74
+ $expiration = 3600 * 168;
75
+ break;
76
+ default:
77
+ $expiration = 3600 * 24;
78
+ }
79
+ $data = $this->get_data($connection, $is_admin);
80
+ set_transient($data_cache_key, $data, $expiration);
81
+ set_transient($connection_cache_key, $serialized_connection, $expiration);
82
+ }
83
+ return $data;
84
+ }
85
+
86
+ public function get_data($connection, $is_admin = false) {
87
+
88
+ if ($connection == null) {
89
+ return null;
90
+ }
91
+
92
+ foreach ($this->get_default_options() as $field => $value) {
93
+ $connection->options->{$field} = isset($connection->options->{$field}) ? esc_attr($connection->options->{$field}) : $value;
94
+ }
95
+ $options = $connection->options;
96
+
97
+ if (isset($connection->connections) && is_array($connection->connections)) {
98
+ $google_business = null;
99
+ foreach ($connection->connections as $conn) {
100
+ switch ($conn->platform) {
101
+ case 'google':
102
+ if (!$google_business) $google_business = array();
103
+ array_push($google_business, $conn);
104
+ break;
105
+ }
106
+ }
107
+ } else {
108
+ $google_business = isset($connection->google) ? $connection->google : null;
109
+ }
110
+
111
+ $google_biz = array();
112
+ $google_reviews = array();
113
+
114
+ if ($google_business != null) {
115
+
116
+ $schedule_step = 60 * 60 * 12;
117
+
118
+ foreach ($google_business as $biz) {
119
+
120
+ $result = $this->get_google_reviews($biz, $is_admin);
121
+ array_push($google_biz, $result['business']);
122
+ $google_reviews = array_merge($google_reviews, $result['reviews']);
123
+
124
+ if (isset($biz->refresh) && $biz->refresh) {
125
+ $args = array($biz->id);
126
+ if (isset($biz->lang) && strlen($biz->lang) > 0) {
127
+ array_push($args, $biz->lang);
128
+ }
129
+ $schedule_cache_key = 'grw_refresh_reviews_' . join('_', $args);
130
+ if (get_transient($schedule_cache_key) === false) {
131
+ wp_schedule_single_event(time() + $schedule_step, 'grw_refresh_reviews', array($args));
132
+ set_transient($schedule_cache_key, $schedule_cache_key, $schedule_step + 60 * 10);
133
+ }
134
+ }
135
+ $schedule_step = $schedule_step + 60 * 60 * 12;
136
+ }
137
+ }
138
+
139
+ $social_biz = array();
140
+ if ($options->header_merge_social) {
141
+ if (count($google_biz) > 0) {
142
+ array_push($social_biz, $this->merge_biz($google_biz));
143
+ }
144
+ } else {
145
+ $social_biz = array_merge($google_biz);
146
+ }
147
+
148
+ $businesses = array();
149
+ if (!$options->header_hide_social) {
150
+ $businesses = $social_biz;
151
+ }
152
+
153
+ $reviews = array();
154
+ if (!$options->hide_reviews) {
155
+
156
+ $revs = array();
157
+ if (count($google_reviews) > 0) {
158
+ array_push($revs, $google_reviews);
159
+ }
160
+
161
+ // Sorting
162
+ while (count($revs) > 0) {
163
+ foreach ($revs as $i => $value) {
164
+ $review = array_shift($revs[$i]);
165
+ array_push($reviews, $review);
166
+ if (count($revs[$i]) < 1) {
167
+ unset($revs[$i]);
168
+ }
169
+ }
170
+ }
171
+
172
+ // Normalize reviews array indexes after unset filter above
173
+ $reviews = array_values($reviews);
174
+
175
+ // Trim reviews limit
176
+ if ($options->reviews_limit > 0) {
177
+ $reviews = array_slice($google_reviews, 0, $options->reviews_limit);
178
+ }
179
+ }
180
+
181
+ return array('businesses' => $businesses, 'reviews' => $reviews, 'options' => $options);
182
+ }
183
+
184
+ public function get_google_reviews($google_biz, $is_admin = false) {
185
+ global $wpdb;
186
+
187
+ // Get Google place
188
+ $place = $wpdb->get_row(
189
+ $wpdb->prepare(
190
+ "SELECT * FROM " . $wpdb->prefix . Database::BUSINESS_TABLE .
191
+ " WHERE place_id = %s", $google_biz->id
192
+ )
193
+ );
194
+
195
+ // Get Google reviews
196
+ $reviews_where = $is_admin ? '' : ' AND hide = \'\'';
197
+ if (strlen($google_biz->lang) > 0) {
198
+ $reviews_where = $reviews_where . ' AND language = \'' . $google_biz->lang . '\'';
199
+ }
200
+ $reviews = $wpdb->get_results(
201
+ $wpdb->prepare(
202
+ "SELECT * FROM " . $wpdb->prefix . Database::REVIEW_TABLE .
203
+ " WHERE google_place_id = %d" . $reviews_where . " ORDER BY time DESC", $place->id
204
+ )
205
+ );
206
+
207
+ // Setup Google photo
208
+ $place->photo = strlen($google_biz->photo) > 0 ? $google_biz->photo : (strlen($place->photo) > 0 ? $place->photo : $place->icon);
209
+
210
+ // Calculate Google reviews count
211
+ if (isset($place->review_count) && $place->review_count > 0) {
212
+ $review_count = $place->review_count;
213
+ } else {
214
+ $review_count = $wpdb->get_var(
215
+ $wpdb->prepare(
216
+ "SELECT count(*) FROM " . $wpdb->prefix . Database::REVIEW_TABLE .
217
+ " WHERE business_id = %d", $place->id
218
+ )
219
+ );
220
+ }
221
+
222
+ // Calculate Google rating
223
+ $rating = 0;
224
+ if ($place->rating > 0) {
225
+ $rating = $place->rating;
226
+ } else if (count($reviews) > 0) {
227
+ foreach ($reviews as $review) {
228
+ $rating = $rating + $review->rating;
229
+ }
230
+ $rating = round($rating / count($reviews), 1);
231
+ }
232
+ $rating = number_format((float)$rating, 1, '.', '');
233
+
234
+ $business = json_decode(json_encode(
235
+ array(
236
+ 'id' => $google_biz->id,
237
+ 'name' => $google_biz->name ? $google_biz->name : $place->name,
238
+ 'url' => $place->url,
239
+ 'photo' => $place->photo,
240
+ 'address' => $place->address,
241
+ 'rating' => $rating,
242
+ 'review_count' => $review_count,
243
+ 'provider' => 'google'
244
+ )
245
+ ));
246
+
247
+ $google_reviews = array();
248
+ foreach ($reviews as $rev) {
249
+ $review = json_decode(json_encode(
250
+ array(
251
+ 'id' => $rev->id,
252
+ 'hide' => $rev->hide,
253
+ 'biz_id' => $google_biz->id,
254
+ 'rating' => $rev->rating,
255
+ 'text' => wp_encode_emoji($rev->text),
256
+ 'author_avatar' => $rev->profile_photo_url,
257
+ 'author_url' => $rev->author_url,
258
+ 'author_name' => $rev->author_name,
259
+ 'time' => $rev->time,
260
+ 'provider' => 'google',
261
+ )
262
+ ));
263
+ array_push($google_reviews, $review);
264
+ }
265
+
266
+ return array('business' => $business, 'reviews' => $google_reviews);
267
+ }
268
+
269
+ private function merge_biz($businesses, $id = '', $name = '', $url = '', $photo = '', $provider = '') {
270
+ $count = 0;
271
+ $rating = 0;
272
+ $review_count = array();
273
+ $review_count_manual = array();
274
+ $business_platform = array();
275
+ $biz_merge = null;
276
+ foreach ($businesses as $business) {
277
+ if ($business->rating < 1) {
278
+ continue;
279
+ }
280
+
281
+ $count++;
282
+ $rating += $business->rating;
283
+
284
+ if (isset($business->review_count_manual) && $business->review_count_manual > 0) {
285
+ $review_count_manual[$business->id] = $business->review_count_manual;
286
+ } else {
287
+ $review_count[$business->id] = $business->review_count;
288
+ }
289
+
290
+ array_push($business_platform, $business->provider);
291
+
292
+ if ($biz_merge == null) {
293
+ $biz_merge = json_decode(json_encode(
294
+ array(
295
+ 'id' => strlen($id) > 0 ? $id : $business->id,
296
+ 'name' => strlen($name) > 0 ? $name : $business->name,
297
+ 'url' => strlen($url) > 0 ? $url : $business->url,
298
+ 'photo' => strlen($photo) > 0 ? $photo : $business->photo,
299
+ 'provider' => strlen($provider) > 0 ? $provider : $business->provider,
300
+ 'review_count' => 0,
301
+ )
302
+ ));
303
+ }
304
+ $rating_tmp = round($rating / $count, 1);
305
+ $rating_tmp = number_format((float)$rating_tmp, 1, '.', '');
306
+ $biz_merge->rating = $rating_tmp;
307
+ }
308
+ $review_count = array_merge($review_count, $review_count_manual);
309
+ foreach ($review_count as $id => $count) {
310
+ $biz_merge->review_count += $count;
311
+ }
312
+ $biz_merge->platform = array_unique($business_platform);
313
+ return $biz_merge;
314
+ }
315
+
316
+ }
includes/core/class-database.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WP_Rplg_Google_Reviews\Includes\Core;
4
+
5
+ class Database {
6
+
7
+ const BUSINESS_TABLE = 'grp_google_place';
8
+
9
+ const REVIEW_TABLE = 'grp_google_review';
10
+
11
+ public function create() {
12
+ global $wpdb;
13
+
14
+ $charset_collate = $wpdb->get_charset_collate();
15
+
16
+ $sql = "CREATE TABLE IF NOT EXISTS " . $wpdb->prefix . "grp_google_place (".
17
+ "id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,".
18
+ "place_id VARCHAR(80) NOT NULL,".
19
+ "name VARCHAR(255) NOT NULL,".
20
+ "photo VARCHAR(255),".
21
+ "icon VARCHAR(255),".
22
+ "address VARCHAR(255),".
23
+ "rating DOUBLE PRECISION,".
24
+ "url VARCHAR(255),".
25
+ "website VARCHAR(255),".
26
+ "review_count INTEGER,".
27
+ "updated BIGINT(20),".
28
+ "PRIMARY KEY (`id`),".
29
+ "UNIQUE INDEX grp_place_id (`place_id`)".
30
+ ") " . $charset_collate . ";";
31
+
32
+ require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
33
+
34
+ dbDelta($sql);
35
+
36
+ $sql = "CREATE TABLE IF NOT EXISTS " . $wpdb->prefix . "grp_google_review (".
37
+ "id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,".
38
+ "google_place_id BIGINT(20) UNSIGNED NOT NULL,".
39
+ "hash VARCHAR(40) NOT NULL,".
40
+ "rating INTEGER NOT NULL,".
41
+ "text VARCHAR(10000),".
42
+ "time INTEGER NOT NULL,".
43
+ "language VARCHAR(10),".
44
+ "author_name VARCHAR(255),".
45
+ "author_url VARCHAR(255),".
46
+ "profile_photo_url VARCHAR(255),".
47
+ "hide VARCHAR(1) DEFAULT '' NOT NULL,".
48
+ "PRIMARY KEY (`id`),".
49
+ "UNIQUE INDEX grp_google_review_hash (`hash`),".
50
+ "INDEX grp_google_place_id (`google_place_id`)".
51
+ ") " . $charset_collate . ";";
52
+
53
+ dbDelta($sql);
54
+ }
55
+
56
+ public function drop() {
57
+ global $wpdb;
58
+
59
+ $wpdb->query("DROP TABLE " . $wpdb->prefix . self::BUSINESS_TABLE . ";");
60
+ $wpdb->query("DROP TABLE " . $wpdb->prefix . self::REVIEW_TABLE . ";");
61
+ }
62
+
63
+ }
includes/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php
grw-setting-fig.php → includes/page-setting-fig.php RENAMED
@@ -1,6 +1,6 @@
1
  <p>To correctly use this plugin you need to get two things - <b><u>Google Place ID</u></b> and <b><u>Google Places API key</u></b>. These are two different values, please do not confuse them.</p>
2
 
3
- <p style="background: #eee; padding: 4px 10px; border-radius: 4px; border: 1px solid #ccc; font-size: 16px; text-align: center; line-height: 32px;">There is nothing complicated and the whole process will not take even 5 minutes,<br>and as a reward you receive a constantly updated your connected Google Rating and Reviews!</p>
4
 
5
  <hr></hr>
6
 
@@ -17,7 +17,7 @@
17
  <b>1</b> Search for your business on Google.
18
  </div>
19
  <div class="rplg-flex-col7">
20
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_placeid_1.png'; ?>"></div>
21
  </div>
22
  </div>
23
 
@@ -26,7 +26,7 @@
26
  <b>2</b> Inspect the “<b>Write a Review</b>” button. To do this in Firefox, right-click and choose “<b>Inspect Element</b>“. In Chrome, right-click and choose “<b>Inspect</b>“. (Most browsers follow a similar process.)
27
  </div>
28
  <div class="rplg-flex-col7">
29
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_placeid_2.png'; ?>"></div>
30
  </div>
31
  </div>
32
 
@@ -35,7 +35,7 @@
35
  <b>3</b> Find “<b>data-pid</b>” as shown above. (This part is a little tricky, but just look inside the <b>&lt;a&gt;</b> tag until you find <b>data-pid=</b>).
36
  </div>
37
  <div class="rplg-flex-col7">
38
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_placeid_3.png'; ?>"></div>
39
  </div>
40
  </div>
41
 
@@ -54,7 +54,7 @@
54
  <b>1</b> Go to your <a href="https://console.developers.google.com/apis/dashboard?pli=1" target="_blank">Google Console</a> dashboard. If you new user agree Google terms:
55
  </div>
56
  <div class="rplg-flex-col">
57
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_key_1.png'; ?>"></div>
58
  </div>
59
  </div>
60
 
@@ -63,8 +63,8 @@
63
  <b>2</b> Select your existing project or create new:
64
  </div>
65
  <div class="rplg-flex-col">
66
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_key_2.png'; ?>"></div>
67
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_key_2_1.png'; ?>"></div>
68
  </div>
69
  </div>
70
 
@@ -73,7 +73,7 @@
73
  <b>3</b> Wait for creation and then click '<b>ENABLE APIS AND SERVICES</b>':
74
  </div>
75
  <div class="rplg-flex-col">
76
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_key_3.png'; ?>"></div>
77
  </div>
78
  </div>
79
 
@@ -82,8 +82,8 @@
82
  <b>4</b> Type '<b>Places API</b>' in the search area, select the first result '<b>Places API</b>' and click '<b>ENABLE</b>' button:
83
  </div>
84
  <div class="rplg-flex-col">
85
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_key_4.png'; ?>"></div>
86
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_key_4_1.png'; ?>"></div>
87
  </div>
88
  </div>
89
 
@@ -92,7 +92,7 @@
92
  <b>5</b> After enable the Places API, click '<b>Navigation menu</b>', select '<b>APIs & Services</b>' and '<b>Credentials</b>':
93
  </div>
94
  <div class="rplg-flex-col">
95
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_key_5.png'; ?>"></div>
96
  </div>
97
  </div>
98
 
@@ -101,7 +101,7 @@
101
  <b>6</b> On Credentials page click '<b>+ CREATE CREDENTIALS</b>' and select '<b>API key</b>':
102
  </div>
103
  <div class="rplg-flex-col">
104
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_key_6.png'; ?>"></div>
105
  </div>
106
  </div>
107
 
@@ -110,7 +110,7 @@
110
  <b>7</b> After creation of API key you need to copy & paste it to the plugin's settings (<b>please do not restrict the key</b>, the plugin can't work with a restricted API key, it's a limitation of Google):
111
  </div>
112
  <div class="rplg-flex-col">
113
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_key_7.png'; ?>"></div>
114
  </div>
115
  </div>
116
 
@@ -119,7 +119,7 @@
119
  <b>8</b> Now, you need to enable Google Billing. It's mandatory step to use the API key. <b>Don’t worry, <a href="https://developers.google.com/maps/billing-credits" target="_blank">Google is currently giving $200 free credit a month</b></a> and it should be enough to use the plugin for connecting several Google places without additional fees except this free $200 credits. Go to <a href="https://console.cloud.google.com/project/_/billing/enable" target="_blank">https://console.cloud.google.com/project/_/billing/enable</a>, select your recent created project and click '<b>CREATE BILLING ACCOUNT</b>':
120
  </div>
121
  <div class="rplg-flex-col">
122
- <div class="box-img"><img src="<?php echo GRW_PLUGIN_URL . '/static/img/google_key_8.png'; ?>"></div>
123
  </div>
124
  </div>
125
 
@@ -129,4 +129,4 @@
129
  </div>
130
  </div>
131
 
132
- <p style="text-align:center"><b>Congratulation! Now you can connect and show your Google reviews through <a href="<?php echo admin_url('widgets.php'); ?>" target="_blank">Widget on a sidebar</a> or <a href="<?php echo admin_url('options-general.php?page=grw&grw_tab=shortcode'); ?>" target="_blank">Shortcode</a> on the any page of your website.</b></p>
1
  <p>To correctly use this plugin you need to get two things - <b><u>Google Place ID</u></b> and <b><u>Google Places API key</u></b>. These are two different values, please do not confuse them.</p>
2
 
3
+ <p style="background: #eee; padding: 4px 10px; border-radius: 4px; border: 1px solid #ccc; font-size: 16px; font-weight: 600; text-align: center; line-height: 32px;">There is nothing complicated and the whole process will not take even 5 minutes,<br>and as a reward you receive a constantly updated and collected Google Rating and Reviews!</p>
4
 
5
  <hr></hr>
6
 
17
  <b>1</b> Search for your business on Google.
18
  </div>
19
  <div class="rplg-flex-col7">
20
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_placeid_1.png'; ?>"></div>
21
  </div>
22
  </div>
23
 
26
  <b>2</b> Inspect the “<b>Write a Review</b>” button. To do this in Firefox, right-click and choose “<b>Inspect Element</b>“. In Chrome, right-click and choose “<b>Inspect</b>“. (Most browsers follow a similar process.)
27
  </div>
28
  <div class="rplg-flex-col7">
29
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_placeid_2.png'; ?>"></div>
30
  </div>
31
  </div>
32
 
35
  <b>3</b> Find “<b>data-pid</b>” as shown above. (This part is a little tricky, but just look inside the <b>&lt;a&gt;</b> tag until you find <b>data-pid=</b>).
36
  </div>
37
  <div class="rplg-flex-col7">
38
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_placeid_3.png'; ?>"></div>
39
  </div>
40
  </div>
41
 
54
  <b>1</b> Go to your <a href="https://console.developers.google.com/apis/dashboard?pli=1" target="_blank">Google Console</a> dashboard. If you new user agree Google terms:
55
  </div>
56
  <div class="rplg-flex-col">
57
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_key_1.png'; ?>"></div>
58
  </div>
59
  </div>
60
 
63
  <b>2</b> Select your existing project or create new:
64
  </div>
65
  <div class="rplg-flex-col">
66
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_key_2.png'; ?>"></div>
67
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_key_2_1.png'; ?>"></div>
68
  </div>
69
  </div>
70
 
73
  <b>3</b> Wait for creation and then click '<b>ENABLE APIS AND SERVICES</b>':
74
  </div>
75
  <div class="rplg-flex-col">
76
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_key_3.png'; ?>"></div>
77
  </div>
78
  </div>
79
 
82
  <b>4</b> Type '<b>Places API</b>' in the search area, select the first result '<b>Places API</b>' and click '<b>ENABLE</b>' button:
83
  </div>
84
  <div class="rplg-flex-col">
85
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_key_4.png'; ?>"></div>
86
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_key_4_1.png'; ?>"></div>
87
  </div>
88
  </div>
89
 
92
  <b>5</b> After enable the Places API, click '<b>Navigation menu</b>', select '<b>APIs & Services</b>' and '<b>Credentials</b>':
93
  </div>
94
  <div class="rplg-flex-col">
95
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_key_5.png'; ?>"></div>
96
  </div>
97
  </div>
98
 
101
  <b>6</b> On Credentials page click '<b>+ CREATE CREDENTIALS</b>' and select '<b>API key</b>':
102
  </div>
103
  <div class="rplg-flex-col">
104
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_key_6.png'; ?>"></div>
105
  </div>
106
  </div>
107
 
110
  <b>7</b> After creation of API key you need to copy & paste it to the plugin's settings (<b>please do not restrict the key</b>, the plugin can't work with a restricted API key, it's a limitation of Google):
111
  </div>
112
  <div class="rplg-flex-col">
113
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_key_7.png'; ?>"></div>
114
  </div>
115
  </div>
116
 
119
  <b>8</b> Now, you need to enable Google Billing. It's mandatory step to use the API key. <b>Don’t worry, <a href="https://developers.google.com/maps/billing-credits" target="_blank">Google is currently giving $200 free credit a month</b></a> and it should be enough to use the plugin for connecting several Google places without additional fees except this free $200 credits. Go to <a href="https://console.cloud.google.com/project/_/billing/enable" target="_blank">https://console.cloud.google.com/project/_/billing/enable</a>, select your recent created project and click '<b>CREATE BILLING ACCOUNT</b>':
120
  </div>
121
  <div class="rplg-flex-col">
122
+ <div class="box-img"><img src="<?php echo GRW_ASSETS_URL . 'img/google_key_8.png'; ?>"></div>
123
  </div>
124
  </div>
125
 
129
  </div>
130
  </div>
131
 
132
+ <p style="text-align:center"><b>Congratulation! Now you need to <a href="<?php echo admin_url('admin.php?page=grw-builder'); ?>" target="_blank">create your first widget and connect Google reviews</a>,<br>then you can show this widget in a sidebar or like a shortcode on the any page of your website.</b></p>
grw-setting-support.php → includes/page-setting-support.php RENAMED
@@ -2,7 +2,7 @@
2
  <div class="rplg-flex-col">
3
  <div class="rplg-support-question">
4
  <h3>I can't connect my Google Place.</h3>
5
- <p>Please check that you correctly found the Place ID of your Google business. It should look like <b>ChIJ</b>3TH9CwFZwokRI... This instruction helps to find any Place ID regardless of whether it has a physical address or it is an area: <a href="<?php echo admin_url('options-general.php?page=grw&grw_tab=fig'); ?>" target="_blank">how to find Place ID of any Google business</a></p>
6
  </div>
7
  </div>
8
  <div class="rplg-flex-col">
2
  <div class="rplg-flex-col">
3
  <div class="rplg-support-question">
4
  <h3>I can't connect my Google Place.</h3>
5
+ <p>Please check that you correctly found the Place ID of your Google business. It should look like <b>ChIJ</b>3TH9CwFZwokRI... This instruction helps to find any Place ID regardless of whether it has a physical address or it is an area: <a href="<?php echo admin_url('admin.php?page=grw-support&grw_tab=fig#place_id'); ?>">how to find Place ID of any Google business</a></p>
6
  </div>
7
  </div>
8
  <div class="rplg-flex-col">
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://richplugins.com/business-reviews-bundle-wordpress-plugin
4
  Tags: google reviews, google, reviews, rating, widget, google business, testimonials, google places reviews, map reviews
5
  Requires at least: 2.8
6
  Tested up to: 5.8
7
- Stable tag: 1.9.9
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -16,7 +16,7 @@ Widget and shortcode for Google reviews! Shows Google reviews on your WordPress
16
 
17
  This plugin display Google Business Reviews on your websites in sidebar widget. A unique feature of the plugin is that it saves reviews in WordPress database and have no depend on any services like Google to show reviews in the widget.
18
 
19
- [youtube https://www.youtube.com/watch?v=KhcDgjxYrNs]
20
 
21
  [Online demo](https://richplugins.com/demos/)
22
 
@@ -83,6 +83,13 @@ Why limit your reviews to just Google Reviews? Check out our other free reviews
83
 
84
  == Changelog ==
85
 
 
 
 
 
 
 
 
86
  = 1.9.9 =
87
  * Bugfix: PHP 8 problem (vsprintf(): Argument #2 ($values) must be of type array)
88
 
4
  Tags: google reviews, google, reviews, rating, widget, google business, testimonials, google places reviews, map reviews
5
  Requires at least: 2.8
6
  Tested up to: 5.8
7
+ Stable tag: 2.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
16
 
17
  This plugin display Google Business Reviews on your websites in sidebar widget. A unique feature of the plugin is that it saves reviews in WordPress database and have no depend on any services like Google to show reviews in the widget.
18
 
19
+ [youtube https://www.youtube.com/watch?v=Wbst-UBgXXk]
20
 
21
  [Online demo](https://richplugins.com/demos/)
22
 
83
 
84
  == Changelog ==
85
 
86
+ = 2.0 =
87
+ * Plugin keeps the widgets and shortcodes
88
+ * Reviews feed builder
89
+ * Separate menu in wp-admin
90
+ * Fully architecture redesign
91
+ * Bug fixes
92
+
93
  = 1.9.9 =
94
  * Bugfix: PHP 8 problem (vsprintf(): Argument #2 ($values) must be of type array)
95